| 作者 | 将狼才鲸 |
|---|---|
| 创建日期 | 2022-11-05 |
Gitee工程和源码地址:才鲸嵌入式 / ARM-Cortex-M3从汇编到C_从Boot到应用教程
CSDN文章阅读地址:ARM Cortex-M3从汇编到C,从Boot到应用的教程
Bilibili视频讲解地址(待完成):才鲸嵌入式
| 工程名称 | 作用 |
|---|---|
| 01_Hello_world | 使用Keil的模拟器在虚拟终端输出Hello world |
| 02_Keil_boot_comments | Keil自带汇编boot的注释 |
| 03_Self_assembler_boot | 自行实现汇编boot |
| 04_Uart_loopback | 串口收发回环,使用Keil的虚拟终端窗口 |
| 05_Assembler_func | 汇编函数的编写 |
| 06_Hardware_arch_code | 将硬件相关的代码与系统逻辑代码分离 |
| 07_OS_kernel | 移植操作系统线程管理模块 |
| 08_OS_memory | 移植操作系统内存管理模块,实现malloc、free |
| 09_OS_filesystem | 移植操作系统文件系统模块 |
| … | … |
如何写汇编函数,汇编宏定义函数
工程和源码在本文档同级目录\src\05_Assembler_func\下
func.inc:
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; @brief 演示ARM M3的汇编宏定义函数
; @author 将狼才鲸
; @date 2022-11-10
; @note File format: UTF-8
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;; 私有宏定义函数,本模块内部使用 ;;;;;;;;
;;
; \brief 将通用寄存器里事先存好的值写到地址中去
; \param[in] $reg, 只能是一个通用寄存器如R0等,里面存放要写的值
; \param[in] $addr, 立即数地址
;;
MACRO ; 宏定义函数
ADDR_W_REG $reg, $addr
; 将地址存在R1中
MOVW R1, #($addr & 0xffff) ; movw命令代表将值放在寄存器的低16位,清零高16位
MOVT R1, #($addr >> 16) ; movt命令代表将值放在寄存器的高16位,不影响低16位
STR $reg, [R1, #0x00] ; 将前面寄存器里的值放到后面R1+0的地址中,
MEND ; 宏定义函数结束
;;
; \brief 将地址里的值读到寄存器中
; \param[in] $reg, 目的寄存器
; \param[in] $addr, 要读的地址
;;
MACRO
ADDR_R_REG $reg, $addr
MOVW R1, #($addr & 0xffff)
MOVT R1, #(&addr >> 16)
LDR $reg, [R1, #0x00] ; *reg = *(R1 + 0)
MEND
;;;;;;;; 接口宏定义函数 ;;;;;;;;
;;
; \brief 将一个立即数写入到地址中
; \param[in] $v, 要写入的值
; \param[in] $addr, 要写的地址
;;
MACRO
ADDR_WRITE $v, $addr
MOVW R0, #($v & 0xffff) ; 将要写入的值低16位转到寄存器
MOVT R0, #($v >> 16) ; 转存高16位
ADDR_W_REG R0, $addr ; 调用函数将R0写入到addr
MEND
;;
; \brief 读一个地址的数据,值放到R0中
; \param[in] $addr, 要读的地址
; \param[out] R0, 返回的值
;;
MACRO
ADDR_READ $addr
ADDR_R_REG R0, $addr ; 调用函数将addr中的值读到R0中
MEND
END
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; @brief 演示ARM M3汇编函数的编写,压栈弹栈,汇编宏定义函数等
; @author 将狼才鲸
; @date 2022-11-10
; @note File format: UTF-8
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
INCLUDE func.inc ; 包含头文件,头文件没有规避递归包含,注意不要多次包含同一个文件
PRESERVE8
THUMB
AREA |.text|, CODE, READONLY
;;
; \brief 汇编写的系统、硬件初始化函数,在main函数执行前先把DDR、PLL等准备好
;;
__hw_init PROC
EXPORT __hw_init
PUSH {R0, R1, R2, R3, LR} ; 先压栈
BL __hw_device_init ; 调用没有参数的函数
POP {R0, R1, R2, R3, LR} ; 最后再弹栈,不需要像51那样和压栈时顺序相反
BX LR ; 返回调用的函数
ALIGN ; 取消字节对齐
ENDP ; 函数结束
__hw_device_init PROC
EXPORT __hw_device_init
PUSH {R0, R1, R2, R3, LR}
ADDR_WRITE 0x00, 0x40004100
;TODO 配置必要的寄存器
POP {R0, R1, R2, R3, LR}
BX LR
ALIGN
ENDP
END