ucos-ii在ti dsp 28377芯片上的运行过程和移植过程

2017/2/10 ucos­ii ti dsp 28377 芯片上的运行过程和移植过程 ­ havihouston ­ 博客园
http://www .cnblogs.com/havihouston/p/6387631.html 1/10
1 、移植过程
在将
ucos 移植到 28377d 平台上时主要遇见了下面几个问题,
1 ) 文件怎么组织,是通过修改 micrim 上提供的 28335 一直代码修改而成的,下载地址为: https://www.micrium.com/
2 )移植完成后发现创建任务完成后,任务无法跳转,移植在主函数中来回循环
3 )当使用 ostimedly ()函数对任务延时,当延时时间已经完成,系统无法跳出空任务循环,移植在 IdleTask 中运行
4 )任务切换过程中总是跳入到异常中断中。
移植思路:

开始移植过程时,下载了micrium官网上提供的关于28335的移植历程,他的历程导入后整体框架如下图所示:


上图中主要包含了

上图中主要包含了 5 个文件夹分别是 APP BSP UC­CPU UC­LIB UCOS­II
APP
主要包含了应用代码,主要是官方自己编写的一个小程序,其中各种 .h 文件是对 ucos 的一些配置
BSP 称作板级支持包,这个就按照通俗理解的官方提供的历程中所使用的各种 .c 文件,比如我需要控制 IO 口,就要使用 F2837xD_GPIO.C 中的一
些函数,这些就是
BSP
UC­CPU
暂时未用,好像有包含
UC­LIB 暂时未用,貌似是一些支持库,但是 F28377D 本身自带就有一些运算支持库
UCOS­II 这个是重头戏,里面包含了两个文件夹
source 文件夹下是 ucos 的无关核代码,这些不需要修改
prots­>c28x­>generic­>ccs 里面的代码是和内核有关的代码,无非也就是操作堆栈,保存 cpu 的当前寄存器值以及恢复等等,这些是
需要修改的
但是下载的代码已经帮我们修改好了。直接使用
最开始的移植思路是 :
BSP 板级支持包不使用 micrum 提供的,查阅代码可以发现 BSP 中无非就是对外设的控制和上电初始化芯片的过程,这些完全可以倒入一个
F28377D 的历程
使用历程中的例子来完成初始化,这样更加方便
提供给
ucos 的时间中断,这个就人为的使用 cputimer 来做一个中断,中断函数里面调用 ostimetick 函数来实现。
步骤如下:

首先在28377D的历程中导入一个blink灯闪的历程,修改后的框架如下图所示:



同样包含了下面几个文件夹,这个只是我自己用的,和历程不一样,这个是随意的:
cmd driver pcore uc­cpu uc­lib ucos­ii
cmd
中存放的是历程的 cmd 文件
driver 存放的就是那些调用外设的驱动程序,也就是用来替换 BSP
pcore 是放置应用程序的。 h 文件的定义,直接从 micrum 中复制过来的
uc­cpu uc­lib ucos­ii 是和 micrum 提供的源码一样的(复制过来的)
主函数被放置在了
processflow 中,这里没有打开显示。
代码如下所示:
修改后的
mian 函数如下:


