引言
在工作闲暇之际,逛逛论坛,无意间看到GD的试用活动,一如既往的积极,在官方还没发布时就申请了,也如愿的收到了板子,感谢官方和社区给了探索这块板子的机会。
Why rtt
RT-Thread Nano 是一个极简版的硬实时内核,它是由 C 语言开发,采用面向对象的编程思维,具有良好的代码风格,是一款可裁剪的、抢占式实时多任务的 RTOS。其内存资源占用极小,功能包括任务处理、软件定时器、信号量、邮箱和实时调度等相对完整的实时操作系统特性。只需内核与Finsh就足够使用,简单方便,个人不喜欢太复杂。
资源
- GD32F427VKT6
- 32位Arm®Cortex®-M4处理器内核
- 高达200 MHz的工作频率
- 3072K Flash
- 256k SRAM
- 4个USART和4个UART,3个I2C,6个SPI,2个I2S,2个CAN2.0B
- 1个SDIO接口、1个10/100M以太网控制器
- 3个采样率高达2.6M SPS的12位高速ADC和2个12位DAC,
- 单循环乘法和硬件除法器
- 浮点单元(FPU)
- 集成DSP指令
- 集成嵌套矢量中断控制器(NVIC)
24位SysTick定时器
板载:
- GDlink(可惜只能作为下载,没有串口)
- 复位按键和用户按键
- 一个用户LED
USB_HS、USB_FS等
开发前准备
- 资料下载地址:
https://aijishu.com/a/1060000000356925
- 安装芯片包
keil安装rtt包
rtt移植
- 打开LED工程
- 添加rtt源码
- board.c处理
- 屏蔽"gd32f4xx_it.c"中HardFault_Handler、PendSV_Handler、 SysTick_Handler函数
- 将裸机的延时函数换成操作系统的延时函数
添加Finsh
在添加Finsh前先准备串口
这里一点需要注意的地方,先上原理图在解释,PA9和PA3已经被占用,使用串口跳过这两个引脚#include "usart.h" #include <stdio.h> #include <rtthread.h> //int fputc(int ch, FILE *f) //{ // /* 将Printf内容发往串口 */ // usart_data_transmit(USART1, (unsigned char) ch); //// while (!(USART1->SR & USART_FLAG_TXE)); // while( usart_flag_get(USART1,USART_FLAG_TC)!= SET); // return (ch); //} void usart_init(int32_t bound) { rcu_periph_clock_enable( RCU_GPIOD); /* enable USART clock */ rcu_periph_clock_enable(RCU_USART1); /* connect port to USARTx_Tx */ gpio_af_set(GPIOD, GPIO_AF_7, GPIO_PIN_5); /* connect port to USARTx_Rx */ gpio_af_set(GPIOD, GPIO_AF_7, GPIO_PIN_6); /* configure USART Tx as alternate function push-pull */ gpio_mode_set(GPIOD, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_5); gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_5); /* configure USART Rx as alternate function push-pull */ gpio_mode_set(GPIOD, GPIO_MODE_AF, GPIO_PUPD_PULLUP,GPIO_PIN_6); gpio_output_options_set(GPIOD, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,GPIO_PIN_6); /* USART configure */ usart_deinit(USART1); usart_baudrate_set(USART1,bound); usart_receive_config(USART1, USART_RECEIVE_ENABLE); usart_transmit_config(USART1, USART_TRANSMIT_ENABLE); // nvic_irq_enable(USART1_IRQn, 2, 0);//设置串口中断的优先级 // //开启串口接收中断 // usart_interrupt_enable(USART1, USART_INT_RBNE); usart_enable(USART1); } //void USART1_IRQHandler(void) //{ // uint8_t rx_data = 0; // //当接收中断发生 // if((RESET != usart_interrupt_flag_get(USART1, USART_INT_FLAG_RBNE)) && // (RESET != usart_flag_get(USART1, USART_FLAG_RBNE))){ // /* Read one byte from the receive data register */ // rx_data = (uint8_t)usart_data_receive(USART1);//获取接收到的数据 //// rt_kprintf("rx_data is %d",rx_data); // } // // //当发送中断发生 // if((RESET != usart_flag_get(USART1, USART_FLAG_TBE)) && // (RESET != usart_interrupt_flag_get(USART1, USART_INT_FLAG_TBE))){ // /* Write one byte to the transmit data register */ // } //}
- 添加Finsh源码
- 在rtconfig.h中打开finsh_config.h
board.c中初始化串口
/* * Copyright (c) 2006-2019, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes * 2021-05-24 the first version */ #include <rthw.h> #include <rtthread.h> #include "systick.h" #include "gd32f4xx.h" #include "usart.h" #if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP) /* * Please modify RT_HEAP_SIZE if you enable RT_USING_HEAP * the RT_HEAP_SIZE max value = (sram size - ZI size), 1024 means 1024 bytes */ #define RT_HEAP_SIZE (20*1024) static rt_uint8_t rt_heap[RT_HEAP_SIZE]; RT_WEAK void *rt_heap_begin_get(void) { return rt_heap; } RT_WEAK void *rt_heap_end_get(void) { return rt_heap + RT_HEAP_SIZE; } #endif void rt_os_tick_callback(void) { rt_interrupt_enter(); rt_tick_increase(); rt_interrupt_leave(); } /* cortex-m 架构使用 SysTick_Handler() */ void SysTick_Handler() { rt_os_tick_callback(); } /** * This function will initial your board. */ void rt_hw_board_init(void) { //#error "TODO 1: OS Tick Configuration." /* * TODO 1: OS Tick Configuration * Enable the hardware timer and call the rt_os_tick_callback function * periodically with the frequency RT_TICK_PER_SECOND. */ systick_config(); SysTick_Config(SystemCoreClock / RT_TICK_PER_SECOND); usart_init(115200); /* Call components board initial (use INIT_BOARD_EXPORT()) */ #ifdef RT_USING_COMPONENTS_INIT rt_components_board_init(); #endif #if defined(RT_USING_USER_MAIN) && defined(RT_USING_HEAP) rt_system_heap_init(rt_heap_begin_get(), rt_heap_end_get()); #endif } #ifdef RT_USING_CONSOLE //static int uart_init(void) //{ //#error "TODO 2: Enable the hardware uart and config baudrate." // return 0; //} //INIT_BOARD_EXPORT(uart_init); void uart_send_byte(rt_uint8_t data) { while( usart_flag_get(USART1,USART_FLAG_TC)!= SET); usart_data_transmit(USART1, (unsigned char) data); } void rt_hw_console_output(const char *str) { //#error "TODO 3: Output the string 'str' through the uart." rt_size_t i = 0, size = 0; char a = '\r'; // __HAL_UNLOCK(&UartHandle); size = rt_strlen(str); for (i = 0; i < size; i++) { if (*(str + i) == '\n') { uart_send_byte(a); } uart_send_byte( *(str + i) ); } } #endif
在finsh_port.c中添加接收代码
/* * Copyright (c) 2006-2021, RT-Thread Development Team * * SPDX-License-Identifier: Apache-2.0 * * Change Logs: * Date Author Notes */ #include <rthw.h> #include <rtconfig.h> #include "usart.h" #ifndef RT_USING_FINSH #error Please uncomment the line <#include "finsh_config.h"> in the rtconfig.h #endif #ifdef RT_USING_FINSH RT_WEAK char rt_hw_console_getchar(void) { /* Note: the initial value of ch must < 0 */ int ch = -1; //#error "TODO 4: Read a char from the uart and assign it to 'ch'." if( usart_flag_get(USART1,USART_FLAG_RBNE) != RESET) //接收中断(接收到的数据必须是0x0d 0x0a结尾) { ch = (uint8_t)usart_data_receive(USART1) & 0xff; // rt_kprintf("ch is %d",ch); } else { if( usart_flag_get(USART1, USART_FLAG_ORERR) != RESET) // { usart_flag_clear(USART1, USART_FLAG_RBNE); } rt_thread_mdelay(10); } return ch; } #endif /* RT_USING_FINSH */
运行结果
- 下载程序,打开终端
- 输入一个命令list_thread