STM32F103使用标准库移植RT-Thread标准版的Finsh

STM32F103使用标准库移植RT-Thread标准版的Finshrtt标准版中stm32的bsp使用的是HAL库,现在想换成标准库。相比于rttnano的移植来说,和标准版的移植还是有不小的差别的,至少我个人这么认为。nano在移植过程中只需要按照#error提示修改好board.c即可。当然如果需要使用finsh的话,你还需要补充完成finsh_board.c和串口的一些信号,具体参见官方文档。整个流程还是相当清晰的,工作量也不大。移植标准版的另一个原因是我想使用ATClient。刚开始我尝试直接向nano版本中进行添加,但似乎…

大家好,又见面了,我是你们的朋友全栈君。

        rtt标准版中stm32的bsp使用的是HAL库,现在想换成标准库。相比于rtt nano的移植来说,和标准版的移植还是有不小的差别的,至少我个人这么认为。nano在移植过程中只需要按照#error提示修改好board.c即可。当然如果需要使用finsh的话,你还需要补充完成finsh_board.c和串口的一些信号,具体参见官方文档。整个流程还是相当清晰的,工作量也不大。

        移植标准版的另一个原因是我想使用AT Client。刚开始我尝试直接向nano版本中进行添加,但似乎nano中不少文件都进行了精简,无奈之下只得重新对rtt进行移植。其实HAL库替换成标准库并不复杂,只是稍微有些麻烦而已。详细的移植过程由于之前没保存就不细写了,下文就finsh移植过程中串口的一些问题做一些记录。此次移植中串口暂不包含DMA。keil文件结构如下:

STM32F103使用标准库移植RT-Thread标准版的Finsh

         在nano版本中,Systick等的适配工作主要在board.c中完成,但在标准版中这部分需要在drv_common.c中处理,大致内容与nano版本差不多:

STM32F103使用标准库移植RT-Thread标准版的Finsh

         对于串口而言,基于HAL库的代码主要在drv_usart.c中对串口的读写控制进行编写,同时完成串口设备向系统的注册。这一部分要修改的内容需要注意,因为HAL库的一些结构体与标准库不同,因此需要按照标准库的要求进行替换和修改,这些工作基本都在drv_usart.h中完成。

STM32F103使用标准库移植RT-Thread标准版的Finsh

        需要注意的是新增的handleInstance元素,它用来表明是哪个串口。对于HAL库而言,似乎这个库的handle中以及有类似的元素存在,因此直接存到handle中了。但标准库的USART_InitTypeDef结构体中尚不支持,所以手动添加这样一个元素,以便后边使用。接着修改drv_usart.c文件,在我的工程中对各个串口的初始化单独写到了USART.c中。因此,串口初始化函数修改后如下:

