26. 模仿STM32驱动开发实验

一、STM32寄存器结构体详解
对于STM32而言,使用一个结构体将一个外设的所有寄存器都放到一起。
二、修改驱动
1、添加清除bss段代码


2、添加寄存器结构体
在结构体中添加寄存器的时候一定要注意地址的连续性,如果不连续的话要添加占位。

3、修改驱动
//main.c
#include "imx6ul.h"

/*
 * @description : 使能I.MX6U所有外设时钟
 * @param       : 无
 * @return      : 无
 */
void clk_enable(void)
{
    
    
    CCM->CCGR0 = 0XFFFFFFFF;
    CCM->CCGR1 = 0XFFFFFFFF;

    CCM->CCGR2 = 0XFFFFFFFF;
    CCM->CCGR3 = 0XFFFFFFFF;
    CCM->CCGR4 = 0XFFFFFFFF;
    CCM->CCGR5 = 0XFFFFFFFF;
    CCM->CCGR6 = 0XFFFFFFFF;
}

/*
 * @description : 初始化LED对应的GPIO
 * @param       : 无
 * @return      : 无
 */
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设置为输出 */

    /* 4、设置GPIO1_IO03输出低电平,打开LED0 */    
    GPIO1->DR &= ~(1 << 3); 
    
}

/*
 * @description : 打开LED灯
 * @param       : 无
 * @return      : 无
 */
void led_on(void)
{
    
    
    /* 将GPIO1_DR的bit3清零     */
    GPIO1->DR &= ~(1<<3); 
}

/*
 * @description : 关闭LED灯
 * @param       : 无
 * @return      : 无
 */
void led_off(void)
{
    
    
    /* 将GPIO1_DR的bit3置1 */
    GPIO1->DR |= (1<<3); 
}

/*
 * @description : 短时间延时函数
 * @param - n   : 要延时循环次数(空操作循环次数,模式延时)
 * @return      : 无
 */
void delay_short(volatile unsigned int n)
{
    
    
    while(n--){
    
    }
}

/*
 * @description : 延时函数,在396Mhz的主频下
 *                延时时间大约为1ms
 * @param - n   : 要延时的ms数
 * @return      : 无
 */
void delay(volatile unsigned int n)
{
    
    
    while(n--)
    {
    
    
        delay_short(0x7ff);
    }
}

/*
 * @description : mian函数
 * @param       : 无
 * @return      : 无
 */
int main(void)
{
    
    
    clk_enable();       /* 使能所有的时钟          */
    led_init();         /* 初始化led           */

    while(1)            /* 死循环              */
    {
    
       
        led_off();      /* 关闭LED            */
        delay(500);     /* 延时500ms          */

        led_on();       /* 打开LED            */
        delay(500);     /* 延时500ms          */
    }

    return 0;
}

//start.S
.global _start  		/* 全局标号 */

/*
 * 描述:	_start函数,程序从此函数开始执行,此函数主要功能是设置C
 *		 运行环境。
 */
_start:

	/* 进入SVC模式 */
	mrs r0, cpsr
	bic r0, r0, #0x1f 	/* 将r0寄存器中的低5位清零,也就是cpsr的M0~M4 	*/
	orr r0, r0, #0x13 	/* r0或上0x13,表示使用SVC模式					*/
	msr cpsr, r0		/* 将r0 的数据写入到cpsr_c中 					*/

	ldr sp,=0X80200000	/* 设置栈指针			 */
	b main				/* 跳转到main函数 		 */

//Makefile
objs := start.o main.o

ledc.bin:$(objs)
    arm-linux-gnueabihf-ld -Timx6ul.lds -o ledc.elf $^
    arm-linux-gnueabihf-objcopy -O binary -S ledc.elf $@
    arm-linux-gnueabihf-objdump -D -m arm ledc.elf > ledc.dis

%.o:%.s
    arm-linux-gnueabihf-gcc -Wall -nostdlib -c -O2 -o $@ $<
    
%.o:%.S
    arm-linux-gnueabihf-gcc -Wall -nostdlib -c -O2 -o $@ $<
    
%.o:%.c
    arm-linux-gnueabihf-gcc -Wall -nostdlib -c -O2 -o $@ $<
    
clean:
    rm -rf *.o ledc.bin ledc.elf ledc.dis

//imx6ul.lds
SECTIONS{
    
    
	. = 0X87800000;
	.text :
	{
    
    
		start.o 
		main.o 
		*(.text)
	}
	.rodata ALIGN(4) : {
    
    *(.rodata*)}     
	.data ALIGN(4)   : {
    
     *(.data) }    
	__bss_start = .;    
	.bss ALIGN(4)  : {
    
     *(.bss)  *(COMMON) }    
	__bss_end = .;
}

三、编译下载验证

猜你喜欢

转载自blog.csdn.net/lljss1980/article/details/114850874