第九讲:模仿STM32驱动开发实验
前言:在02中我们学习的如何使用C语言的知识去编写代码,并且是直接定义寄存器地址的。你自己回想一下,stm32的库文件是这样的吗?当然不是,它是继续封装了地址,把寄存器封装为结构体使用,我们需要打开stm32库文件,关于寄存器地址定义的在#include "stm32f10x_it.h" 文件中
寄存器结构体封装-以GPIO寄存器为例
下面的5张图表示的就是寄存器封装的过程
封装步骤:
1:把数据类型重定义一下,像stm32一样的
2:把所有的寄存器开始封装,根据结构体地址递增的特点,如果发现地址不连续,那么随便定义一个变量占就可以了,如果是多个就使用数组占
3:定义各个外设的基地址,如GPIO1的基地址
#define GPIO1_BASE (0x0209C000) /* * GPIO寄存器结构体 */ typedef struct { volatile unsigned int DR; volatile unsigned int GDIR; volatile unsigned int PSR; volatile unsigned int ICR1; volatile unsigned int ICR2; volatile unsigned int IMR; volatile unsigned int ISR; volatile unsigned int EDGE_SEL; }GPIO_Type; #define GPIO1 ((GPIO_Type *)GPIO1_BASE)
工程汇编文件书写
这里的汇编代码书写,与前面的有所不同,不同的就是:我们手动清零bss段的数据
看到前一节的链接脚本的书写
.word表示的意思是占位的意思,类似于int也是占了2/4个字节的位置
把起始和结束地址保存在寄存器中,这里涉及到了另外几个汇编-stmia、cmp、ble
这里的mov可以改成ldr吗?你可以尝试一下
/* 清BSS段 */ ldr r0, _bss_start ldr r1, _bss_end mov r2, #0 bss_loop: stmia r0!, {r2} /* 向r0的地址写入0,然后r0寄存器保存的地址值加1 */ cmp r0, r1 /* 比较r0和r1,也就是__bss_start和__bss_end的值*/ ble bss_loop /* 如果小于等于的话就跳转到bss_loop继续清bss段*/
C代码编写
void led_init(void)
{
/* 1、初始化IO复用 */
IOMUX_SW_MUX->GPIO1_IO03 = 0X5; /* 复用为GPIO1_IO03 */
/* 2、配置GPIO1_IO03的IO属性
*bit 16:0 HYS关闭
*bit [15:14]: 00 默认下拉
*bit [13]: 0 kepper功能
*bit [12]: 1 pull/keeper使能
*bit [11]: 0 关闭开路输出
*bit [7:6]: 10 速度100Mhz
*bit [5:3]: 110 R0/6驱动能力
*bit [0]: 0 低转换率
*/
IOMUX_SW_PAD->GPIO1_IO03 = 0X10B0;
/* 3、初始化GPIO */
GPIO1->GDIR = 0X0000008; /* GPIO1_IO03设置为输出 */
GPIO1->GDIR = 9;
/* 4、设置GPIO1_IO03输出低电平,打开LED0 */
GPIO1->DR &= ~(1 << 3);
}
Makefile编写
其实这里的-Wall -nostdlib -c -o2也可以写到一起
第十讲NXP官方SDK使用
前言:
在第九讲我们完成了模仿stm32的驱动方式完成我们的LED点灯工程,我们手动添加了我们需要的寄存器地址并且定义和使用(使用方式为:stm32的使用方式),但是我们知道6ULL有很多的寄存器因此我们不可能一个一个自己这样添加,但是好的就是NXP官方已经帮我们搞好了这些,因此本讲的内容就是选择性的使用NXP官方提供的SDK并且移植到我们的工程中去
但是实际上对于以后的开发,很少有芯片会有这种配套的SDK给我们使用,我们一般也不会使用官方提供的库和bsp,因为我们的驱动但是直接操作寄存器的,不使用哪些库(这是视频zzk讲的,现在我还没有理解,留个印象)
移植后,我们需要改动,至于怎么改动?视频没讲为什么,直接操作了,并且在讲解移植的时候,出现了问题(原因是:文件乱码了,这个问题很容易遇到,我也经常遇到,在copy代码的时候),因此zzk建议我们不要移植nxp的,直接移植正点原子写好了的文件就可以了
主要内容:移植的两个函数讲解
IOMUXC_SetPinMux(IOMUXC_GPIO1_IO03_GPIO1_IO03,0);
IOMUXC_SetPinConfig(IOMUXC_GPIO1_IO03_GPIO1_IO03,0X10B0);
static inline void IOMUXC_SetPinMux(uint32_t muxRegister,
uint32_t muxMode,
uint32_t inputRegister,
uint32_t inputDaisy,
uint32_t configRegister,
uint32_t inputOnfield)
static inline void IOMUXC_SetPinConfig(uint32_t muxRegister,
uint32_t muxMode,
uint32_t inputRegister,
uint32_t inputDaisy,
uint32_t configRegister,
uint32_t configValue)
原型和使用你会发现我使用的只有两个形参,我们写错了吗?
#define IOMUXC_GPIO1_IO03_GPIO1_IO03 0x020E0068U, 0x5U, 0x00000000U, 0x0U, 0x020E02F4U
Mux表示的是复用寄存器,config表示的是功能模式的(比如上下拉速度之类的)
其实是IOMUXC_GPIO1_IO03_GPIO1_IO03表示的是5个参数
*((volatile uint32_t *)configRegister) = configValue;
配置输出和电平还是单独使用寄存器配置的
/* 3、初始化GPIO,设置GPIO1_IO03设置为输出 */
GPIO1->GDIR |= (1 << 3);
/* 4、设置GPIO1_IO03输出低电平,打开LED0 */
GPIO1->DR &= ~(1 << 3);
Makefile书写
这次的Makefile书写比上一次的又升级了?=的使用,其实我感觉有点多余了
CROSS_COMPILE ?= arm-linux-gnueabihf- NAME ?= ledc CC := $(CROSS_COMPILE)gcc LD := $(CROSS_COMPILE)ld OBJCOPY := $(CROSS_COMPILE)objcopy OBJDUMP := $(CROSS_COMPILE)objdump TEMP := -Wall -nostdlib -c -O2 -o OBJS := start.o main.o $(NAME).bin:$(OBJS) $(LD) -Timx6ul.lds -o $(NAME).elf $^ $(OBJCOPY) -O binary -S $(NAME).elf $@ $(OBJDUMP) -D -m arm $(NAME).elf > $(NAME).dis %.o:%.s $(CC) $(TEMP) $@ $< %.o:%.c $(CC) $(TEMP) $@ $< clean: rm -rf *.o $(NAME).bin $(NAME).elf $(NAME).dis
目录
第九讲:模仿STM32驱动开发实验
寄存器结构体封装-以GPIO寄存器为例
工程汇编文件书写
C代码编写
Makefile编写
第十讲NXP官方SDK使用
前言:
主要内容:移植的两个函数讲解
Makefile书写