RT-Thread 基于STM32F1xx HAL 库的学习笔记(1)---加入HAL库

目前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,内容如下:

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 
#include 
//  Internal SRAM memory size[Kbytes] <8-64>
//	Default: 64
#define STM32_SRAM_SIZE         64
#define STM32_SRAM_END          (0x20000000 + STM32_SRAM_SIZE * 1024)

//  Console on USART: <0=> no console <1=>USART 1 <2=>USART 2 <3=> USART 3
// 	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的版本信息。




你可能感兴趣的:(嵌入式开发环境)