Assembly project based on MCUXPresso tools for MCXN family

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

Assembly project based on MCUXPresso tools for MCXN family

Assembly project based on MCUXPresso tools for MCXN family

In most cases, C project is generated and used. But assembly project has it’s own advantage, with assembly project, you can program with assembly language directly, can test assembly instruction with assembly mnemonic. Generally, C language is inefficient, so in order to test the performance of the core, or get peripheral highest performance, the assembly project is required.

The doc discusses the procedure to create an assembly language project, in the end, gives an example to toggle a LED, which demos how to initialize the NVIC, CTimer, GPIO with assembly language. It also gives the example of subroutine.

 

1. The procedure to create an assembly language project based on MCUXPresso tools

1.1 Load MCUXPresso tools and drag SDK to the Installed SDK menu

Then click “Create a new C/C++ project”

xiangjun_rong_0-1731589149867.png

 

1.2 Select the board or processor, then clock “Next” software button

xiangjun_rong_1-1731589305914.png

 

1.3 Name the project and Select the driver.

In the menu, it is okay to use default configuration, then clock “Finish”

xiangjun_rong_2-1731589334564.png

 

1.4 A New project called MCXN947_project is created with C language

xiangjun_rong_3-1731589357474.png

 

1.5 Delete the MCXN947_project.c and add the main.s

Click the “source” group with right mouse button, the click “New”->”source File”

xiangjun_rong_4-1731589387456.png

 

1.6 Add the main.s as the following Fig and click “Finish”

xiangjun_rong_5-1731589442105.png

 

1.7 The final project is like:

xiangjun_rong_6-1731589491099.png

 

2.0 writing the assembly code in the main.s

This is the code in main.s

/* This assembly file uses GNU syntax */

.equ SYSCON_ANGCLKCTRLSET0,0x40000220

.equ SYSCON_AHBCLKCTRLSET1,0x40000224

.equ SYSCON_AHBCLKCTRLSET2,0x40000228

.equ SYSCON_CTIMER4CLKSEL, 0x4000027C

.equ SYSCON_CTIMER4CLKDIV, 0x400003E0

 

/*PIO3_4 LED blue*/

.equ PORT3_PCR_BASE,0x40119000

.equ PORT3_PCR4,PORT3_PCR_BASE+0x90

 

.equ GPIO3_BASE,0x4009C000

.equ GPIO3_PDDR,GPIO3_BASE+0x54

.equ GPIO3_PDOR,GPIO3_BASE+0x40

 

 

/*PIT configuration*/

.equ CTIMER4_BASE,0x40010000

.equ CTIMER4_IR,CTIMER4_BASE+0x00

.equ CTIMER4_TCR,CTIMER4_BASE+0x04

.equ CTIMER4_MCR,CTIMER4_BASE+0x14

.equ CTIMER4_MR0,CTIMER4_BASE+0x18

.equ CTIMER4_MSR0,CTIMER4_BASE+0x78

.equ CTIMER4_PWMC,CTIMER4_BASE+0x74

 

 

/*NVIC configuration*/

/*refer to 4.2 Nested Vectored Interrupt Controller in Cortex-M4 Generic User's Guide.pdf*/

.equ NVIC_ISER0,0xE000E100

.equ NVIC_ISER1,0xE000E104

 

.equ NVIC_ICPR0,0xE000E284

.equ NVIC_ICPR1,0xE000E288

 

.equ NVIC_IPR12,0xE000E430

.equ NVIC_IPR14,0xE000E438

 

 

 

    .global __user_mem_buffer1,__user_mem_buffer2

    .text

    .section   .rodata

    .align  2

 

 

.LC0:

 

    .text

    .thumb

    .align  2

    .global main

    .global CTIMER0_IRQHandler

    .type main function

 

main:

    push {r3, lr}

    add r3, sp, #4

    nop

    BL peripheralInit

    nop

    nop

    nop

    nop

    NOP

    /*cpsie i*/

loop:

    b loop

    mov r3, #0

    mov r0, r3

    pop {r3, pc}

 

 

/*subroutine 1*/

/* copy 10 words from one place to another*/

    .type MyFunc function

    .func

MyFunc:

    push {r0,r1,r2,lr}

    MOV R2,#0x00

    LDR R0,=USER_MEM_BUFFER1

    MOV R1,#0x00

loop1:

    NOP

    STR R1,[R0]

    ADD R1,#0x10

    ADD R0,#4

    ADD R2,#1

    CMP R2,#0x10

    BNE loop1

    AND R5,R1,R5 ;

    ASR R3,R2,#1

    ORR R5,R1,R5

    ADD R3,R2,R3

    ADC R3,R2,R3

    AND R2,R1,R2 ; /*#0x0F*/

    LDR R0,=0x1234

    /*LDR R0, [R1], #4*/

    nop

    pop {r0,r1,r2,pc}

    .endfunc

/***************************************/

 

/*subroutine 2*/

    .type peripheralInit function

    .func

peripheralInit:

 

 //enable CTimer4 gated clock

    LDR R0,=0x400000

    LDR R1,=SYSCON_AHBCLKCTRLSET2

    nop

    STR R0, [R1]

 

    MOV R0,#0x03 //select

    LDR R1,=SYSCON_CTIMER4CLKSEL

    nop

    STR R0, [R1]

 

 

    MOV R0,#0x09 //select

    LDR R1,=SYSCON_CTIMER4CLKDIV

    nop

    STR R0, [R1]

    /*setting CTimer0*/

 

    //set Ctimer0_IR

    MOV R3,#0x01

    LDR R1,=CTIMER4_IR

    Nop

    LDR R2,[R1]

    ORR R2,R2,R3

    STR R2,[R1]

 

 

