曾是一颗薏米 · 2 天前 · 广东

【Mini-F5265-OB开发板试用测评】RT-Thread的移植(调通串口+LED)

前言

近期,笔者有幸获得灵动微MM32F5265开发板的体验资格。MM32F5260搭载了arm china "Star-MC1 内核"处理器,拥有高性能,主打家电和工业等高可靠性应用领域。

总结一下,有以下亮点:

  • 本土团队打造,完全自主可控,采用全国产化供应链;
  • 基于Armv8-M架构,带有L1 I-Cache & D-Cache,对比市面主流的M3/M4,有20%性能提升;
  • 通过I-Cache实现对flash的零延迟访问,拥有零延迟 AHB 总线矩阵,支持多并发总线;
  • 拥有信号间互联矩阵,可对多个事件进行逻辑组合,可实现较为复杂的功能;

移植

本次rt-thread的移植参考了 “Rice我叫加饭?” 的博文:
https://aijishu.com/a/1060000000347637

参考代码:
https://gitee.com/RiceChen0/mm32f5270\\_rtt
(感谢原作者的付出)

这里我重点说一下不一样的地方:

1.打印重定向到虚拟串口

虽然Mini-F5265-OB开发板上没有板载CH340,但这也不影响交互功能,官方提供了一种新的途径:通过板载的MM32-LINK-OB的虚拟串口来实现串口的交互。

简述实现的流程:

  1. PC通过USB连接板载的MM32-LINK-OB;
  2. 板载的MM32-LINK-OB将USB数据转发成SWD接口信号和串口的tx/rx信号;
  3. 最终信号达到Mini-F5265-OB开发板,实现串口的交互和程序的烧写功能;

板载的MM32-LINK-OB,连接如下图所示:
 title=

Mini-F5265-OB开发板,连接如下图所示:
 title=

因此,移植的第一步就是要用上虚拟串口。
通过查看上述的原理图可知虚拟串口用到uart3。
修改drv\_uart.h,添加uart3支持:

#if defined(BSP_USING_UART3)
#ifndef UART3_CONFIG
#define UART3_CONFIG                                \
    {                                               \
        .name           = "uart3",                  \
        .rx_gpiox       = GPIOC,                    \
        .rx_rcc_clock   = RCC_AHBPeriph_GPIOC,       \
        .rx_pin         = GPIO_Pin_11,              \
        .rx_gpio_af     = GPIO_AF_7,                \
        .tx_gpiox       = GPIOB,                    \
        .tx_rcc_clock   = RCC_AHBPeriph_GPIOC,      \
        .tx_pin         = GPIO_Pin_10,              \
        .tx_gpio_af     = GPIO_AF_7,                \
        .uart_rcc_clock = RCC_APB1Periph_UART3,     \
        .uartx          = UART3,                    \
        .irq_type       = UART3_IRQn,               \
    }
#endif /* UART3_CONFIG */
#endif /* BSP_USING_UART3 */

修改drv\_uart.c,uart3使用的PC10和PC11需要初始化:

static int rt_hw_uart_gpio_init(struct mm32_uart_config *cfg)
{
    GPIO_InitTypeDef GPIO_InitStruct;

    RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART3, ENABLE);
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOC, ENABLE);
    
    GPIO_PinAFConfig(GPIOC, GPIO_PinSource10, GPIO_AF_7);
    GPIO_PinAFConfig(GPIOC, GPIO_PinSource11, GPIO_AF_7);

    GPIO_StructInit(&GPIO_InitStruct);
    GPIO_InitStruct.GPIO_Pin   = GPIO_Pin_10;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_High;
    GPIO_InitStruct.GPIO_Mode  = GPIO_Mode_AF_PP;
    GPIO_Init(GPIOC, &GPIO_InitStruct);

    GPIO_StructInit(&GPIO_InitStruct);
    GPIO_InitStruct.GPIO_Pin  = GPIO_Pin_11;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(GPIOC, &GPIO_InitStruct);
    
    return RT_EOK;
}

修改drv\_uart.c,实现mm32\_uart\_ops(由于篇幅原因,这里仅截取关键部分)

static rt_err_t mm32_control(struct rt_serial_device *serial,
                            int                      cmd,
                            void                     *arg)
{
    struct mm32_uart *uart;
    rt_ubase_t ctrl_arg = (rt_ubase_t)arg;

    RT_ASSERT(serial != RT_NULL);

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

    switch (cmd)
    {
        case RT_DEVICE_CTRL_SET_INT:
        {
            UART_ITConfig(uart->config->uartx, UART_IT_RX, ENABLE);
            NVIC_EnableIRQ(uart->config->irq_type);
            
            break;
        }
        case RT_DEVICE_CTRL_CLR_INT:
        {
            UART_ITConfig(uart->config->uartx, UART_IT_RX, DISABLE);
            NVIC_DisableIRQ(uart->config->irq_type);
            break;
        }

    }
    return 0;
}