static rt_err_t stm32_configure(struct rt_serial_device *serial, struct serial_configure *cfg)
{
   struct stm32_uart *uart;
   RT_ASSERT(serial != RT_NULL);
   RT_ASSERT(cfg != RT_NULL);

   uart = rt_container_of(serial, struct stm32_uart, serial);

   uart->handleInstance          = uart->config->Instance;
   uart->handle.USART_BaudRate     = cfg->baud_rate;
   uart->handle.USART_HardwareFlowControl    = USART_HardwareFlowControl_None;
   uart->handle.USART_Mode         = USART_Mode_Rx|USART_Mode_Tx;
//   uart->handle.Init.OverSampling = UART_OVERSAMPLING_16;
   switch (cfg->data_bits)
   {
   case DATA_BITS_8:
       uart->handle.USART_WordLength = USART_WordLength_8b;
       break;
   case DATA_BITS_9:
       uart->handle.USART_WordLength = USART_WordLength_9b;
       break;
   default:
       uart->handle.USART_WordLength = USART_WordLength_8b;
       break;
   }
   switch (cfg->stop_bits)
   {
   case STOP_BITS_1:
       uart->handle.USART_StopBits   = USART_StopBits_1;
       break;
   case STOP_BITS_2:
       uart->handle.USART_StopBits   = USART_StopBits_2;
       break;
   default:
       uart->handle.USART_StopBits   = USART_StopBits_1;
       break;
   }
   switch (cfg->parity)
   {
   case PARITY_NONE:
       uart->handle.USART_Parity     = USART_Parity_No;
       break;
   case PARITY_ODD:
       uart->handle.USART_Parity     = USART_Parity_Odd;
       break;
   case PARITY_EVEN:
       uart->handle.USART_Parity     = USART_Parity_Even;
       break;
   default:
       uart->handle.USART_Parity     = USART_Parity_No;
       break;
   }

#ifdef RT_SERIAL_USING_DMA
   uart->dma_rx.last_index = 0;
#endif

//    if (HAL_UART_Init(&uart->handle) != HAL_OK)
//    {
//        return -RT_ERROR;
//    }
    #ifdef BSP_USING_UART
        if (uart->handleInstance == USART1) {
            USART1_Init(uart->handle.USART_BaudRate);
        }
        if (uart->handleInstance == USART2) {
            USART_DeInit(uart->handleInstance);
            USART2_Init(uart->handle.USART_BaudRate);
        }
        if (uart->handleInstance == USART3) {
            USART_DeInit(uart->handleInstance);
            USART3_Init(uart->handle.USART_BaudRate);
        }
        if (uart->handleInstance == UART4) {
            USART_DeInit(uart->handleInstance);
            UART4_Init(uart->handle.USART_BaudRate);
        }
    #endif
   return RT_EOK;
}

        工程中由于只用4个串口,因此没有对芯片所有的串口资源都做处理。接着,照猫画虎修改控制函数。这个函数我并没有做完整的处理,后面再慢慢修改吧

static rt_err_t stm32_control(struct rt_serial_device *serial, int cmd, void *arg)
{
    struct stm32_uart *uart;
#ifdef RT_SERIAL_USING_DMA
    rt_ubase_t ctrl_arg = (rt_ubase_t)arg;
#endif

    RT_ASSERT(serial != RT_NULL);
    uart = rt_container_of(serial, struct stm32_uart, serial);

    switch (cmd)
    {
    /* disable interrupt */
    case RT_DEVICE_CTRL_CLR_INT:
        /* disable rx irq */
        // rt_kprintf("stop uart irq\n");
    //    NVIC_DisableIRQ(uart->config->irq_type);
        /* disable interrupt */
//        __HAL_UART_DISABLE_IT(&(uart->handle), UART_IT_RXNE);

#ifdef RT_SERIAL_USING_DMA
        /* disable DMA */
        if (ctrl_arg == RT_DEVICE_FLAG_DMA_RX)
        {
            HAL_NVIC_DisableIRQ(uart->config->dma_rx->dma_irq);
            if (HAL_DMA_Abort(&(uart->dma_rx.handle)) != HAL_OK)
            {
                RT_ASSERT(0);
            }

            if (HAL_DMA_DeInit(&(uart->dma_rx.handle)) != HAL_OK)
            {
                RT_ASSERT(0);
            }
        }
        else if(ctrl_arg == RT_DEVICE_FLAG_DMA_TX)
        {
            HAL_NVIC_DisableIRQ(uart->config->dma_tx->dma_irq);
            if (HAL_DMA_DeInit(&(uart->dma_tx.handle)) != HAL_OK)
            {
                RT_ASSERT(0);
            }
        }
#endif
        break;
    /* enable interrupt */
    case RT_DEVICE_CTRL_SET_INT:
        /* enable rx irq */
        // NVIC_EnableIRQ(uart->config->irq_type);
        // rt_kprintf("allow uart irq\n");
    //    HAL_NVIC_SetPriority(uart->config->irq_type, 1, 0);
//        HAL_NVIC_EnableIRQ(uart->config->irq_type);
        /* enable interrupt */
//        __HAL_UART_ENABLE_IT(&(uart->handle), UART_IT_RXNE);
        break;

#ifdef RT_SERIAL_USING_DMA
    case RT_DEVICE_CTRL_CONFIG:
        stm32_dma_config(serial, ctrl_arg);
        break;
#endif

    case RT_DEVICE_CTRL_CLOSE:
        // rt_kprintf("reset uart\n");
       USART_DeInit(uart->handleInstance);
        break;

    }
    return RT_EOK;
}

