1、使用的uTenux内核代码:http://www.uloong.cc/cn/download/uTenux_V1.6.00r180.zip
2、uTenux的特性:
1、微内核 2、开放源码、完全免费 3、不需要MMU,占用ROM/RAM少 4、可移植、可固化、可裁剪 5、抢占式实时多任务操作系统 6、支持所有32位ARM7/9和Cortex M系列的微控制器 7、可配置任意多个的任务、任务的优先级最多255个
3、实验软硬件环境:
OS软件版本:uTexux1.60
开发板:STM32F4 Discovery
工具链:MDK470
4、最新版本使用单工程形式给出,不用再为查找不到变量而担心。而旧版本OS的各个部分分成了独立的工程,看代码相对比较麻烦点,就连写代码时候,MDK的语法提示功能都不能使用。
5、依赖于宏定义和目录结构的头文件引用
uT工程中包含了很多芯片配置和应用,估计是为了方便编译和扩展,使用了一种很奇怪的头文件引用方式。对于一般的开发,感觉很繁琐。
比如,我使用STM32F4VG这个芯片,按照悠龙提供的配置手册就要打开D:\uLoong\uTenux\bin\app_stm32f4\workspace.uvmpw这个工程文件。
在这个工程的编译选项里边,定义了这么几个宏定义:_APP_STM32F4_,_CHIP_STM32F407VG_,CPU_ARMV7E_M。
在Appusermain工程的usermain.c文件中,我们可以看到这么个引用:
#include <tk_config.h>
tk_config.h文件位于D:\uLoong\uTenux\config目录下,这个文件中有这么个引用:
#include <sysdepend/tk_config_common.h>
我们可以在sysdepend这个文件夹找到tk_config_common.h。这里就将引用导向了另外一个位置。
在文件tk_config_common.h中,宏定义就开始登场了:这个文件里做的是一些根据宏定义而进行的条件编译。这里的条件编译,同样是将引用指向另外的位置。
在F4的工程中定义了_APP_STM32F4_于是,引用又导向到了sysdepend/app_stm32f4/tk_config_depend.h
同样,这个tk_config_depend.h也在做根据宏定义的导向:
#ifdef _CHIP_STM32F407IG_ #include <sysdepend/app_stm32f4/chip_stm32f407ig/tk_config_depend.h> #endif #ifdef _CHIP_STM32F407VG_ #include <sysdepend/app_stm32f4/chip_stm32f407vg/tk_config_depend.h> #endif #ifdef _CHIP_STM32F407ZG_ #include <sysdepend/app_stm32f4/chip_stm32f407zg/tk_config_depend.h> #endif我们定义了_CHIP_STM32F407VG_于是引用被最终导向到了这里
D:\uLoong\uTenux\config\sysdepend\app_stm32f4\chip_stm32f407vg\tk_config_depend.h
这才是真正的系统配置文件。各种芯片信息都在这里了。
还有几个地方使用的也是这种配置引用导向的方式,比如各种MakeFile,暂时还没去关心。
这种引用方式,对于程序的扩展,添加更多的MCU确实很方便。可是我在看代码的时候却费死了劲。也许悠龙这么做,就是为了让俺们不要关心最底层的代码吧!
6、一点总结:
1、uT的WorkSpace里边所有的工程都会引用根目录下include和config这两个文件夹。
2、使用宏定义确定使用的是哪个系列的哪种芯片。如果uT没有提供,可以自己加。
3、uT的跳转很多,引用包含很多。但是结构一致,搞懂一个剩下的就容易了。
4、要添加自己的驱动,将文件放到D:\uLoong\uTenux\lib\libdev\src\sysdepend\app_stm32f4中,并将驱动文件添加到工程目录的libdev目录里。
5、各个工程有不同的分工,写哪个部分将哪个工程设置为活跃,不然就会有各种难题出现。
7、每次修改代码之后,都要Batch Build。
Bin这个工程每次都需要重新编译
Appusermain工程中操作使用OS提供的功能,比如创建/删除任务。当更改这个工程内容时需要重新编译
Kernel工程只需要在首次编译时候或者修改了配置文件之后编译下即可,因为我们一般是不需要修改内核的。
Libcpu、libtm、libdev在修改了与芯片有关的内容时候才需要重新编译。
8、关于工程中的libtm
这个工程中,有用到 tm_monitor这个东西。
昨天咨询了uTenux的工程师,工程中tm_monitor是一只打开的,不管配置文件中的USE_TMONITOR是1还是0.
于是,这个monitor就完全可以作为一个串口处理类来使用了。
先了解一下tm_monitor.c中的几个函数(内核规范中没得介绍,可能是因为不属于内核吧)。
1、uint32_t tm_getchar( uint32_t wait );
关中断,然后从控制台接收字符。
2、uint32_t tm_getline( uint8_t *buff );
关中断,然后接收一行字符。直到遇见结束符(空字符)
3、void tm_monitor( void );
就是一个空的for死循环
4、uint32_t tm_putchar( uint32_t c );
向控制台发送一个字符
5、uint32_t tm_putstring( const uint8_t *buff );
向控制台发送字符串
这里的各个功能都依赖于串口实现。串口的实现在libdev中的ts_uart.c中完成。只有三个函数:初始化,接收字符,发送字符:
1、void uart_init(void)
串口初始化
2、void uart_sendchar(uint8_t c)
串口发送一个字符
3、uint8_t uart_recvchar(void)
通过串口接收一个字符。如果没有字符进来,就一直死循环。
9、向工程中添加底层驱动:
将驱动文件放入D:\uLoong\uTenux\lib\libdev\src\sysdepend\app_at91sam3文件夹中
将文件添加到工程libdev的src目录中
在D:\uLoong\uTenux\include\dev\sysdepend\ts_devdef_common.h中添加对驱动头文件的引用。
将硬件初始化函数添加到文件D:\uLoong\uTenux\include\dev\sysdepend\ts_devdef_common.h中的函数Inline void bsp_init ( void )中。
重新编译。之后就可以使用你写的硬件驱动了。
当然,想文件中添加这些内容的时候,要注意宏定义,别搞错了MCU
10、在示例工程中打开STM32F4的FPU功能
先在编译选项中设置使用FPU,然后在内核文件knl_kernel.h中第97行设置即可
#define __FPU_PRESENT 1
当然,我不知道为什么要用FPU。但是有这个功能就打开好了