#include <string.h>
#include "F28x_Project.h"
#include "F2837xD_Ipc_drivers.h "
#include <app_cfg.h>
#include <ucos_ii.h>
#include <cpu_core.h>
#include <lib_def.h>
__interrupt void cpu_timer0_isr(void);
//#pragma CODE_SECTION(App_TaskStartStk , "RAMGS0");
//#pragma CODE_SECTION(App_TaskPendStk , "RAMGS0");
//#pragma CODE_SECTION(App_TaskPostStk , "RAMGS0");
CPU_STK_SIZE App_TaskStartStk[APP_CFG_TASK_STK_SIZE];
/* Ping Task's stack. */
CPU_STK_SIZE App_TaskPendStk[APP_CFG_TASK_STK_SIZE];
/* Pong Task's stack. */
CPU_STK_SIZE App_TaskPostStk[APP_CFG_TASK_STK_SIZE];
static OS_EVENT *AppTaskObjSem;
/*********************************************************************************************
************
* FUNCTION PROTOTYPES
**********************************************************************************************
***********
*/
/* Start Task.*/
static void App_TaskStart(void *p_arg);
/* Ping Task. */
//static void App_TaskPing (void *p_arg);
/* Pong Task. */
static void App_TaskPong (void *p_arg);
void cpu_timer0_isr(void)
{
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
OSIntEnter();
OSTimeTick();
OSIntExit();
}
void CPU_Initfunc(void){
InitSysCtrl();
//memcpy(&RamfuncsRunStart,&RamfuncsLoadStart,(size_t)&RamfuncsLoadSize);
InitFlash();
//IPCBootCPU2(C1C2_BROM_BOOTMODE_BOOT_FROM_FLASH);
//CsmUnlock();
InitGpio();
DINT;
InitPieCtrl();
IER = 0x0000;
IFR = 0x0000;
InitPieVectTable();
EINT; // Enable Global interrupt INTM
ERTM; // Enable Global realtime interrupt DBG
}
void BSP_INIT(void){
GPIO_SetupPinMux(10, GPIO_MUX_CPU1, 0);
GPIO_SetupPinOptions( 10, GPIO_OUTPUT, GPIO_ASYNC);
}
void BSP_LED_Off(void){
GpioDataRegs.GPADAT.bit.GPIO10= 0;
}
void BSP_Tick_Init(void){
EALLOW; // This is needed to write to EALLOW protected registers
PieVectTable.TIMER0_INT = & cpu_timer0_isr;
EDIS; // This is needed to disable write to EALLOW protected registers
InitCpuTimers();
//CpuTimer0 时间为设置扫频之间的等待时间 1000 代表1ms
//CpuTimer1为采样定时器时间设置
ConfigCpuTimer(&CpuTimer0, 200, 100000);
CpuTimer0Regs.TCR.all = 0x4000; // Use write­only instruction to set TSS bit = 0
IER |= M_INT1;
IER |= M_INT13;
//IER |= M_INT14;
CpuTimer0Regs.TCR.bit.TSS =1;
PieCtrlRegs.PIEIER1.bit.INTx7= 1;
EINT; // Enable Global interrupt INTM
ERTM; // Enable Global realtime interrupt DBGM
CpuTimer0Regs.TCR.all = 0x4000;
}
void BSP_LED_Toggle(void){
GpioDataRegs.GPATOGGLE.bit.GPIO10= 1;
}
int main (void)
{
/* Initialize the CPU and Board. */
//CPU_Init();
//BSP_Init();
CPU_Initfunc();
BSP_INIT();
OSInit();
DELAY_US(1000000);
/* Create the Start task. */
OSTaskCreateExt(App_TaskStart,
(void *)0,
(CPU_STK *)&App_TaskStartStk[ 0],
(INT8U )APP_CFG_TASK_START_PRIO,
(INT16U )APP_CFG_TASK_START_PRIO,
(CPU_STK *)&App_TaskStartStk[APP_CFG_TASK_STK_SIZE ­1u],
(INT32U )APP_CFG_TASK_STK_SIZE,
(void *)0,
(INT16U )(OS_TASK_OPT_STK_CHK| OS_TASK_OPT_STK_CLR));
/* Start multitasking (i.e.
give control to uC/OS­II). */
OSStart();
/* Should never get here. */
while (DEF_TRUE) {
; } }
/*
**********************************************************************************************
***********
* App_TaskStart()
*
* Description : First task to be scheduled. Creates the application tasks.
*
* Argument(s) : p_arg the argument passed by 'OSTaskCreateExt()'.
*
* Return(s) : none.
*
* Caller(s) : This is a task.
*
* Note(s) : (1) This task creates the application task. The application is a simple LED
blinking
* demo where LD1 and LD4 blink at a 4:3 polyrhythm.
**********************************************************************************************
***********
*/
static void App_TaskStart (void *p_arg)
{
CPU_INT08U os_err;
/* Prevent compiler warning
for not using 'p_arg' */
(void)&p_arg;
/* Clear the LEDs. */
BSP_LED_Off();
/* Start the Ticker. */
BSP_Tick_Init();
/* Create the Ping task. */
AppTaskObjSem = OSSemCreate(0);
// OSTaskCreateExt(App_TaskPing,
// (void *)0,
// (CPU_STK *)&App_TaskPendStk[0],
// (INT8U )APP_CFG_TASK_PEND_PRIO,
// (INT16U )APP_CFG_TASK_PEND_PRIO,
// (CPU_STK *)&App_TaskPendStk[APP_CFG_TASK_STK_SIZE ­ 1u],
// (INT32U )APP_CFG_TASK_STK_SIZE,
// (void *)0,
/* Create the Pongtask. */
OSTaskCreateExt(App_TaskPong,
(void *)0,
(CPU_STK *)&App_TaskPostStk[ 0],
(INT8U )APP_CFG_TASK_POST_PRIO,
(INT16U )APP_CFG_TASK_POST_PRIO,
(CPU_STK *)&App_TaskPostStk[APP_CFG_TASK_STK_SIZE ­1u],
(INT32U )APP_CFG_TASK_STK_SIZE,
(void *)0,
(INT16U )(OS_TASK_OPT_STK_CHK| OS_TASK_OPT_STK_CLR));
/* All tasks should be
written as an infinite
loop. */
while (DEF_TRUE) {
//os_err = OSSemPost(AppTaskObjSem);
//OSTimeDlyHMSM(0, 0, 0, 500);
OSTimeDly(80);
DELAY_US(1000000);
} }
/*
**********************************************************************************************
***********
* App_TaskPing()
*
* Description : 'Ping' task, toggles LD1.
*
* Argument(s) : p_arg the argument passed by 'OSTaskCreateExt()'.
*
* Return(s) : none.
*
* Caller(s) : This is a task.
**********************************************************************************************
***********
*/
//static void App_TaskPing (void *p_arg)
//{
// CPU_INT08U os_err;
// /* Prevent compiler
warning for not using 'p_arg' */
// (void)&p_arg;
//
// /* Task body, always
written as an infinite loop. */
// while (DEF_TRUE) {
// OSSemPend( AppTaskObjSem,
// 0,
// &os_err);
// }
//}
/*
**********************************************************************************************
***********
* App_TaskPong)
*
* Description : 'Pong' task, toggles LD4.
*
* Argument(s) : p_arg the argument passed by 'OSTaskCreateExt()'.
*
* Return(s) : none.
*
* Caller(s) : This is a task.
**********************************************************************************************
***********
*/
static void App_TaskPong (void *p_arg)
{
/* Prevent compiler warning
for not using 'p_arg' */
(void)&p_arg;
/* Task body, always written
as an infinite loop. */
while (DEF_TRUE) {
BSP_LED_Toggle();
OSTimeDly(2);
}}



