大多数情况下,生成并使用C项目。但是汇编项目有它自己的优势,有了汇编项目,您可以直接使用汇编语言编程,可以使用汇编助记符测试汇编指令。一般来说,C语言效率较低,所以为了测试内核的性能,或者得到外设的最高性能,需要汇编工程。
该文档讨论了创建汇编语言项目的过程,最后给出了一个切换 LED 的示例,演示了如何用汇编语言初始化 NVIC、CTimer、GPIO。并给出了子程序的例子。
1.1 加载 MCUXPresso 工具并将 SDK 拖到已安装的 SDK 菜单
然后点击“创建一个新的C/C++项目”
1.2 选择主板或处理器,然后点击“下一步”软件按钮
1.3 命名项目并选择驱动程序。
在菜单中,使用默认配置即可,然后单击“完成”
1.4 使用 C 语言创建一个名为 MCXN947_project 的新项目
1.5 删除MCXN947_project.c并添加 main.s
右键点击“源”组,点击“新建”->“源文件”
1.6 添加main.s如下图,点击“完成”
1.7 最终项目如下:
2.0在 main.s 中编写汇编代码
这是 main.s 中的代码
/* 该汇编文件使用 GNU 语法 */
.equ SYSCON_ANGCLKCTRLSET0,0x40000220
.equ SYSCON_AHBCLKCTRLSET1,0x40000224
.equ SYSCON_AHBCLKCTRLSET2,0x40000228
.equ SYSCON_CTIMER4CLKSEL,0x4000027C
.equ SYSCON_CTIMER4CLKDIV,0x400003E0
/*PIO3_4 LED 蓝色*/
.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配置*/
.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配置*/
/*参考Cortex-M4通用用户指南.pdf中的4.2嵌套向量中断控制器*/
.equ NVIC_ISER0,0xE000E100
.equ NVIC_ISER1,0xE000E104
.equ NVIC_ICPR0,0xE000E284
.equ NVIC_ICPR1,0xE000E288
.equ NVIC_IPR12,0xE000E430
.equ NVIC_IPR14,0xE000E438
.全局__user_mem_buffer1,__user_mem_buffer2
。文本
.section .rodata
.align 2
.LC0:
。文本
.thumb
.align 2
.global main
.全局CTIMER0_IRQHandler
.type主要功能
主要的:
推 {r3, lr}
add r3, sp, #4
nop
BL 外设初始化
nop
nop
nop
nop
NOP
/*cpsie i*/
环形:
b 环
mov r3, #0
mov r0, r3
弹出 {r3, pc}
/*子程序1*/
/* 从一个地方复制 10 个单词到另一个地方 */
.type MyFunc 函数
.函数
MyFunc:
推 {r0,r1,r2,lr}
MOV R2,#0x00
LDR R0,=USER_MEM_BUFFER1
MOV R1,#0x00
循环1:
NOP
力量 R1,[R0]
添加 R1,#0x10
添加 R0,#4
添加 R2,#1
CMP R2,#0x10
BNE 环路1
并且 R5,R1,R5;
ASR R3,R2,#1
ORR R5,R1,R5
添加 R3,R2,R3
ADC R3、R2、R3
AND R2,R1,R2 ; /*#0x0F*/
LDR R0,=0x1234
/*LDR R0,[R1],#4*/
nop
弹出 {r0,r1,r2,pc}
.endfunc
/***************************************/
/*子程序2*/
.type peripheralInit 函数
.函数
外设初始化:
//启用CTimer4门控时钟
LDR R0,=0x400000
LDR R1,=SYSCON_AHBCLKCTRLSET2
nop
力量 R0, [R1]
MOV R0,#0x03 //选择
LDR R1,=SYSCON_CTIMER4CLKSEL
nop
力量 R0, [R1]
MOV R0,#0x09 //选择
LDR R1,=SYSCON_CTIMER4CLKDIV
nop
力量 R0, [R1]
/*设置CTimer0*/
//设置Ctimer0_IR
MOV R3,#0x01
LDR R1,=CTIMER4_IR
Nop
LDR R2,[R1]
ORR R2,R2,R3
力量 R2,[R1]
//设置CTIMER4_MCR
MOV R3,#0x03
LDR R1,=CTIMER4_MCR
LDR R2,[R1]
ORR R2,R2,R3
力量 R2,[R1]
LDR R0,=6000000
LDR R1,=CTIMER4_MR0
力量 R0,[R1]
LDR R0,=6000000
LDR R1,=CTIMER4_MSR0
力量 R0,[R1]
MOV R0,#00
LDR R1,=CTIMER4_PWMC
力量 R0,[R1]
nop
nop
//lop1:
// b lop1
/*设置中断,Ctimer4 IRQ 56*/
LDR R1,=NVIC_ISER1
LDR R0,[R1]
LDR R3,=0x01000000
ORR R0,R0,R3
力量 R0,[R1]
LDR R1,=NVIC_ICPR1
LDR R0,[R1]
LDR R3,=0x01000000
ORR R0,R0,R3
力量 R0,[R1]
MOV R0,#0x00
LDR R1,=NVIC_IPR14
力量 R0,[R1]
/*引脚复用设置*/
/*启用PORT3和GPIO3门控时钟*/
LDR R0,=0x410000
LDR R1,=SYSCON_ANGCLKCTRLSET0
nop
力量 R0, [R1]
/*设置GPIO3_4为GPIO输出模式*/
LDR R0,=#0x1000
LDR R1,=PORT3_PCR4
力量 R0,[R1]
LDR R1,=GPIO3_PDDR
LDR R0,[R1]
LDR R3,=0x10
ORR R0,R0,R3
力量 R0,[R1]
/*CTimer4启动*/
MOV R3,#0x01
LDR R1,=CTIMER4_TCR
LDR R0,[R1]
ORR R0, R0,R3
力量 R0,[R1]
nop
nop
nop
/*cpsid i*/
BX LR
.endfunc
/*********************************************/
/*子程序 3*/
。文本
.type testcal 函数
.函数
测试校准:
LDR R0,=0x12345678
MOV R1,#0x0F
AND R0,R1
/*测试饱和函数*/
LDR R0,=0x8234
LDR R1,=0x8234
/*添加 R5,R0,R1*/
QADD16 R6,R0,R1 /*饱和发生,R6将变为负最小值0x8000*/
nop
/***8888888*/
LDR R0,=0x6234
LDR R1,=0x6234
/*添加 R5,R0,R1*/
SADD16 R6,R0,R1
nop
QADD16 R6,R0,R1 /*饱和发生,R6将变为负最小值0x7FFF*/
nop
SMUAD R6,R0,R1
BX LR
.endfunc
/*********************************************/
/*中断服务程序*/
.全局 CTIMER4_IRQHandler
。文本
.align 2
.type CTIMER4_IRQHandler function
.函数
CTIMER4_IRQ处理程序:
/*清除中断*/
推 {R0,R1,LR}
nop
nop
nop
LDR R1,=CTIMER4_IR
LDR R0,[R1] /*虚拟读数*/
MOV R4,#0x10;
ORR R0,R0,R4
力量 R0, [R1]
/*切换 LED*/
LDR R1,=GPIO3_PDOR
LDR R0,[R1]
LDR R3,=0x10
EOR R0、R0、R3
力量 R0,[R1]
NOP
弹出 {R0,R1,PC}
.endfunc
/******************************************************/
/*中断服务程序*/
.global SVC_Handler
。文本
.align 2
.type SVC_Handler 函数
.函数
SVC_Handler:
推 {R0,R1,LR}
NOP
弹出 {R0,R1,PC}
/******************************************************/
.align 2
.L3:
.word
.align 4
.section .contantData
你好_TXT:
.space 0x100
Hello_END:
.ALIGN 4
/*.lcomm */
.lcomm USER_MEM_BUFFER1 0x100
.lcomm USER_MEM_BUFFER2 0x100
.end
3.0代码解释
在代码中,必须定义主函数,在核心执行完在 startup_mcxn847_cm33_core0.c 中定义的代码 ResetISR(void) 后,它会跳转到 main() 函数
示例代码实现了初始化CTimer、GPIO和NVIC、SYSCON模块的功能,使得CTimer可以产生中断,在CTimer的ISR中,LED会进行切换。
运行代码后,你可以看到 LED 被切换了。
peripheralInit子程序用于初始化 CTimer、NVIC、GPIO、SYSCON 模块,以便 CTimer 可以触发中断并切换 LED。CTIMER4_IRQHandler是 CTimer4 的 ISR,它在 startup_mcxn847_cm33_core0 中定义。
MyFunc函数和testCal子程序只是为了测试特定的汇编指令,以及测试如何创建和调用子程序,它们没有特定的目标。