裸机驱动模板

本文详细解析了如何通过构建一个设备类来编写高效的裸机驱动,以SPIFLASH为例,展示了如何剥离一致属性,构建通用设备结构体,并通过函数封装简化设备操作。实现了驱动的移植性和易用性。

编写裸机驱动,一般都比较随意。这通常导致代码不统一,移植性差。

本例以SPI FLASH来分析一种优秀的裸机驱动编写模板。

 

首先定义一个设备类。

 

/*

 *flash device class

 */

typedef struct flash_dev_s{

 const struct flash_dev_funs *funs;          /* Function pointers */

 uint32                     flags;          /* Devicecharacteristics */

 hsaddr_t                   start;          /* First address*/

 hsaddr_t                   end;            /* Last address */

 uint32                     num_block_infos;/* Number of entries */

 const flash_block_info_t   *block_info;    /* Info about oneblock size */

 

 const void                 *priv;          /* Devices privatedata */

} flash_dev_t;

 

/* Structure of pointers to functions inthe device driver */

Struct  flash_dev_funs {

 sys_error_t (*flash_init) (struct flash_dev_s *dev) REENTRANT;

 sys_error_t (*flash_erase_block) (struct flash_dev_s *dev,

                                    hsaddr_tblock_base) REENTRANT;

 sys_error_t (*flash_program) (struct flash_dev_s *dev,

                                hsaddr_t base,

                                const void*ram_base, size_t len) REENTRANT;

 sys_error_t (*flash_read) (struct flash_dev_s *dev,

                             const hsaddr_tbase,

                             void* ram_base,size_t len) REENTRANT;

};

同一种设备类型可能有不同厂家和不同参数的差异,但它的大体功能属性是一致的。我们首先把一致的属性剥离出来,构建一个设备类。类似C++的类,包含数据和操作方法。一个设备驱动模板的雏形就出来了。

 

我们来看一个设备实例来看它的方便之处。

struct flash_dev_funs mx25l_funs = {

   mspi_init,

   m25lxx_erase_block,

   m25lxx_program,

   m25lxx_read,

   NULL

};

 

flash_dev_t n25q256_dev = {

   &mx25l_funs,

   FLAG_FSR_POLL,

   CFG_FLASH_START_ADDRESS,

   0,

   1,

   &n25q256_info,

   NULL };

flash_dev_t w25q16_dev = {

   &mx25l_funs,

   0,

  CFG_FLASH_START_ADDRESS,

   0,

   1,

  &w25q16cv_info,

  NULL };

/*end*/

 

flash_dev_t w25q64cv_dev = {

   &mx25l_funs,

   0,

   CFG_FLASH_START_ADDRESS,

   0,

   1,

   &w25q64cv_info,

NULL };

 

这里用一个通用设备结构体定义和初始化了多个不同的spi设备实例。我们看到每个设备的不同之处在它们的功能函数和设备属性。当我们需要新增一个设备时,只需定义一个通用设备类,再去添加它自己的操作方法和数据属性就行了。实现这些之后,对外部调用来说就简单了,直接操作这个设备类的统一接口,上层代码不需要做任何改动,提高了驱动移植性。


我们还可以做进一步的函数封装。

例如:把设备操作完全屏蔽,上层代码不需要管是什么设备。

sys_error_t
flash_read(hsaddr_t flash_base, void *ram_base, size_t len)
{

    dev = board_get_flash_dev();
    if (!dev) {
        return SYS_ERR;
    }

    rv = (*dev->funs->flash_read)(dev, addr, ram, this_read);

    ......

}

### RK3588 Bare-Metal Driver 开源资源与教程汇总 #### 1. 裸机开发概述 RK3588 是一款基于 ARM Cortex-A76 和 A55 架构的高性能 SoC,广泛应用于边缘计算、AI 推理等领域。对于裸机开发者而言,掌握其底层驱动设计至关重要。以下是关于 RK3588 裸机驱动的相关开源资源和教程。 --- #### 2. 开发环境搭建 构建 RK3588 的裸机开发环境需要以下工具链和支持库: - **GNU 工具链**: 提供交叉编译器 (`aarch64-none-elf-gcc`)。 - **QEMU 模拟器**: 可选工具,用于测试基本功能而无需真实硬件[^1]。 - **OpenOCD 或 JTAG 调试器**: 实现代码下载和调试。 推荐使用官方文档或社区维护的指南作为参考,例如 Rockchip 官方发布的《RK3588 Boot Flow》手册[^2]。 --- #### 3. GPIO 控制示例 GPIO 是裸机开发中最常见的外设之一。以下是一个简单的 GPIO 输出配置实例: ```c #include "rk3588_gpio.h" void gpio_init(void) { volatile uint32_t *gpio_reg = (uint32_t *)GPIO_BASE; // 配置 GPIO 功能模式 *(gpio_reg + GPIO_SWPORT_DDR_OFFSET) |= (1 << LED_PIN); // 设置为输出 *(gpio_reg + GPIO_SWPORT_DR_OFFSET) &= ~(1 << LED_PIN); // 清零(关闭) } void led_toggle(void) { volatile uint32_t *gpio_reg = (uint32_t *)GPIO_BASE; static int state = 0; if (!state++) { // 打开 LED *(gpio_reg + GPIO_SWPORT_DR_OFFSET) |= (1 << LED_PIN); } else { // 关闭 LED *(gpio_reg + GPIO_SWPORT_DR_OFFSET) &= ~(1 << LED_PIN); } } ``` 上述代码片段展示了如何初始化并切换一个连接到 GPIO 的 LED 状态。 --- #### 4. I2C 外设交互 I2C 协议常用于与 PMIC(电源管理芯片)或其他外围设备通信。以下是一段基础的 I2C 主控发送数据代码: ```c #include "rk3588_i2c.h" void i2c_write(uint8_t addr, uint8_t reg, uint8_t data) { volatile uint32_t *i2c_reg = (uint32_t *)I2C_BASE; // 配置目标地址 *(i2c_reg + I2C_CON_OFFSET) = (addr << I2C_TAR_SHIFT); // 入寄存器值 *(i2c_reg + I2C_DATA_CMD_OFFSET) = reg; while (!(*(i2c_reg + I2C_STATUS_OFFSET) & I2C_ACTIVITY)); // 等待完成 *(i2c_reg + I2C_DATA_CMD_OFFSET) = data; while (!(*(i2c_reg + I2C_STATUS_OFFSET) & I2C_ACTIVITY)); } ``` 这段代码演示了向指定 I2C 设备入单字节数据的过程[^1]。 --- #### 5. 社区资源链接 多个活跃项目提供了针对 RK3588 的裸机开发支持: - **GitHub Repositories**: - [Rockchip Official BSP](https://github.com/rockchip-linux): 包含丰富的启动加载程序和驱动模板。 - [Barebox Project](https://www.barebox.org/): 专注于嵌入式系统的引导固件框架,兼容多种平台。 - **在线教程**: - YouTube 上有大量由爱好者分享的实际操作视频,关键词搜索 “RK3588 bare metal programming”。 - 中文论坛如电子发烧友网也经常发布相关技术文章和经验总结[^2]。 --- #### 6. 注意事项 - **硬件依赖性**: 不同版本的核心板可能具有略微不同的引脚定义,请仔细查阅具体型号的数据表。 - **实时性考量**: 对于时间敏感的应用场景,需合理规划中断服务程序以减少延迟影响。 - **功耗优化**: 使用低功耗模式可以显著延长电池续航能力,在必要时可通过软件调节 CPU 频率[^2]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值