RT_Thread應(yīng)用開(kāi)發(fā)

一、Bootloader固件升級(jí)

RT-Thread ST固件更新過(guò)程

RT-Thread 通用 Bootloader 的軟件框架

image

RT-Thread 通用 Bootloader 特點(diǎn)

  • 以 bin 文件的形式提供,無(wú)需修改即可使用
  • 資源占用小,ROM 最小只需要 16KB,最大 32KB
  • 適用于多系列 STM32 芯片(目前支持 F1 和 F4 系列 )
  • 支持各種 SPI Flash 存儲(chǔ)固件
  • 支持固件加解密功能
  • 支持多種固件壓縮方式
  • 支持恢復(fù)出廠固件功能

1.固件升級(jí)過(guò)程

image

當(dāng)系統(tǒng)需要升級(jí)固件時(shí),Bootloader 將從 download 分區(qū)將固件搬運(yùn)到 app 分區(qū),主要功能流程如下所示:

  1. Bootloader 啟動(dòng)時(shí)檢查 download 分區(qū)和 app 分區(qū)中的固件版本。
  2. 如果兩個(gè)固件版本相同,則跳轉(zhuǎn)到 app 分區(qū),Bootloader 運(yùn)行結(jié)束。
  3. 固件版本不同則將 download 分區(qū)中的固件搬運(yùn)到 app 分區(qū)。
  4. 在搬運(yùn)的過(guò)程中 Bootloader 可以對(duì)固件進(jìn)行校驗(yàn)、解密、解壓縮等操作。
  5. 搬運(yùn)完畢后,刪除 download 分區(qū)中存儲(chǔ)的固件。
  6. 重啟系統(tǒng)跳轉(zhuǎn)到 app 分區(qū)中的固件運(yùn)行,Bootloader 運(yùn)行結(jié)束。

2.獲取 Bootloader

Bootloader 在線獲取地址

fal:Flash 抽象層

根據(jù)板級(jí)實(shí)際情況選擇硬件配置和分區(qū)

image

3.工程設(shè)置分區(qū)表

/* partition table */
#define FAL_PART_TABLE                                                                                                     \
{                                                                                                                          \
    {FAL_PART_MAGIC_WROD, "download",        "onchip_flash_128k", 0 , (128*1024), 0}, \
    {FAL_PART_MAGIC_WROD, "app",        "onchip_flash_128k", (1*128*1024) , FLASH_SIZE_GRANULARITY_128K-(128*1024), 0}, \
}
//onchip_flash_128k代表首地址為地址0x08020000基礎(chǔ),偏移0, 長(zhǎng)度為(128*1024),即128k

二、example程序使用

將示例程序添加到bsp/xxx/application文件夾下,工程文件夾路徑下,并在SConscript文件中加入其文件,在編譯時(shí)或生成工程時(shí),就會(huì)將文件加入工程之中執(zhí)行編譯

  • application的SConscript文件

    import rtconfig
    from building import *
    
    cwd     = GetCurrentDir()
    CPPPATH = [cwd, str(Dir('#'))]
    src     = Split("""
    application.c
    startup.c
    """)
    
    # add UI engine demo.
    if GetDepend('PKG_USING_GUIENGINE'):
        src += ['rtgui_demo.c']
        
    src += ['tofile.c'] #將需要添加的文件加入src變量中
    src += ['rtc_test.c']
    
    group = DefineGroup('Applications', src, depend = [''], CPPPATH = CPPPATH)
    
    Return('group')
    

通過(guò)FINSH_FUNCTION_EXPORT或MSH_CMD_EXPORT 宏定義,可以將函數(shù)加入到Finsh或MSH的命令之中

1.使用Ymodem協(xié)議傳輸文件到RT-Thread文件系統(tǒng)

1)使能Ymodem組件
  • 開(kāi)啟RT-Thread Components ---> Utilities ---> Enable Ymodem
2)添加tofile.c應(yīng)用程序
  • 將rt-thread\examples\ymodem\tofile.c文件添加到bsp工程的application文件夾中,并在其SConscript文件中添加tofile.c
