当前位置: 首页 > news >正文

Linux开发——开发板介绍及裸机程序设计

本次Linux开发学习使用的开发板是来自正点原子的i.mx6ull开发板

我们的linux开发主要聚焦内核开发,这块开发板采用 ARM Cortex-A7 内核,芯片内部集成了丰富的外设控制器,支持 DDR3,支持 LCD 显示屏;多种连接接口: 如双网口(支持百兆以太网)、USB OTG、多种串口(UART)、CAN 总线、I2C、SPI 等。满足复杂linux系统开发学习。

本次学习开发语言采用C语言。

.led点灯程序设计

1.main.c

#define IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 (*(volatile unsigned int *)0x020E0068)
#define IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03 (*(volatile unsigned int *)0x020E02F4)
#define GPIO1_GDIR (*(volatile unsigned int*)0x0209C004) 
#define GPIO1_DR (*(volatile unsigned int*)0x0209C000)#define CCM_CCGR0 (*(volatile unsigned int*)0x020C4068)
#define CCM_CCGR1 (*(volatile unsigned int*)0x020C406C)
#define CCM_CCGR2 (*(volatile unsigned int*)0x020C4070)
#define CCM_CCGR3 (*(volatile unsigned int*)0x020C4074)
#define CCM_CCGR4 (*(volatile unsigned int*)0x020C4078)
#define CCM_CCGR5 (*(volatile unsigned int*)0x020C407C)
#define CCM_CCGR6 (*(volatile unsigned int*)0x020C4080)struct GPIO_t
{unsigned int DR;unsigned int GDIR;unsigned int PSR;unsigned int ICR1;unsigned int ICR2;unsigned int IMR;unsigned int ISR;unsigned int EDGE_SEL;
};#define GPIO1 ((struct GPIO_t *)0x0209C000)
#define GPIO2 ((struct GPIO_t *)0x020A0000)void clock_init(void)
{CCM_CCGR0 = 0xFFFFFFFF;CCM_CCGR1 = 0xFFFFFFFF;CCM_CCGR2 = 0xFFFFFFFF;CCM_CCGR3 = 0xFFFFFFFF;CCM_CCGR4 = 0xFFFFFFFF;CCM_CCGR5 = 0xFFFFFFFF;CCM_CCGR6 = 0xFFFFFFFF;}void led_init(void)
{IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 = 0x5;IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03 = 0x10B0;GPIO1 -> GDIR |=(1<<3);
}
void led_on(void)
{GPIO1-> DR &=~(1<<3);
}
void led_off(void)
{GPIO1->DR |=(1<<3);
}
void led_delay(int t)
{while(t--);
}int main(void)
{clock_init();led_init();while (1){led_on();led_delay(0xFFFFFF);led_off();led_delay(0xFFFFFF);}return 0;
}

1. 寄存器定义部分

#define IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 (*(volatile unsigned int *)0x020E0068)
#define IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03 (*(volatile unsigned int *)0x020E02F4)
  • 引脚复用控制寄存器:配置 GPIO1_IO03 引脚的功能(设置为 GPIO 模式)

  • 引脚属性控制寄存器:配置引脚的电气特性(如上拉/下拉、驱动强度等)

#define GPIO1_GDIR (*(volatile unsigned int*)0x0209C004) 
#define GPIO1_DR (*(volatile unsigned int*)0x0209C000)
  • GPIO 方向寄存器:控制引脚输入/输出方向

  • GPIO 数据寄存器:读取或写入引脚电平

#define CCM_CCGR0 ... #define CCM_CCGR6
  • 时钟控制模块寄存器:控制各个外设模块的时钟使能

2. GPIO 结构体定义

struct GPIO_t
{unsigned int DR;        // 数据寄存器unsigned int GDIR;      // 方向寄存器unsigned int PSR;       // 引脚状态寄存器unsigned int ICR1;      // 中断配置寄存器1unsigned int ICR2;      // 中断配置寄存器2unsigned int IMR;       // 中断掩码寄存器unsigned int ISR;       // 中断状态寄存器unsigned int EDGE_SEL;  // 边沿选择寄存器
};

