RT-Thread 基于STM32F1xx HAL 库的学习笔记(1)---加入HAL库
2016-12-02 19:14
706 查看
目前RT-Thread 2.1.0的关于STM32F系列的库的驱动大部分还是标准库的的,在BSP目录中,有stm32f411-nucleo分支和stm32f7-disco是基于HAL库的,但STM32F1系列还没有HAL的支持,借助此次学习机会,现将HAL库移植到RT-Thread 2.1.0的STM32F10x分支中。
移植环境:开发板 arm fly V3开发板,编译环境 Keil MDK 5 ,win7 64平台
【1】 将rt-thread-2.1.0\bsp目录下的stm32f10x复制一份,然后重命名成stm32f10x-curer。
【2】 将Libraries目录下的文件和文件夹更换成新的CMSIS文件夹和STM32F1xx_HAL_Driver,SConscript保留。
【3】 用Note Plus打开stm32f10x-curer根目录下rtconfig.py,定位到32行附近,指定ARMCC编译器的安装位置,修改如下:
if CROSS_TOOL == 'gcc':
PLATFORM = 'gcc'
EXEC_PATH = 'D:/SourceryGCC/bin'
elif CROSS_TOOL == 'keil':
PLATFORM = 'armcc'
EXEC_PATH = 'D:/Keil_v5'
elif CROSS_TOOL == 'iar':
PLATFORM = 'iar'
IAR_PATH = 'C:/Program Files/IAR Systems/Embedded Workbench 6.0 Evaluation'
if os.getenv('RTT_EXEC_PATH'):
EXEC_PATH = os.getenv('RTT_EXEC_PATH')
然后保存。
【4】在STM32F1xx_HAL_Driver目录下添加一个SConscript,内容如下:
【5】复制stm32f411-nucleo\drivers分支目录下的drv_usart.c和drv_usart.h,drv_led.c和drv_led.h,然后修改之。
【6】修改drv_uart.c,下面是代码有修改的部分,可以对照一下
在修改drv_uart.c之前先修改下\stm32f10x-curer\drivers目录下的Conscript脚本,修改如下:
# add the general drivers.
src = Split("""
board.c
stm32f1xx_it.c
drv_led.c
drv_usart.c
""")
然后修改drv_uart.c,结果如下:
关注下上面代码的条件编译,原文件写的有些乱,我在这里整理了下。
【7】打开board.c,定位到210行附近,加入系统时钟使能,代码修改如下:
注意上面HAL_RCC_GetHCLKFreq()/1000是两次systimer中断间隔时间,相应地在rtconfig.h中也要修改成
还要注意下board.h文件中的内容,不然在切换UART1和UART2时可能会有莫名其妙的错误
【10】检查下rtconfig.h,可以把不相关的功能关掉,请确保#define RT_USING_UART1已经打开。
【11】先在命令行中执行下scons --target=mdk5 -s重新生成下工程,当然前提是已经安装了python 2.7.1 和scons 2.5.x。
重新生成工程以后,在keiMDK 5中打开此工程,先尝试编译下,自行解决下编译错误,正常情况下,可以编译通过,下载到开发板之后,可以看到led灯闪烁,在串行终端中可以可看到rt-thread的版本信息。
移植环境:开发板 arm fly V3开发板,编译环境 Keil MDK 5 ,win7 64平台
【1】 将rt-thread-2.1.0\bsp目录下的stm32f10x复制一份,然后重命名成stm32f10x-curer。
【2】 将Libraries目录下的文件和文件夹更换成新的CMSIS文件夹和STM32F1xx_HAL_Driver,SConscript保留。
【3】 用Note Plus打开stm32f10x-curer根目录下rtconfig.py,定位到32行附近,指定ARMCC编译器的安装位置,修改如下:
if CROSS_TOOL == 'gcc':
PLATFORM = 'gcc'
EXEC_PATH = 'D:/SourceryGCC/bin'
elif CROSS_TOOL == 'keil':
PLATFORM = 'armcc'
EXEC_PATH = 'D:/Keil_v5'
elif CROSS_TOOL == 'iar':
PLATFORM = 'iar'
IAR_PATH = 'C:/Program Files/IAR Systems/Embedded Workbench 6.0 Evaluation'
if os.getenv('RTT_EXEC_PATH'):
EXEC_PATH = os.getenv('RTT_EXEC_PATH')
然后保存。
【4】在STM32F1xx_HAL_Driver目录下添加一个SConscript,内容如下:
import rtconfig Import('RTT_ROOT') from building import * # get current directory cwd = GetCurrentDir() # The set of source files associated with this SConscript file. src = Glob('Src/*.c') path = [cwd + '/Inc'] CPPDEFINES = ['USE_HAL_DRIVER'] group = DefineGroup('STM32F1xx_HAL_Driver', src, depend = [''], CPPPATH = path, CPPDEFINES = CPPDEFINES) Return('group')然后保存。如果没有HAL库,可以下载一个STM32F CubeMX软件生成一个,很方便。
【5】复制stm32f411-nucleo\drivers分支目录下的drv_usart.c和drv_usart.h,drv_led.c和drv_led.h,然后修改之。
int rt_led_hw_init(void) { GPIO_InitTypeDef GPIO_InitStruct; /* GPIO Ports Clock Enable */ __HAL_RCC_GPIOF_CLK_ENABLE(); /* Configure GPIO pin: PI1 (LD1) */ GPIO_InitStruct.Pin = GPIO_PIN_6; GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; GPIO_InitStruct.Pull = GPIO_PULLDOWN; GPIO_InitStruct.Speed = GPIO_SPEED_LOW; HAL_GPIO_Init(GPIOF, &GPIO_InitStruct); return 0; } INIT_BOARD_EXPORT(rt_led_hw_init);因为arm fly V3的LED灯端口控制引脚是PF6,所以上面代码也要相应改过来。
【6】修改drv_uart.c,下面是代码有修改的部分,可以对照一下
在修改drv_uart.c之前先修改下\stm32f10x-curer\drivers目录下的Conscript脚本,修改如下:
# add the general drivers.
src = Split("""
board.c
stm32f1xx_it.c
drv_led.c
drv_usart.c
""")
然后修改drv_uart.c,结果如下:
#if defined(RT_USING_UART1) /* UART1 device driver structure */ static struct drv_uart uart1; struct rt_serial_device serial1; void USART1_IRQHandler(void) { struct drv_uart *uart; uart = &uart1; /* enter interrupt */ rt_interrupt_enter(); /* UART in mode Receiver -------------------------------------------------*/ if ((__HAL_UART_GET_FLAG(&uart->UartHandle, UART_FLAG_RXNE) != RESET) && (__HAL_UART_GET_IT_SOURCE(&uart->UartHandle, UART_IT_RXNE) != RESET)) { rt_hw_serial_isr(&serial1, RT_SERIAL_EVENT_RX_IND); /* Clear RXNE interrupt flag */ __HAL_UART_CLEAR_FLAG(&uart->UartHandle, UART_FLAG_RXNE); } /* leave interrupt */ rt_interrupt_leave(); } #endif /* RT_USING_UART1 */ #if defined(RT_USING_UART2) /* UART1 device driver structure */ static struct drv_uart uart2; struct rt_serial_device serial2; void USART2_IRQHandler(void) { struct drv_uart *uart; uart = &uart2; /* enter interrupt */ rt_interrupt_enter(); /* UART in mode Receiver -------------------------------------------------*/ if ((__HAL_UART_GET_FLAG(&uart->UartHandle, UART_FLAG_RXNE) != RESET) && (__HAL_UART_GET_IT_SOURCE(&uart->UartHandle, UART_IT_RXNE) != RESET)) { rt_hw_serial_isr(&serial2, RT_SERIAL_EVENT_RX_IND); /* Clear RXNE interrupt flag */ __HAL_UART_CLEAR_FLAG(&uart->UartHandle, UART_FLAG_RXNE); } /* leave interrupt */ rt_interrupt_leave(); } #endif /* RT_USING_UART2 */ /** * @brief UART MSP Initialization * This function configures the hardware resources used in this example: * - Peripheral's clock enable * - Peripheral's GPIO Configuration * - NVIC configuration for UART interrupt request enable * @param huart: UART handle pointer * @retval None */ void HAL_UART_MspInit(UART_HandleTypeDef *huart) { GPIO_InitTypeDef GPIO_InitStruct; #if defined(RT_USING_UART1) if (huart->Instance == USART1) { /*##-1- Enable peripherals and GPIO Clocks #################################*/ /* Enable GPIO TX/RX clock */ USART1_TX_GPIO_CLK_ENABLE(); USART1_RX_GPIO_CLK_ENABLE(); /* Enable USARTx clock */ USART1_CLK_ENABLE(); /*##-2- Configure peripheral GPIO ##########################################*/ /* UART TX GPIO pin configuration */ GPIO_InitStruct.Pin = USART1_TX_PIN; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(USART1_TX_GPIO_PORT, &GPIO_InitStruct); /* UART RX GPIO pin configuration */ GPIO_InitStruct.Pin = USART1_RX_PIN; GPIO_InitStruct.Mode = GPIO_MODE_AF_INPUT; HAL_GPIO_Init(USART1_RX_GPIO_PORT, &GPIO_InitStruct); HAL_NVIC_SetPriority(USART1_IRQn, 0, 1); HAL_NVIC_EnableIRQ(USART1_IRQn); } #endif /* RT_USING_UART1 */ #if defined(RT_USING_UART2) if (huart->Instance == USART2) { /*##-1- Enable peripherals and GPIO Clocks #################################*/ /* Enable GPIO TX/RX clock */ USART2_TX_GPIO_CLK_ENABLE(); USART2_RX_GPIO_CLK_ENABLE(); /* Enable USARTx clock */ USART2_CLK_ENABLE(); /*##-2- Configure peripheral GPIO ##########################################*/ /* UART TX GPIO pin configuration */ GPIO_InitStruct.Pin = USART2_TX_PIN; GPIO_InitStruct.Mode = GPIO_MODE_AF_PP; GPIO_InitStruct.Pull = GPIO_PULLUP; GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; HAL_GPIO_Init(USART2_TX_GPIO_PORT, &GPIO_InitStruct); /* UART RX GPIO pin configuration */ GPIO_InitStruct.Pin = USART2_RX_PIN; GPIO_InitStruct.Mode = GPIO_MODE_AF_INPUT; HAL_GPIO_Init(USART2_RX_GPIO_PORT, &GPIO_InitStruct); HAL_NVIC_SetPriority(USART2_IRQn, 0, 1); HAL_NVIC_EnableIRQ(USART2_IRQn); } #endif /* RT_USING_UART2 */ } /** * @brief UART MSP De-Initialization * This function frees the hardware resources used in this example: * - Disable the Peripheral's clock * - Revert GPIO and NVIC configuration to their default state * @param huart: UART handle pointer * @retval None */ void HAL_UART_MspDeInit(UART_HandleTypeDef *huart) { #if defined(RT_USING_UART1) if (huart->Instance == USART1) { /*##-1- Reset peripherals ##################################################*/ USART1_FORCE_RESET(); USART1_RELEASE_RESET(); /*##-2- Disable peripherals and GPIO Clocks #################################*/ /* Configure UART Tx as alternate function */ HAL_GPIO_DeInit(USART1_TX_GPIO_PORT, USART1_TX_PIN); /* Configure UART Rx as alternate function */ HAL_GPIO_DeInit(USART1_RX_GPIO_PORT, USART1_RX_PIN); HAL_NVIC_DisableIRQ(USART1_IRQn); } #endif /* RT_USING_UART2 */ #if defined(RT_USING_UART2) if (huart->Instance == USART2) { /*##-1- Reset peripherals ##################################################*/ USART2_FORCE_RESET(); USART2_RELEASE_RESET(); /*##-2- Disable peripherals and GPIO Clocks #################################*/ /* Configure UART Tx as alternate function */ HAL_GPIO_DeInit(USART2_TX_GPIO_PORT, USART2_TX_PIN); /* Configure UART Rx as alternate function */ HAL_GPIO_DeInit(USART2_RX_GPIO_PORT, USART2_RX_PIN); HAL_NVIC_DisableIRQ(USART2_IRQn); } #endif /* RT_USING_UART2 */ } int hw_usart_init(void) { struct drv_uart *uart; struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; #ifdef RT_USING_UART1 uart = &uart1; uart->UartHandle.Instance = USART1; serial1.ops = &drv_uart_ops; serial1.config = config; /* register UART1 device */ rt_hw_serial_register(&serial1, "uart1", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, uart); #endif /* RT_USING_UART1 */ #ifdef RT_USING_UART2 uart = &uart2; uart->UartHandle.Instance = USART2; serial2.ops = &drv_uart_ops; serial2.config = config; /* register UART2 device */ rt_hw_serial_register(&serial2, "uart2", RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX, uart); #endif /* RT_USING_UART2 */ return 0; } INIT_BOARD_EXPORT(hw_usart_init);
关注下上面代码的条件编译,原文件写的有些乱,我在这里整理了下。
【7】打开board.c,定位到210行附近,加入系统时钟使能,代码修改如下:
if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) { while(1); } /**Configure the Systick interrupt time */ HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000); /**Configure the Systick */ HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK); /* SysTick_IRQn interrupt configuration */ HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0);
/** * This function will initial STM32 board. */ void rt_hw_board_init() { HAL_Init(); /* Configure the system clock @ 72 Mhz */ SystemClock_Config(); __CRC_CLK_ENABLE(); hw_usart_init(); #ifdef RT_USING_HEAP rt_system_heap_init((void *)HEAP_BEGIN, (void *)HEAP_END); #endif #ifdef RT_USING_COMPONENTS_INIT rt_components_board_init(); #endif #ifdef RT_USING_CONSOLE rt_console_set_device(CONSOLE_DEVICE); #endif }
注意上面HAL_RCC_GetHCLKFreq()/1000是两次systimer中断间隔时间,相应地在rtconfig.h中也要修改成
/* Tick per Second */ #define RT_TICK_PER_SECOND 1000
还要注意下board.h文件中的内容,不然在切换UART1和UART2时可能会有莫名其妙的错误
#include <stm32f1xx.h> #include <stm32f1xx_hal.h> // <o> Internal SRAM memory size[Kbytes] <8-64> // <i>Default: 64 #define STM32_SRAM_SIZE 64 #define STM32_SRAM_END (0x20000000 + STM32_SRAM_SIZE * 1024) // <o> Console on USART: <0=> no console <1=>USART 1 <2=>USART 2 <3=> USART 3 // <i>Default: 1 #define STM32_CONSOLE_USART 1 #if STM32_CONSOLE_USART == 0 #define CONSOLE_DEVICE "no" #elif STM32_CONSOLE_USART == 1 #define CONSOLE_DEVICE "uart1" #elif STM32_CONSOLE_USART == 2 #define CONSOLE_DEVICE "uart2" #elif STM32_CONSOLE_USART == 3 #define CONSOLE_DEVICE "uart3" #endif【8】修改drv_led.h的引脚操作
#ifndef __DRV_LED_H #define __DRV_LED_H //#include "board.h" #define rt_led_on() HAL_GPIO_WritePin(GPIOF, GPIO_PIN_6, GPIO_PIN_SET) #define rt_led_off() HAL_GPIO_WritePin(GPIOF, GPIO_PIN_6, GPIO_PIN_RESET) int rt_led_hw_init(void); #endif【9】检查下stm32f1xxx_hal_conf.h中的相关开关项,如果有的功能块没有打开,会产生错误。
【10】检查下rtconfig.h,可以把不相关的功能关掉,请确保#define RT_USING_UART1已经打开。
【11】先在命令行中执行下scons --target=mdk5 -s重新生成下工程,当然前提是已经安装了python 2.7.1 和scons 2.5.x。
重新生成工程以后,在keiMDK 5中打开此工程,先尝试编译下,自行解决下编译错误,正常情况下,可以编译通过,下载到开发板之后,可以看到led灯闪烁,在串行终端中可以可看到rt-thread的版本信息。
相关文章推荐
- RT-Thread 基于STM32F1xx HAL 库的学习笔记(2)---加入pin功能支持
- RT-Thread 学习笔记(八)---开启基于SPI Flash的elmfat文件系统(下)
- RT-Thread 学习笔记(十三)--- 开启基于RTGUI的LCD显示功能(3)<触屏屏驱动移植和测试>
- RT-Thread 学习笔记(九)---开启基于SD卡中的 Elm FatFS 文件系统
- RT-Thread 学习笔记(十二)--- 开启基于RTGUI的LCD显示功能(2)<编译测试>
- RT-Thread 学习笔记(十) --- 开启基于LWIP协议的网络功能
- RT-Thread 学习笔记(十一)--- 开启基于RTGUI的LCD显示功能(1)<LCD驱动接口移植>
- RT-Thread 学习笔记(七)---开启基于SPI Flash的elmfat文件系统(中)
- RT-Thread 学习笔记(六)--- 开启基于SPI Flash的elmfat文件系统(上)
- RT-Thread 学习笔记(二)---配置github代码版本控制工具
- STM32 + RT Thread OS 学习笔记[六]
- RT-Thread 学习笔记(四)---用Eclipse构建编译环境
- 优先级反转实验,使用信号量实现【RT-Thread学习笔记 5】
- STM32 + RT Thread OS 学习笔记[二]
- STM32 + RT Thread OS 学习笔记[二]
- RT-Thread 学习笔记(五)---编辑、下载、调试程序
- 线程让出实验【RT-Thread学习笔记 4】
- 线程优先级抢占实验【RT-Thread学习笔记 3】
- STM32 + RT Thread OS 学习笔记[四]