3)修改文件默認(rèn)保存路徑
  • tofile.c默認(rèn)使用根目錄/保存文件,但ST的SPI Flash關(guān)連的文件系統(tǒng)掛載在/spi路徑下,所以需要將修改文件保存路徑,否則無(wú)法生成文件

    static enum rym_code _rym_bg(
            struct rym_ctx *ctx,
            rt_uint8_t *buf,
            rt_size_t len)
    {
        struct custom_ctx *cctx = (struct custom_ctx*)ctx;
        cctx->fpath[0] = '/';
      cctx->fpath[1] = 's';
      cctx->fpath[2] = 'p';
      cctx->fpath[3] = 'i';
      cctx->fpath[4] = '/';
      /* the buf should be the file name */
        strcpy(&(cctx->fpath[5]), (const char*)buf);
    
4)增加msh命令
  • tofile.c默認(rèn)使用FinSH命令,增加一個(gè)msh命令方便使用

    //在tofile.c末尾添加
    rt_err_t ymodem_rec(uint8_t argc, char **argv)
    {
      rt_err_t res;
    
        rt_device_t dev = rt_device_find(argv[1]);
        if (!dev)
        {
            rt_kprintf("could not find device:%s\n", argv[1]);
            return -RT_ERROR;
        }
    
        res = rym_write_to_file(dev);
    
        return res;
    }
    
    MSH_CMD_EXPORT(ymodem_rec, receive files by ymodem protocol);
    
5)使用Ymodem
  • 編譯并燒錄程序,使用SecureCRT連接調(diào)試串口
    • 在msh命令中輸入:ymodem_rec uart1,準(zhǔn)備接收文件,在SecureCRT選擇Ymodem傳輸方式,選擇文件傳輸。

三、設(shè)備和驅(qū)動(dòng)

RT_Thread設(shè)備類(lèi)型定義

enum rt_device_class_type
{
    RT_Device_Class_Char = 0,                           /**< character device */
    RT_Device_Class_Block,                              /**< block device */
    RT_Device_Class_NetIf,                              /**< net interface */
    RT_Device_Class_MTD,                                /**< memory device */
    RT_Device_Class_CAN,                                /**< CAN device */
    RT_Device_Class_RTC,                                /**< RTC device */
    RT_Device_Class_Sound,                              /**< Sound device */
    RT_Device_Class_Graphic,                            /**< Graphic device */
    RT_Device_Class_I2CBUS,                             /**< I2C bus device */
    RT_Device_Class_USBDevice,                          /**< USB slave device */
    RT_Device_Class_USBHost,                            /**< USB host bus */
    RT_Device_Class_SPIBUS,                             /**< SPI bus device */
    RT_Device_Class_SPIDevice,                          /**< SPI device */
    RT_Device_Class_SDIO,                               /**< SDIO bus device */
    RT_Device_Class_PM,                                 /**< PM pseudo device */
    RT_Device_Class_Pipe,                               /**< Pipe device */
    RT_Device_Class_Portal,                             /**< Portal device */
    RT_Device_Class_Timer,                              /**< Timer device */
    RT_Device_Class_Miscellaneous,                      /**< Miscellaneous device */
    RT_Device_Class_Sensor,                             /**< Sensor device */
    RT_Device_Class_Unknown                             /**< unknown device */
};

char *const device_type_str[] =
{
    "Character Device",
    "Block Device",
    "Network Interface",
    "MTD Device",
    "CAN Device",
    "RTC",
    "Sound Device",
    "Graphic Device",
    "I2C Bus",
    "USB Slave Device",
    "USB Host Bus",
    "SPI Bus",
    "SPI Device",
    "SDIO Bus",
    "PM Pseudo Device",
    "Pipe",
    "Portal Device",
    "Timer Device",
    "Miscellaneous Device",
    "Sensor Device",
    "Unknown"
};
  • rt-thread\bsp\stm32的資源配置在drv_config.h中選擇。

  • rt-thread\bsp\stm32\stm32f429-atk-apollo\board\CubeMX_Config\Src\stm32f4xx_hal_msp.c是芯片具體的資 源配置。

  • 可以通過(guò)stm32cubemx生成資源配置文件。

1.Pin設(shè)備

應(yīng)用程序通過(guò) RT-Thread 提供的 PIN 設(shè)備管理接口來(lái)訪問(wèn) GPIO,相關(guān)接口如下所示:

函數(shù) 描述
rt_pin_mode() 設(shè)置引腳模式
rt_pin_write() 設(shè)置引腳電平
rt_pin_read() 讀取引腳電平
rt_pin_attach_irq() 綁定引腳中斷回調(diào)函數(shù)
rt_pin_irq_enable() 使能引腳中斷
rt_pin_detach_irq() 脫離引腳中斷回調(diào)函數(shù)
  • 這些函數(shù)默認(rèn)沒(méi)有使用宏定義RTM_EXPORT將其導(dǎo)出到符號(hào)表,如果動(dòng)態(tài)模塊需要使用,則需要將其導(dǎo)出。