static int mm32_putc(struct rt_serial_device *serial, char c)
{
    struct mm32_uart *uart;

    RT_ASSERT(serial != RT_NULL);

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

    UART_SendData(uart->config->uartx, (uint8_t)(c));
    while (RESET == UART_GetFlagStatus(uart->config->uartx, UART_FLAG_TXC)) {};

    return 1;
}

static int mm32_getc(struct rt_serial_device *serial)
{
    struct mm32_uart *uart;
    int ch = -1;

    RT_ASSERT(serial != RT_NULL);

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

    if(UART_GetFlagStatus(uart->config->uartx, UART_FLAG_RXAVL))
    {
        ch = UART_ReceiveData(uart->config->uartx);
        return ch;
    }

    return -1;
}

static void uart_isr(struct rt_serial_device *serial)
{
    struct mm32_uart *uart;

    RT_ASSERT(serial != RT_NULL);

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

    if(SET == UART_GetFlagStatus(uart->config->uartx, UART_IT_RX))
    {
        rt_hw_serial_isr(serial, RT_SERIAL_EVENT_RX_IND);
    }
}

void UART3_IRQHandler(void)
{
    rt_interrupt_enter();

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

    rt_interrupt_leave();
}

2.添加hal库等文件

  1. 从官方的提供的例程资料中找到HAL\_Lib文件夹,将里面的头文件和源文件拷贝工程的libraries/drivers目录里面。
  2. 修改libraries/drivers的mm32f5260.h,定义“USE\_STDPERIPH\_DRIVER”的宏。(注意官方提供的默认没有定义该宏,需要定义后才会编译标准外设驱动库)
  3. 在libraries/drivers目录创建hal\_common.h,并在里面包含"hal\_conf.h",目的是在外面可以调到hal层的函数接口。
  4. 将官方提供的core\_starmc1.h拷贝到工程的libraries/libraries/CMSIS/Include目录下,替换原来的core\_star.h。
  5. 将官方提供的source文件夹里面的文件整理到libraries和mdk目录。

注:以上仅列出关键部分,其余详见代码仓库。

3.实现systisk

跟以往不同的是:本次使用的SDK里面已经实现了对系统时钟的初始化(system\_mm32f5260.c),我们仅需实现systisk即可,代码如下:

void SysTick_Init(void)
{
    uint32_t reload = 0;

    SysTick->CTRL &= (uint32_t)0xFFFFFFFB;

    reload = CLOCK_SYSTICK_FREQ/RT_TICK_PER_SECOND;
    reload--;

    SysTick->CTRL |= SysTick_CTRL_TICKINT_Msk;
    SysTick->LOAD = reload;
    SysTick->CTRL |= SysTick_CTRL_ENABLE_Msk;
}

void SysTick_Handler(void)
{
    /* enter interrupt */
    rt_interrupt_enter();

    rt_tick_increase();

    /* leave interrupt */
    rt_interrupt_leave();
}

void rt_hw_board_init()
{
    SysTick_Init();
    SystemClock_Config();

#if defined(RT_USING_HEAP)
    rt_system_heap_init(HEAP_BEGIN, (void *)HEAP_END);
#endif

#ifdef RT_USING_SERIAL
    extern int rt_hw_uart_init(void);
    rt_hw_uart_init();
#endif

#if defined(RT_USING_CONSOLE) && defined(RT_USING_DEVICE)
   rt_console_set_device(RT_CONSOLE_DEVICE_NAME);
#endif

#ifdef RT_USING_COMPONENTS_INIT
    rt_components_board_init();
#endif
}

移植效果

到此为止,基本上已经完成了移植工作。
编译,烧写,可以到rt-thread的打印:
 title=
查看开发板可看到LED2隔500ms闪烁一次。

总结

本次移植过程修改的地方不多,主要是因为SDK变动而做的修改。在此,可以看到灵动微在维护hal库做出的努力。毕竟hal层兼容性越强,可以吸收更多潜在用户,节省用户熟悉SDK的时间,这也是国产芯片替代的必经之路。
最后,感谢灵动微和极术社区提供的平台,也祝愿国产芯片越来越好。

仓库代码:
https://gitee.com/sakura96888/mm32f5260\_rtt

推荐阅读
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息