将 GPIO 的所有寄存器映射到结构体,方便访问。

3. 功能函数

时钟初始化

void clock_init(void)
{CCM_CCGR0 = 0xFFFFFFFF;// ... 其他 CCGR 寄存器CCM_CCGR6 = 0xFFFFFFFF;
}

使能所有外设时钟,确保 GPIO 模块可以正常工作。

LED 初始化

void led_init(void)
{IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO03 = 0x5;    // 设置为 GPIO 功能IOMUXC_SW_PAD_CTL_PAD_GPIO1_IO03 = 0x10B0; // 配置引脚电气属性GPIO1->GDIR |= (1<<3);                     // 设置为输出模式
}

LED 控制函数

void led_on(void)   { GPIO1->DR &= ~(1<<3); }  // 第3位清零,LED亮
void led_off(void)  { GPIO1->DR |= (1<<3); }   // 第3位置1,LED灭

延时函数

void led_delay(int t) { while(t--); }  // 简单软件延时

4. 主函数

int main(void)
{clock_init();    // 初始化时钟led_init();      // 初始化LED引脚while (1)        // 主循环{led_on();    // 点亮LEDled_delay(0xFFFFFF);  // 延时led_off();   // 熄灭LED  led_delay(0xFFFFFF);  // 延时}return 0;
}

2.start.S

.global _start_start:ldr pc, =_reset_handler_ldr pc, =_undef_handler_ldr pc, =_svc_handler_ldr pc, =_prefetch_handler_ldr pc, =_data_handler_nopldr pc, =_irq_handler_ldr pc, =_fiq_handler__undef_handler_:b _undef_handler__svc_handler_:b _svc_handler__prefetch_handler_:b _prefetch_handler__data_handler_:b _data_handler__irq_handler_:b _irq_handler__fiq_handler_:b _fiq_handler__reset_handler_:cpsid icps #0x12/*mrs r0, cpsrbic r0, r0, #(0x1F << 0)bic r0, r0, #(1 << 7)       //使能irq中断orr r0, r0, #(0x12 << 0)    //切换到irq模式msr cpsr, r0*/ldr sp, =0x82000000cps #0x1F/*mrs r0, cpsrorr r0, r0, #(0x1F << 0)  //切换到system模式msr cpsr, r0*/ldr sp, =0x84000000cpsie ib main
_finish:b _finish

1. 异常向量表

assembly

复制下载

_start:ldr pc, =_reset_handler_    ; 复位异常ldr pc, =_undef_handler_    ; 未定义指令异常ldr pc, =_svc_handler_      ; 软件中断异常(SVC)ldr pc, =_prefetch_handler_ ; 预取指异常ldr pc, =_data_handler_     ; 数据访问异常nop                         ; 保留ldr pc, =_irq_handler_      ; 普通中断异常ldr pc, =_fiq_handler_      ; 快速中断异常

异常向量表位置:ARM 处理器在复位或发生异常时,会跳转到特定的地址执行相应的处理程序。

2. 异常处理程序

assembly

复制下载

_undef_handler_:b _undef_handler_      ; 未定义指令异常 - 死循环
_svc_handler_:b _svc_handler_        ; SVC 异常 - 死循环
_prefetch_handler_:b _prefetch_handler_   ; 预取指异常 - 死循环
_data_handler_:b _data_handler_       ; 数据异常 - 死循环
_irq_handler_:b _irq_handler_        ; 中断异常 - 死循环
_fiq_handler_:b _fiq_handler_        ; 快速中断 - 死循环

这些处理程序目前都是空实现,只是简单地在原地循环。在实际应用中需要根据具体需求实现相应的异常处理逻辑。

3. 复位处理程序(主程序入口)

assembly