micrum 提供的历程中 app.c 里面的 mian ()函数是包含了 CPU_Init ();和 BSP_Init ()两个函数,分别是用来初始化芯片以及初始化 ucos 。在我
的函数中
同样提供了两个函数分别为
CPU_Initfunc ()和 BSP_INIT();
CPU_Initfunc
()函数主要是对cpu进行必要的初始化,复制的历程的初始化代码流程
BSP_INIT() 的代码代码段是初始化GPIO10,我的板子上GPIO10连着一个灯。
之后就是创建了第一个任务APP_TASKSTART任务,
之后调用OSSTART()函数去执行当前优先任务最好的任务,至于osstart()函数中的内容,请自己去看
void BSP_Tick_Init(void)
void cpu_timer0_isr(void)
函数为ucos系统提供时钟节拍,第一个函数是初始化timer,代码是参考28377d的历程中有关于timer定时器的设置,此处
设置的是50的定时
50ms定时一到就会跳入中断函数,也就是第二个函数,在第二个函数中调用ostimetick()函数为ucos提供时钟节拍,os
timetick()请
自己参考函数内容。
下面来说明产生问题的原因以及解决:
\ 文件组织问题上面已经显示了
2 、移植完成后系统无法跳转进入任务执行:
产生原因 :在任务跳转的时候,ucos其实是模拟了返回中断的过程,在创建任务的时候,将创建任务的各种信息(创建的时候其实只有
sp指针以及返回地址有用),虽然
创建的时候cpu的值是使用的假信息,具体自己去看创建代码。
在需要做任务切换时,系统是将对应任务tcb中的堆栈指针返回到cpu的堆栈sp中,然后通过出栈过程将信息返回,然后执行回调跳
回到需要执行的任务的代码处。
问题就出现在cpu的sp寄存器是16位的,所以在创建task过程中,指定的App
_TaskPostStk 的内存必须要指定在一个地址低于
16 位的内存当中,他的指定是在 cmd 中完成的。
最开始出错是应为我将App
_TaskPostStk 内存映射到了 0x10000 的内存当中,所以 16 sp 获取到的 sp 的值就为 0x0000 调转到初始代码处,
所以一直在循环:
OSTaskCreateExt(App_TaskPong,
(void *)0,
(CPU_STK *)&App_TaskPostStk[0],

2017/2/10 ucos­ii ti dsp 28377 芯片上的运行过程和移植过程 ­ havihouston ­ 博客园
http://www .cnblogs.com/havihouston/p/6387631.html 7/10
(INT8U )APP_CFG_TASK_POST_PRIO,
(INT16U )APP_CFG_TASK_POST_PRIO,
(CPU_STK *)&App_TaskPostStk[APP_CFG_TASK_STK_SIZE - 1u],
(INT32U )APP_CFG_TASK_STK_SIZE,
(void *)0,
(INT16U )(OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR));
下面是调试过程的截图:

1


扫描二维码关注公众号,回复: 1122788 查看本文章



2:




1 中任务启动后会跳转到 osstarthigtrdy 函数中,然后在跳转到 OS_CTX_RESTORE 这个函数在 asm 文件中自己看,
主要的目的就是把最高优先级的任务返回到
cpu 中,看反汇编代码中 0119a4 地址中的指令时将 sp 返回的,最右边的 sp 的值是 DA35
如果超过 16 位那就被结尾了,再然后调用 IRET 函数将保存在任务栈中的 task 地址返回到 pc 中执行。这样就完成了任务的切换。至于创建任务的时
候,各种值是怎么保存到栈中的,请
自己查看代码。
3 、当使用 ostimedly ()函数对任务延时,当延时时间已经完成,系统无法跳出空任务循环,移植在 IdleTask 中运行
通过
ostimedly 函数,任务就有一个延时参数,每次中断完成调用 ostimetick 函数,延迟参数减一,知道递减到 0 ,然后 ostimetick 函数将
任务又重新插入到就绪表里,具体参考
ostimetick 函数。
但是 但是 但是
ostimetick 函数里是没有任务切换的 ostimetick 函数里是没有任务切换的 ostimetick 函数里是没有任务切换的;
重要的事情说三遍,所以添加上
osIntEnter ()和 OsIntExit ()函数。
OsIntExit ()函数里有任务切换函数。这才会导致任务从 IdleTask 中重新调回任务中执行。
void cpu_timer0_isr(void)
{
PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
OSIntEnter();
OSTimeTick();
OSIntExit();

4、任务切换过程中总是跳入到异常中断中

首先必须要明白一个问题,任务的切换还是穿件 ucos 都是将他作为一个中断过程来处理的。比如在上面的程序中,任务延时 2 个时钟节拍后要继续
执行,
timer 定时器的中断中,调用 osIntExit ()函数。




看看看 重要的地方出现了,任务的跳转是调用了 OSiNTcTXsW 这个宏定义。
这个宏定义就是 :
asm(" TRAP #16");
跳转到中断列表中第 16 个中断,请翻阅 28377d 的芯片手册,第 16 个中断的为位置真好是在默认包含了所有中断表的。 c 文件即
F28377xD_DefaultISR.c 中。
16 个中断对应的地址就是 : inrerrupt void RTOS_ISR(void) 中;
就是说,这个时候
ucos 通过指令就把指针调转到了 inrerrupt void RTOS_ISR(void) 中来执行。
按照
ucos 的设想,在这个函数中呢就包含了两个步骤,保存当前 cpu 寄存器值,
将最高优先级任务
sp 指针返回,并当做中断回调到任务中去。
但是坑就在这个地方;因为我使用的是
TI 的历程,历程中这个函数是空的,关于 cpu 寄存器的操作是在 ucos­ii­>prots­>generic­>ccs­
>os_cpu_a.asm
这个文件中的 _os_cpu_rtosint_handler: 函数,这个自己去看,是有的。
最初的做法,我是在
inrerrupt void RTOS_ISR(void) 中断函数中调用 _os_cpu_rtosint_handler ;这就相当于进了两次中断,子啊保存的时
候保存了两次,
保存在堆栈中断返回地址就已近不是任务的返回地址而是其他的值了。
所以这个点我做了一点修改,中断函数是按照名字来区别的(实际是名字所对应的地址),所以我就将:
ucos­ii­>prots­>generic­>ccs­>os_cpu_a.asm 文件下 _os_cpu_rtosint_handler 的名字更换为 _RTOS_ISR; 让中断直接运行,不经过两次调用
F28377xD_DefaultISR.c 中将 inrerrupt void RTOS_ISR(void) 函数屏蔽。





运行成功。
整个移植过程就完成了,并且能够让这个
ucos 运行起来。至于他更精妙的用法我暂时还没有领会到。
慢慢在用起来把。
如果上文有错误之处,请指正:
邮箱
[email protected]

猜你喜欢

转载自blog.csdn.net/taiyangshenniao/article/details/54973339
今日推荐