|
GD32系列MCU作为较罕见的国产MCU产品表现出了很高的品质,特别是GD32F207ZET6芯片为基于Cortex-M3内核的通用MCU属于一款较高端的产品。
目前国产的RTOS更是百花齐放,既有trochiliOS,还有RT-Thread、SylixOS、djyos、raw-os、uTenux等等。在这里选择了uTenux移植到小红板。
uTenux实时操作系统是由大连悠龙软件公司以基于TRON标准的T-Kernel精简版本uT/Kernel为核心开发的,主要针对ARM系列微控制器从ARM7/9至Cortex M系列。在大连悠龙的官网上有关于uTenux的具体介绍,这里不再过多说明。
接下来,对uTenux的移植进行介绍。
根据GD32F207ZE小红板自带的软件(GD32-Colibri-F207ZE-DEMO)我们看到其已经对小红板的led、uart、key等给出了BSP(目录board中),因此这对方便我们移植起到了帮助。本次移植要实现led点亮和uart打印输出的功能以帮助测试uTenux。
从悠龙公司官网下载uTenux的源码包,目前最新版的uTenux为V2.0.00r400版,本移植工作就是针对这一版本进行。解压下载的源码包,可以在其中看到有uTenux的内核文件(source)、说明文件(manual)、代码示例(sample)等多个文件夹。其中uTenux与具体芯片无关的内核文件位于目录/source/uTenux/uTOS中,可将其整体复制到准备新建的工程中使用。
采用Keil MDK 5.16a工具进行移植开发工作。建立的文件目录如图所示,其中
uTOS中存放为上述的uTenux与具体芯片无关的内核文件;
Obj中为建立的keil工程文件;
GD32F207ZET6中为小红板的所有硬件相关文件;
App中为用户主程序和任务应用程序;
实现uTenux在小红板上的移植主要是对tk_config_depend.h、tm_monitor.c和startup_gd32f20x.s三个文件进行修改。
tk_config_depend.h中定义了所移植芯片的一些参数,以及对uTenux的配置参数,具体设置可以参考文件《uTOS内核移植指南_uTenux_uTOS_Porting_Guide_C》;
- #ifndef __TK_CONFIG_DEPEND_H__
- #define __TK_CONFIG_DEPEND_H__
- #ifdef __cplusplus
- extern "C" {
- #endif
- /*
- * Vector ROM region definition, must be same as with startup code.
- */
- #define TK_ROM_VECTORAREA_TOP 0x08000000UL /* ROM VCETOR table start */
- #define TK_ROM_VECTORAREA_END 0x080001A8UL /* ROM VCETOR table end 418B */
- #define TK_ROM_VECTOR_NUMBER 106U /* ROM VCETOR table size */
- /*
- * Kernel RAM region definition, ram region defined in link script must be same.
- */
- #define TK_RAM_TOTALAREA_TOP 0x20000000UL /* Total Internal RAM start */
- #define TK_RAM_VECTORAREA_TOP 0x20000000UL /* RAM VCETOR table start */
- #define TK_RAM_VECTORAREA_END 0x200001A8UL /* RAM VCETOR table end 0.4K */
- #define TK_RAM_BSSDATAAREA_TOP 0x200001A8UL /* Bss and Data area start */
- #define TK_RAM_BSSDATAAREA_END 0x20002000UL /* Bss and Data area end 7.6k */
- #define TK_RAM_SYSTEMAREA_TOP 0x20002000UL /* Kernel malloc area start */
- #define TK_RAM_SYSTEMAREA_END 0x20012000UL /* Kernel malloc area end 64k */
- #define TK_RAM_USERAREA_TOP 0x20012000UL /* User manual area start */
- #define TK_RAM_USERAREA_END 0x20020000UL /* User manual area end 56k */
- #define TK_RAM_STACKAREA_TOP 0x20020000UL /* Stack startup area start */
- #define TK_RAM_STACKAREA_END 0x20020000UL /* Stack startup area end 0k */
- #define TK_RAM_TOTALAREA_END 0x20020000UL /* Total Internal RAM end 128k */
- #define TK_RAM_VECTOR_NUMBER 106U /* RAM VCETOR table size */
- /*
- * Use Chip Deep Sleep ( Stop and Standby ) function
- */
- #define TK_USE_POW_DEEP 0U /* 0isable 1:Enable */
- /*
- * Kernel tick source timer clock function and definition
- */
- #define TK_USE_SYSTICK_LESS 0U /* 0: use systick, 1: use other timer */
- #define KNL_CFG_TIMER_CLOCK 72U /* Timer clock input(MHz)¡ê?select MCK */
- #define KNL_CFG_TIMER_INTLEVEL 0U /* Timer interrupt level */
- #define KNL_CFG_TIMER_PERIOD 10U /* Timer period(ms), between 1 and 50 */
- /*
- * System object number config
- */
- #define KNL_CFG_MAX_TSKID 8
- #define KNL_CFG_MAX_SEMID 4
- #define KNL_CFG_MAX_FLGID 4
- #define KNL_CFG_MAX_MBXID 2
- #define KNL_CFG_MAX_MTXID 2
- #define KNL_CFG_MAX_MBFID 2
- #define KNL_CFG_MAX_PORID 2
- #define KNL_CFG_MAX_MPLID 2
- #define KNL_CFG_MAX_MPFID 2
- #define KNL_CFG_MAX_CYCID 2
- #define KNL_CFG_MAX_ALMID 2
- /*
- * Task priority config
- */
- #define KNL_CFG_MAX_PRI 16U /* Large means low priority */
- /*
- * Use dynamic memory allocation when kernel init
- */
- #define TK_USE_MALLOC 1U
- /*
- * Use dynamic exception and high level programming language handler support define
- */
- #define TK_USE_INT_DEFHDR 1U /* Dynamic exception handler support */
- #define TK_USE_INT_HLLHDR 1U /* High level program language support*/
- /*
- * Use FPU for active FPU function
- */
- #define TK_USE_FPU 0U /* 0isable 1:Enable */
- /*
- * Use clean-up sequence when kernel exit
- */
- #define KNL_CFG_USE_CLEANUP 1U
- /*
- * Debugger support function
- * 0: Invalid
- * 1: Valid
- */
- #define TK_USE_DBGSPT 0U
- /*
- * Use program trace function (in debugger support)
- */
- #define TK_USE_HOOK_TRACE 0U
- /*
- * Use object name to each control block
- * 0: Do not use object name
- * 1: Use object name
- */
- #define TK_USE_OBJ_NAME 1U
- #define TK_OBJ_NAME_LENGTH 8U /* Object name length (Byte) */
- /*
- * Use tm_monitor to output kernel message
- */
- #define TK_USE_TM_MONITOR 1U
- /*
- * Output (error) messages from Kernel
- * 0: Do not output message
- * 1: Output message
- */
- #define TK_USE_MESSAGE 1U
- /*
- * Predefined boot message
- */
- #define KNL_CFG_BOOT_MESSAGE \
- "\n" \
- "-------------------------------------------------------\n" \
- " micro Tenux \n" \
- " Supported MCU is GD32F207ZET6 \n" \
- " (build 0400) \n" \
- " Copyright(c) 2008-2014 by Tenux Open Source Society \n" \
- "-------------------------------------------------------\n" \
- "\n\0"
- #ifdef __cplusplus
- }
- #endif
- #endif /* __TK_CONFIG_DEPEND_H__ */
复制代码
tm_monitor.c中主要是用于uTenux输出信息的一些函数,需要对其与小红板BSP进行适配修改,这里只需小的修改就可和小红板自带DEMO中colibri_bsp_uart.c文件中的函数进行替换;
- #include "colibri_bsp_uart.h"
- #include "gd32f20x.h"
- #include <tm_monitor.h>
- #if TK_USE_TM_MONITOR
- /* Definition of normal control char */
- #define TM_CHAR_NUL 0x00U /* null character */
- #define TM_CHAR_ETX 0x03U /* end of text character */
- #define TM_CHAR_CR 0x0DU /* carriage return character */
- #define TM_CHAR_LF 0x0AU /* line feed character */
- /*
- * Function Name : tm_getchar
- * Create Date : 2013/2/18-2014/4/1
- * Author : wangshb
- * Description : disable interrupt,then receive char from console,util success
- * supported only on wait != 0 (polling not supported)
- * Param : int32_t wait: no used
- * Return Code : int32_t c: char to receive
- */
- int32_t tm_getchar( int32_t wait )
- {
- uint8_t c;
- uint32_t imask;
- char character;
- /* Disable interrupt */
- imask = __get_PRIMASK();
- __set_PRIMASK( 0x1u );
- //c = tm_recvuart();
- EvbUart1ReadByte(&character);
- c = (uint8_t)character;
- /* Enable interrupt */
- __set_PRIMASK( imask );
- return (int32_t)c;
- }
- /*
- * Function Name : tm_getline
- * Create Date : 2013/2/18-2014/4/1
- * Author : wangshb
- * Description : disable interrupt,then receive a line from console,util success
- * special key is not supported
- * Param : uint8_t *buff: buffer to save one line chars
- * Return Code : int32_t len: line length to receive
- */
- int32_t tm_getline( uint8_t *buff )
- {
- int32_t len = 0;
- uint32_t imask;
- /* Disable interrupt */
- imask = __get_PRIMASK();
- __set_PRIMASK( 0x1u );
- for (;;) {
- //*buff = tm_recvuart();
- EvbUart1ReadByte(buff);
- //tm_senduart(*buff); /* echo back */
- EvbUart1WriteByte(*buff);
- if ( *buff == TM_CHAR_CR ) {
- //tm_senduart(TM_CHAR_LF);
- EvbUart1WriteByte(TM_CHAR_LF);
- *buff = TM_CHAR_NUL;
- } else if ( *buff == TM_CHAR_ETX ) {
- *buff = TM_CHAR_NUL;
- len = -1;
- }
- if ( *buff == TM_CHAR_NUL ) {
- break;
- }
- len++;
- buff++;
- }
- /* Enable interrupt */
- __set_PRIMASK( imask );
- return len;
- }
- #endif /* TK_USE_TM_MONITOR */
- /*
- * Function Name : tm_monitor
- * Create Date : 2013/2/18-2013/4/26
- * Author : wangshb
- * Description : Empty loop
- * Param : none
- * Return Code : none
- */
- void tm_monitor( void )
- {
- for(;;) {
- ;
- }
- }
- #if TK_USE_TM_MONITOR
- /*
- * Function Name : tm_putchar
- * Create Date : 2013/2/18-2014/4/1
- * Author : wangshb
- * Description : send a char to console util success
- * Ctrl-C is not supported
- * Param : int32_t c: char to send
- * Return Code : int32_t len: not used
- */
- int32_t tm_putchar( int32_t c )
- {
- uint8_t buf = (uint8_t)c;
- uint32_t imask;
- /* Disable interrupt */
- imask = __get_PRIMASK();
- __set_PRIMASK( 0x1u );
- if (buf == TM_CHAR_LF) {
- //tm_senduart(TM_CHAR_CR);
- EvbUart1WriteByte(TM_CHAR_CR);
- }
- //tm_senduart(buf);
- EvbUart1WriteByte(buf);
- /* Enable interrupt */
- __set_PRIMASK( imask );
- return 0;
- }
- /*
- * Function Name : tm_putstring
- * Create Date : 2013/2/18-2014/4/1
- * Author : wangshb
- * Description : send a string to console util success
- * Ctrl-C is not supported
- * Param : const uint8_t *buff: string to send
- * Return Code : int32_t len: not used
- */
- int32_t tm_putstring( const uint8_t *buff )
- {
- uint32_t imask;
- /* Disable interrupt */
- imask = __get_PRIMASK();
- __set_PRIMASK( 0x1u );
- while ( *buff != TM_CHAR_NUL ) {
- if (*buff == TM_CHAR_LF) {
- //tm_senduart(TM_CHAR_CR);
- EvbUart1WriteByte(TM_CHAR_CR);
- }
- //tm_senduart(*buff);
- EvbUart1WriteByte(*buff);
- buff++;
- }
- /* Enable interrupt */
- __set_PRIMASK( imask );
- return 0;
- }
- #endif /* TK_USE_TM_MONITOR */
复制代码
startup_gd32f20x.s中为小红板的启动文件,是汇编语言写的。这里需要将sysTick和PendSV所对应的中断处理函数替换为uTenux所提供的函数;
- Stack_Size EQU 0x400
- AREA STACK, NOINIT, READWRITE, ALIGN = 3
- Stack_Mem SPACE Stack_Size
- __initial_sp
- ;// <h> Heap Configuration
- ;// <o> Heap Size (in Bytes) <0-4096:8>
- ;// </h>
- Heap_Size EQU 0x200
- AREA HEAP, NOINIT, READWRITE, ALIGN = 3
- __heap_base
- Heap_Mem SPACE Heap_Size
- __heap_limit
- IMPORT knl_dsp_entry [WEAK]
- IMPORT knl_int_tckhdr [WEAK]
- PRESERVE8
- THUMB
- ; Vector table entries with the exceptions ISR address
- AREA RESET, DATA, READONLY
- EXPORT __Vectors
- EXPORT __Vectors_End
- EXPORT __Vectors_Size
- __Vectors DCD __initial_sp ; Top of Stack
- DCD Reset_Handler ; Vector Number 1,Reset Handler
- DCD NMI_Handler ; Vector Number 2,NMI Handler
- DCD HardFault_Handler ; Vector Number 3,Hard Fault Handler
- DCD MemManage_Handler ; Vector Number 4,MPU Fault Handler
- DCD BusFault_Handler ; Vector Number 5,Bus Fault Handler
- DCD UsageFault_Handler ; Vector Number 6,Usage Fault Handler
- DCD 0 ; Reserved
- DCD 0 ; Reserved
- DCD 0 ; Reserved
- DCD 0 ; Reserved
- DCD SVC_Handler ; Vector Number 11,SVCall Handler
- DCD DebugMon_Handler ; Vector Number 12,Debug Monitor Handler
- DCD 0 ; Reserved
- ;DCD PendSV_Handler ; Vector Number 14,PendSV Handler
- ;DCD SysTick_Handler ; Vector Number 15,SysTick Handler
- DCD knl_dsp_entry ; Vector Number 14,knl_dsp_entry
- DCD knl_int_tckhdr ; Vector Number 15,knl_int_tckhdr
复制代码
uTenux启动任务的过程为:
main()->initctsk()->usermain()->App_TaskCreate()->App_TaskStart()
这里建立三个用户任务:tsk_id_LED_R;tsk_id_LED_G;tsk_id_LED_Y分别点亮三个LED并通过uart输出相应的信息。
以上就是对在小红板上移植uTenux的阶段总结。目前移植工作还未完成,存在任务启动后没有输出信息的问题,正在进一步解决中,所以就先不上传代码了。还是先把作业交了占个位置吧。
TRON标 准是国际上嵌入式领域OS开发的一个标准,因此这里对uTenux进行了研究和移植。当然对于RTOS还是要根据开发工作的需要进行选择。对于学习而言更 推荐参考资料全面的trochiliOS,它有和小红板配套的教材《嵌入式实时操作系统原理与最佳实践》。毕竟RTOS的原理基本是类似的,一通百通吗。 |
|