修改stm32_putc和stm32_getc:

static int stm32_putc(struct rt_serial_device *serial, char c)
{
   struct stm32_uart *uart;
   RT_ASSERT(serial != RT_NULL);

    uart = rt_container_of(serial, struct stm32_uart, serial);
#if defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32F0) \
   || defined(SOC_SERIES_STM32L0) || defined(SOC_SERIES_STM32G0) || defined(SOC_SERIES_STM32H7) \
   || defined(SOC_SERIES_STM32G4)
   uart->handle.Instance->TDR = c;
#else
    USART_SendData(uart->handleInstance, c);
    while (USART_GetFlagStatus(uart->handleInstance, USART_FLAG_TXE) == RESET);
    while (USART_GetFlagStatus(uart->handleInstance, USART_FLAG_TC) == RESET);
#endif
   return 1;
}

static int stm32_getc(struct rt_serial_device *serial)
{
   int ch;
   struct stm32_uart *uart;
   RT_ASSERT(serial != RT_NULL);
   uart = rt_container_of(serial, struct stm32_uart, serial);

   ch = -1;
   if (USART_GetITStatus(uart->handleInstance, USART_IT_RXNE) != RESET)
   {
#if defined(SOC_SERIES_STM32L4) || defined(SOC_SERIES_STM32F7) || defined(SOC_SERIES_STM32F0) \
   || defined(SOC_SERIES_STM32L0) || defined(SOC_SERIES_STM32G0) || defined(SOC_SERIES_STM32H7) \
   || defined(SOC_SERIES_STM32G4)
       ch = uart->config->Instance->RDR & 0xff;
#else
       ch = uart->config->Instance->DR & 0xff;
#endif
   }
   return ch;
}

修改中断处理:

/**
 * Uart common interrupt process. This need add to uart ISR.
 *
 * @param serial serial device
 */