//set CTIMER4_MCR

    MOV R3,#0x03

    LDR R1,=CTIMER4_MCR

    LDR R2,[R1]

    ORR R2,R2,R3

    STR R2,[R1]

 

 

    LDR R0,=6000000

    LDR R1,=CTIMER4_MR0

    STR R0,[R1]

 

    LDR R0,=6000000

    LDR R1,=CTIMER4_MSR0

    STR R0,[R1]

 

 

    MOV R0,#00

    LDR R1,=CTIMER4_PWMC

    STR R0,[R1]

 

    nop

    nop

//lop1:

//  b lop1

 

 

    /*setting interrupt, Ctimer4 IRQ 56*/

    LDR R1,=NVIC_ISER1

    LDR R0,[R1]

    LDR R3,=0x01000000

    ORR R0,R0,R3

    STR R0,[R1]

 

    LDR R1,=NVIC_ICPR1

    LDR R0,[R1]

    LDR R3,=0x01000000

    ORR R0,R0,R3

    STR R0,[R1]

 

    MOV R0,#0x00

    LDR R1,=NVIC_IPR14

    STR R0,[R1]

 

    /*pin mux setting*/

    /*enable PORT3 and GPIO3 gated clock*/

    LDR R0,=0x410000

    LDR R1,=SYSCON_ANGCLKCTRLSET0

    nop

    STR R0, [R1]

    /*set the GPIO3_4 as GPIO output mode*/

    LDR R0,=#0x1000

    LDR R1,=PORT3_PCR4

    STR R0,[R1]

 

 

    LDR R1,=GPIO3_PDDR

    LDR R0,[R1]

    LDR R3,=0x10

    ORR R0,R0,R3

    STR R0,[R1]

 

    /*CTimer4 start*/

    MOV R3,#0x01

    LDR R1,=CTIMER4_TCR

    LDR R0,[R1]

    ORR R0, R0,R3

    STR R0,[R1]

    nop

    nop

    nop

    /*cpsid i*/

    BX LR

    .endfunc

/*********************************************/

 

/*subroutine 3*/

    .text

    .type testcal function

    .func

testCal:

    LDR R0,=0x12345678

    MOV R1,#0x0F

    AND R0,R1

    /*test saturation function*/

    LDR R0,=0x8234

    LDR R1,=0x8234

    /*ADDS R5,R0,R1*/

    QADD16 R6,R0,R1  /*saturation heppen, the R6 will become negative minumum 0x8000*/

    nop

    /***8888888*/

 

    LDR R0,=0x6234

    LDR R1,=0x6234

    /*ADDS R5,R0,R1*/

    SADD16 R6,R0,R1

    nop

    QADD16 R6,R0,R1 /*saturation heppen, the R6 will become negative minumum 0x7FFF*/

    nop

    SMUAD R6,R0,R1

    BX LR

    .endfunc

/*********************************************/

 

/*interrupt service routine*/

    .global CTIMER4_IRQHandler

    .text

    .align 2

    .type CTIMER4_IRQHandler function

    .func

CTIMER4_IRQHandler:

        /*clear interrupt*/

    push {R0,R1,LR}

    nop

    nop

    nop

    LDR R1,=CTIMER4_IR

    LDR R0,[R1] /*dummy reading*/

    MOV R4,#0x10;

    ORR R0,R0,R4

    STR R0, [R1]

    /*toggle a LED*/

    LDR R1,=GPIO3_PDOR

    LDR R0,[R1]

    LDR R3,=0x10

    EOR R0,R0,R3

    STR R0,[R1]

    NOP

    POP {R0,R1,PC}

    .endfunc

 

 

/******************************************************/

/*interrupt service routine*/

    .global SVC_Handler

    .text

    .align 2

    .type SVC_Handler function

    .func

SVC_Handler:

    push {R0,R1,LR}

           NOP

    POP {R0,R1,PC}

/******************************************************/

 

    .align  2

.L3:

    .word

 

    .align 4

    .section .contantData

HELLO_TXT:

    .space 0x100

Hello_END:

    .ALIGN 4

  /*.lcomm */

  .lcomm USER_MEM_BUFFER1  0x100

  .lcomm USER_MEM_BUFFER2  0x100

    .end

 

3.0 code explanation

 

In the code, you have to define the main function, after the core has executed the code ResetISR(void), which is defined in startup_mcxn847_cm33_core0.c, it jump to main() function

xiangjun_rong_7-1731589601652.png

 

The example code implement the function to initialize CTimer, GPIO and NVIC, SYSCON module so that the CTImer can generate interrupt, in the ISR of CTimer, a LED is toggled.

After you run the code, you can see that the led is toggled.

The peripheralInit Subroutine is used to initialize the CTimer, NVIC, GPIO, SYSCON module so that the CTimer can fire an interrupt and toggle a LED.The CTIMER4_IRQHandler is an ISR of CTimer4, which is defined in startup_mcxn847_cm33_core0.

 

The MyFunc function and testCal  Subroutines are just for testing a specific assembly instruction, and test how to establish and call a subroutines, they do not have a specific target.

No ratings
Version history
Last update:
a month ago
Updated by: