|
一、 利用旗语解决冲突 目的:说明如何使用旗语来阻止另一个任务线程访问该数据结构。 方法:两个任务线程共享一个数据结构,当其中一个任务线程修改这个数据结构时,就产生了冲突。为了解决这个冲突,两个任务都有一段通过使用同一个旗语调用SEM_pend来保护的代码。在第一个任务执行这段受保护代码期间,另一个任务即使抢先了第一个任务,也不能执行这段受保护的代码(互斥)。 步骤: 1. 复制并打开工程 从CCS安装目录的tutorial﹨sim64xx文件夹中将例子文件目录mutex复制到一个新文件夹中,该工程中使用的文件如下。 mutex.c:程序的源代码 mutex.cdb:DSP/BIOS的配置文件 2. 检查CDB配置文件 在DM642实验板上运行这个例子。该程序的CDB配置文件已经创建了1个SEM旗语对象、2个TSK任务对象和1个现实消息的LOG对象。为了在DM642上运行,还需要修改VECT中断向量表的位置,设置RTDX的模式为JTAG模式,再将LOG_system对象的buflen参数改为512,以及将“logtype”项设为“fixed”;然后保存该配置文件。 3. 查看源代码 在CCS的Project View区域中,可以双击mutex.c文件来查看源代码。下面是各个部分的详细介绍。 ·变量声明部分:包含了程序用到的各种头文件,以及程序中使用的函数的原型。同时,还定义了maincoun全局变量,它是由两个任务共同使用,并通过旗语来实现互斥访问。另外,两个全局变量tsk1count,tsk2count分别用于记录任务运行次数。 ·main函数:该例子中的main()为空函数,简单地返回DSP/BIOS内核地IDL循环。 ·mutex1函数:该函数在任务线程task()中调用。其程序代码如下。 * ======== mutex1 ======== */ Void mutex1() { LgUns tempvar; LgUns time;
for (;;) { LOG_printf(&trace, "\n Running mutex1 function"); if (SEM_count(&sem) == 0) { LOG_printf(&trace, "Sem blocked in mutex1"); } SEM_pend(&sem, SYS_FOREVER); tempvar = maincount; time = CLK_getltime(); /* wait for two system ticks to pass */ while (CLK_getltime() <= (time + 1)) { ; } tsk1count++; maincount = ++tempvar; /* combine hex values to display LgUns */ #ifdef _28_ LOG_printf(&trace, "mutex1: loop 0x%04x%04x;", (Arg)(tsk1count >> 16), (Arg)(tsk1count & 0xffff)); LOG_printf(&trace, " total count = 0x%04x%04x", (Arg)(maincount >> 16), (Arg)(maincount & 0xffff)); #else LOG_printf(&trace, "mutex1: loop 0x%04x%04x;", (Int)(tsk1count >> 16), (Int)(tsk1count & 0xffff)); LOG_printf(&trace, " total count = 0x%04x%04x", (Int)(maincount >> 16), (Int)(maincount & 0xffff)); #endif
SEM_post(&sem); TSK_sleep(1); } } 该函数是一个无限循环,在进入循环时首先打印输出信息,表示该任务函数已经开始运行。然后判断旗语计数器,如果计数器为0,则输出一条该任务即将暂停等待旗语地信息。接下来调用SEM_pend函数等待旗语。当收到旗语后,对全局变量maincount加1,输出计算结果,最后发送旗语信号,并使该任务线程暂停一会儿。在这个函数中,SEM_pend和TSK_sleep函数地调用都会导致任务切换。 ·mutex2函数:mutex2函数由任务task1调用,它将首先运行(task1的优先级比task()高)。该函数与前面介绍的mutex1函数非常相似,这里不再重复。比较两个任务函数可以看出,两个函数都需要对全局变量maincount进行操作,所以在每个任务对maincount操作前,都需要得到旗语信号。在没有这个信号前,任务都处于暂停状态,即使优先级高的任务也如此。 4. 在CCS中运行 编译、连接后,装入该程序。选择菜单命令“DSP/BIOS”|“RTA Control Panel”,打开DSP/BIOS分析工具的控制面板窗口,只选择“nable CLK logging”、“Enable TSK logging”和“lobal host enable”三项,这样,DSP/BIOS执行图更加清晰。同时,打开执行图窗口和LOG窗口,按F5键开始运行程序。
所有源程序如下: mutexcfg.h代码 /* Do *not* directly modify this file. It was */ /* generated by the Configuration Tool; any */ /* changes risk being overwritten. */
/* INPUT mutex.cdb */
#define CHIP_6416 1
/* Include Header Files */ #include <std.h> #include <hst.h> #include <swi.h> #include <tsk.h> #include <log.h> #include <sem.h> #include <sts.h>
#ifdef __cplusplus extern "C" { #endif
extern far HST_Obj RTA_fromHost; extern far HST_Obj RTA_toHost; extern far SWI_Obj KNL_swi; extern far TSK_Obj TSK_idle; extern far TSK_Obj task0; extern far TSK_Obj task1; extern far LOG_Obj LOG_system; extern far LOG_Obj trace; extern far SEM_Obj sem; extern far STS_Obj IDL_busyObj; extern far void CSL_cfgInit();
#ifdef __cplusplus } #endif /* extern "C" */
mutexcfg_c.c代码 /* Do *not* directly modify this file. It was */ /* generated by the Configuration Tool; any */ /* changes risk being overwritten. */
/* INPUT mutex.cdb */
/* Include Header File */ #include "mutexcfg.h"
#ifdef __cplusplus #pragma CODE_SECTION(".text:CSL_cfgInit") #else #pragma CODE_SECTION(CSL_cfgInit,".text:CSL_cfgInit") #endif
#ifdef __cplusplus #pragma FUNC_EXT_CALLED() #else #pragma FUNC_EXT_CALLED(CSL_cfgInit) #endif
/* Config Structures */ /* Handles */
/* * ======== CSL_cfgInit() ======== */ void CSL_cfgInit() { }
mutex.c代码 /* * Copyright 2003 by Texas Instruments Incorporated. * All rights reserved. Property of Texas Instruments Incorporated. * Restricted rights to use, duplicate or disclose this code are * granted through contract. * */ /* "@(#) DSP/BIOS 4.90.270 06-11-03 (barracuda-m10)" */ /* * ======== mutex.c ======== */
#include <std.h>
#include <clk.h> #include <log.h> #include <tsk.h> #include <sem.h>
#include "mutexcfg.h"
Void mutex1(); Void mutex2();
LgUns tsk1count = 0; LgUns tsk2count = 0; LgUns maincount = 0;
/* * ======== main ======== */ Void main() { /* Does nothing */ }
/* * ======== mutex1 ======== */ Void mutex1() { LgUns tempvar; LgUns time;
for (;;) { LOG_printf(&trace, "\n Running mutex1 function"); if (SEM_count(&sem) == 0) { LOG_printf(&trace, "Sem blocked in mutex1"); } SEM_pend(&sem, SYS_FOREVER); tempvar = maincount; time = CLK_getltime(); /* wait for two system ticks to pass */ while (CLK_getltime() <= (time + 1)) { ; } tsk1count++; maincount = ++tempvar; /* combine hex values to display LgUns */ #ifdef _28_ LOG_printf(&trace, "mutex1: loop 0x%04x%04x;", (Arg)(tsk1count >> 16), (Arg)(tsk1count & 0xffff)); LOG_printf(&trace, " total count = 0x%04x%04x", (Arg)(maincount >> 16), (Arg)(maincount & 0xffff)); #else LOG_printf(&trace, "mutex1: loop 0x%04x%04x;", (Int)(tsk1count >> 16), (Int)(tsk1count & 0xffff)); LOG_printf(&trace, " total count = 0x%04x%04x", (Int)(maincount >> 16), (Int)(maincount & 0xffff)); #endif
SEM_post(&sem); TSK_sleep(1); } }
/* * ======== mutex2 ======== */ Void mutex2() { LgUns tempvar;
for (;;) { LOG_printf(&trace, "\n Running mutex2 function"); if (SEM_count(&sem) == 0) { LOG_printf(&trace, "Sem blocked in mutex2"); } SEM_pend(&sem, SYS_FOREVER); tempvar = maincount; tsk2count++; maincount = ++tempvar; /* combine hex values to display LgUns */ #ifdef _28_ LOG_printf(&trace, "mutex2: loop 0x%04x%04x;", (Arg)(tsk2count >> 16), (Arg)(tsk2count & 0xffff)); LOG_printf(&trace, " total count = 0x%04x%04x", (Arg)(maincount >> 16), (Arg)(maincount & 0xffff)); #else LOG_printf(&trace, "mutex2: loop 0x%04x%04x;", (Int)(tsk2count >> 16), (Int)(tsk2count & 0xffff)); LOG_printf(&trace, " total count = 0x%04x%04x", (Int)(maincount >> 16), (Int)(maincount & 0xffff)); #endif SEM_post(&sem); TSK_sleep(1); } }
|