static void uart_isr(struct rt_serial_device *serial)
{
    struct stm32_uart *uart;

    RT_ASSERT(serial != RT_NULL);
    uart = rt_container_of(serial, struct stm32_uart, serial);

    /* UART in mode Receiver -------------------------------------------------*/
    if ((USART_GetFlagStatus(uart->handleInstance, USART_FLAG_RXNE) != RESET) &&
            (USART_GetITStatus(uart->handleInstance, USART_IT_RXNE) != RESET))
    {
        rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
    }
    else
    {
    //    if (USART_GetFlagStatus(uart->handleInstance, UART_FLAG_ORE) != RESET)
    //    {
    //        __HAL_UART_CLEAR_OREFLAG(&uart->handle);
    //    }
       if (USART_GetFlagStatus(uart->handleInstance, USART_FLAG_NE) != RESET)
       {
           USART_ClearFlag(uart->handleInstance, USART_FLAG_NE);
       }
       if (USART_GetFlagStatus(uart->handleInstance, USART_FLAG_FE) != RESET)
       {
           USART_ClearFlag(uart->handleInstance, USART_FLAG_FE);
       }
       if (USART_GetFlagStatus(uart->handleInstance, USART_FLAG_PE) != RESET)
       {
           USART_ClearFlag(uart->handleInstance, USART_FLAG_PE);
       }
#if !defined(SOC_SERIES_STM32L4) && !defined(SOC_SERIES_STM32F7) && !defined(SOC_SERIES_STM32F0) \
    && !defined(SOC_SERIES_STM32L0) && !defined(SOC_SERIES_STM32G0) && !defined(SOC_SERIES_STM32H7) \
    && !defined(SOC_SERIES_STM32G4)
        if (USART_GetFlagStatus(uart->handleInstance, USART_FLAG_LBD) != RESET)
        {
            USART_ClearFlag(uart->handleInstance, USART_FLAG_LBD);
        }
#endif
       if (USART_GetFlagStatus(uart->handleInstance, USART_FLAG_CTS) != RESET)
       {
           USART_ClearFlag(uart->handleInstance, USART_FLAG_CTS);
       }
       if (USART_GetFlagStatus(uart->handleInstance, USART_FLAG_TXE) != RESET)
       {
           USART_ClearFlag(uart->handleInstance, USART_FLAG_TXE);
       }
       if (USART_GetFlagStatus(uart->handleInstance, USART_FLAG_TC) != RESET)
       {
           USART_ClearFlag(uart->handleInstance, USART_FLAG_TC);
       }
        if (USART_GetITStatus(uart->handleInstance, USART_IT_RXNE) != RESET)
        {
            USART_ClearITPendingBit(uart->handleInstance, USART_IT_RXNE); // 清中断标志
        }
    }
}

        uart_isr函数是我个人觉得需要注意的另一处重点。最早开始移植的时候从putty中能看到输出的启动信息,但是无论怎么按键盘rtt控制台都始终没有反应。点灯大法显示串口确实进接收中断了,输出的话rt_kprintf一点毛病都没有,就是输入不行!

官方finsh移植说明是这么写的:

STM32F103使用标准库移植RT-Thread标准版的Finsh

 然后,在rt-thread-3.1.5\src\device.c中找到了rt_device_read函数。。。实现好了

rx_indicate函数没找到,但在rt-thread-3.1.5\components\finsh\shell.c中找到个类似的:

STM32F103使用标准库移植RT-Thread标准版的Finsh

?????????我是真的迷茫了

一气之下套娃实现了一个 rx_indicate()然后在串口1的中断函数中进行调用,结果还是不行。。。

        细看rt-thread-3.1.5\components\finsh\shell.c的代码发现实际上官方文档中说的rx_indicate()十有八九就是上图中finsh_rx_ind这个函数,然后在finsh的初始化中已经对这个函数做了绑定。只要有触发的信号系统会自动调用此回调函数:

STM32F103使用标准库移植RT-Thread标准版的Finsh

这文档是在玩我吗。。。

        无奈之下 再次打开HAL库的工程模板,此模板中对串口的中断做了统一的处理,也就是通过uart_isr函数对串口的相关标志位进行清除,然后通过rt_hw_serial_isr函数对系统进行通知。之后系统便会通过stm32_getc来获取输入。所以,重点便是rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);

这大坑踩得是真酸爽

往后基本就没什么修改的了,USART中断统一的制式:

void USART1_IRQHandler(void)
{
    /* enter interrupt */
    rt_interrupt_enter();          //在中断中一定要调用这对函数,进入中断
    
    uart_isr(&(uart_obj[UART1_INDEX].serial));

    /* leave interrupt */
    rt_interrupt_leave();    //在中断中一定要调用这对函数,离开中断
}

void USART2_IRQHandler(void)
{
    /* enter interrupt */
    rt_interrupt_enter();          //在中断中一定要调用这对函数,进入中断

    uart_isr(&(uart_obj[UART2_INDEX].serial));

    /* leave interrupt */
    rt_interrupt_leave();    //在中断中一定要调用这对函数,离开中断
}
......

编译、烧写,Finsh总算搞定了:

STM32F103使用标准库移植RT-Thread标准版的Finsh

 下一步准备AT Client,希望一切顺利。。。

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/146225.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)
blank

相关推荐

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号