复制下载

_reset_handler_:cpsid i                 ; 禁用中断cps #0x12              ; 切换到 IRQ 模式

处理器模式设置

  • cpsid i:禁用 IRQ 中断

  • cps #0x12:切换到 IRQ 模式(中断模式)

栈指针设置

assembly

复制下载

ldr sp, =0x82000000    ; 设置 IRQ 模式的栈指针cps #0x1F              ; 切换到 System 模式ldr sp, =0x84000000    ; 设置 System 模式的栈指针

栈内存布局

  • IRQ 模式栈:0x82000000

  • System 模式栈:0x84000000

注释掉的代码说明

assembly

复制下载

/*
mrs r0, cpsr
bic r0, r0, #(0x1F << 0)
bic r0, r0, #(1 << 7)       // 使能 IRQ 中断
orr r0, r0, #(0x12 << 0)    // 切换到 IRQ 模式
msr cpsr, r0
*/

这是用传统方式修改 CPSR 寄存器来切换模式的代码,被更简洁的 cps 指令替代。

4. 主程序执行

assembly

复制下载

cpsie i                ; 启用中断bl _led_init           ; 调用 LED 初始化函数b _finish              ; 跳转到结束循环b main                 ; 这行代码不会执行(被上一行跳转跳过)

5. 结束处理

assembly

复制下载

_finish:b _finish             ; 无限循环,程序停留在这里

代码执行流程总结

  1. 上电复位 → 跳转到 _reset_handler_

  2. 初始化设置

    • 禁用中断

    • 设置 IRQ 模式栈指针

    • 设置 System 模式栈指针

    • 启用中断

  3. 执行应用代码:调用 _led_init

  4. 进入死循环:程序执行完毕,停留在 _finish

http://www.dtcms.com/a/398683.html

相关文章:

  • 百度网站推广关键词怎么查凡科微信小程序怎么样
  • 定制网站开发接活wordpress固定链接设置技巧
  • HTTP代理HTTP(S)、SOCKS5有哪些作用?
  • vue3+TS 前端调用海康摄像头视频流,后端用 Node.js 做 RTSP 转 WebSocket-FLV 转发,并且前后端优化延迟方案
  • 计算机视觉(opencv)练习——抠图(图像裁剪与轮廓提取)
  • 网站建设知识点的总结怎么做网站一个平台
  • 西安做网站的在网站后台设置wap模板目录
  • 软件行业|Parasoft与IAR的嵌入式DevOps测试集成
  • 设计模式-状态模式详解
  • 微信小程序通用弹窗组件封装与动画实现
  • 「日拱一码」099 数据处理——降维
  • 速通ACM省铜第十三天 赋源码(Watermelon)
  • 【C++进阶系列】:位图和布隆过滤器(附模拟实现的源码)
  • 洛阳网站建设建站系统怎么删除网站的死链
  • 山东省城乡建设厅网站wordpress academia
  • 广州番禺服装网站建设济南网站优化
  • 下载huggingface中数据集/模型
  • vue事件循环机制
  • 分布式专题——19 Zookeeper分布式一致性协议ZAB源码剖析
  • 前端核心框架vue之(组件篇2/5)
  • 【分布式】分布式事务方案:两阶段、TCC、SEATA
  • Kafka介绍
  • Netty 解码器 DelimiterBasedFrameDecoder
  • 位运算 常见方法总结 算法练习 C++
  • 电子商务平台网站源码国外炫网站
  • PTZ相机的知识体系
  • Nginx反向代理配置全流程实战:从环境搭建到HTTPS部署
  • HTTPS 能抓包吗?实战答案与逐步可行方案(HTTPS 抓包原理、证书Pinning双向认证应对、工具对比)
  • 对网站建设的讲话wordpress 自定义面板
  • 【23】C++实战篇——C++报错:LNK2001:无法解析的外部符号 ,LNK2019: 无法解析的外部符号,原因分析及解决方法