1)獲取引腳編號(hào)
  • 如果使用 rt-thread/bsp/stm32 目錄下的 BSP 則可以使用下面的宏獲取引腳編號(hào)
    • GET_PIN(port, pin)
  • 如果使用其他 BSP 則需要查看 PIN 驅(qū)動(dòng)代碼 drv_gpio.c 文件確認(rèn)引腳編號(hào)。此文件里有一個(gè)數(shù)組存放了每個(gè) PIN 腳對(duì)應(yīng)的編號(hào)信息
    • 如:STM32F429-apollo是基于STM32F4xx_PIN_NUMBERS == 176的芯片,參考rt-thread\bsp\stm32f429-apollo\drivers\drv_gpio.c的pins[]數(shù)組,PB.0和PB.1分別對(duì)應(yīng)index 56和57。

2.ADC

  • 開(kāi)啟adc需要把RT_USING_DEVICE_OPS也打開(kāi),否則看不到adc設(shè)備

    • RT-Thread Kernel → Kernel Device Object → Using ops for each device object
  • rt-thread\bsp\stm32f429-apollo的drivers默認(rèn)沒(méi)有注冊(cè)adc設(shè)備的驅(qū)動(dòng),需要自行添加

    • 其stm32f4xx_hal_conf.h中也沒(méi)有define HAL_ADC_MODULE_ENABLED 需要自行打開(kāi)注釋

3.UART

  • bsp\stm32\stm32f429-atk-apollo中只會(huì)初始化uart1,需要在底層文件中添加uart2和uart3的初始化程序

    • rt-thread\bsp\stm32\stm32f429-atk-apollo\board\CubeMX_Config\Src\stm32f4xx_hal_msp.c是芯片具體的資源配置
    • stm32_configure -> HAL_UART_Init -> HAL_UART_MspInit(UART_HandleTypeDef* huart)
    void HAL_UART_MspInit(UART_HandleTypeDef* huart)
    {
    
      GPIO_InitTypeDef GPIO_InitStruct = {0};
      if(huart->Instance==USART1)
      {
      /* USER CODE BEGIN USART1_MspInit 0 */
          
    
      /* USER CODE END USART1_MspInit 0 */
        /* Peripheral clock enable */
        __HAL_RCC_USART1_CLK_ENABLE();
      
        __HAL_RCC_GPIOA_CLK_ENABLE();
        /**USART1 GPIO Configuration    
        PA9     ------> USART1_TX
        PA10     ------> USART1_RX 
        */
        GPIO_InitStruct.Pin = GPIO_PIN_9|GPIO_PIN_10;
        GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
        GPIO_InitStruct.Pull = GPIO_PULLUP;
        GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
        GPIO_InitStruct.Alternate = GPIO_AF7_USART1;
        HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
        /* USART1 interrupt Init */
        HAL_NVIC_SetPriority(USART1_IRQn, 0, 0);
        HAL_NVIC_EnableIRQ(USART1_IRQn);
      /* USER CODE BEGIN USART1_MspInit 1 */
    
      /* USER CODE END USART1_MspInit 1 */
      }
      
      if (huart->Instance == USART2)
      {
          /* Enable USARTx clock */
          __HAL_RCC_USART2_CLK_ENABLE();
          
          __HAL_RCC_GPIOA_CLK_ENABLE();
          /**USART1 GPIO Configuration    
          PA2     ------> USART2_TX
          PA3     ------> USART2_RX 
          */
          GPIO_InitStruct.Pin = GPIO_PIN_2|GPIO_PIN_3;
          GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
          GPIO_InitStruct.Pull = GPIO_PULLUP;
          GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
          GPIO_InitStruct.Alternate = GPIO_AF7_USART2;
          HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
    
          /* USART1 interrupt Init */
          HAL_NVIC_SetPriority(USART2_IRQn, 0, 1);
          HAL_NVIC_EnableIRQ(USART2_IRQn);
      }
    
      if (huart->Instance == USART3)
      {
          /* Enable USARTx clock */
          __HAL_RCC_USART2_CLK_ENABLE();
          
          __HAL_RCC_GPIOA_CLK_ENABLE();
          /**USART1 GPIO Configuration    
          PB10     ------> USART3_TX
          PB11     ------> USART3_RX 
          */
          GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11;
          GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
          GPIO_InitStruct.Pull = GPIO_PULLUP;
          GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
          GPIO_InitStruct.Alternate = GPIO_AF7_USART3;
          HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
    
          /* USART1 interrupt Init */
          HAL_NVIC_SetPriority(USART2_IRQn, 0, 1);
          HAL_NVIC_EnableIRQ(USART2_IRQn);
      }
    
    }
    
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容