| |
第一次使用ecos,当然要先编个hello程序啦。那就编个多任务的,恩,3个线程任务同时打印信息,A线程每秒打印一次,B线程每3秒打印一次,C线程每6秒打印一次。
这个程序在ucos51演示程序中也有,就是demo1。现在来比较一下二者的异同。
从总体看,ecos和ucos的应用程序大同小异,都有线程/任务创建、线程/任务函数、堆栈等内容,只是API函数名字不同。
ecos应用程序没有从main开始,而是从cyg_start启动,在cyg_start中创建test线程,再在test中创建3个实际的工作线程。
ecos的命名规则很有层次感,比如:cyg_thread_delay(),cyg表示cygnus公司出品,thread表示这个函数是与线程相关的(如:线程创建、延时),delay表示延时。怎么样?是不是很好记忆。比ucos的OSTimeDly好记吧!所有cygnus公司提供的API函数前面都带cyg前缀,你自己写的函数可以加上你的标识前缀,如我自己定义的函数前加yy前缀。
cyg_thread_create(//创建线程
线程优先级,
线程函数指针,
线程函数参数,//对应线程函数的(cyg_addrword_t data)入口参数
线程名, //用于调试目的
堆栈基址,
堆栈大小,
线程句柄,
保存此线程内核数据结构的存储空间
);
cyg_thread_resume(线程句柄); //线程恢复
cyg_thread_delay(延时时间); //以10ms为单位
cyg_scheduler_start(); //启动调度器开始工作。该函数被调用后不会返回,类似ucos中的OSStart();
好了,第一个程序就是这么简单,跟ucos很像吧,其实,所有的RTOS都差不多的,只是函数名字不同罢了。ecos和ucos一样都是直接使用平板内存,没有特权概念,不过,ecos比ucos更高级,包含了TCP/IP栈、文件系统、GUI,功能也更强大,可以用C++开发。这个演示应用程序可以不加修改地用在任何支持ecos的平台上,例如:EASYARM2200和SMARTARM2200上的运行效果是一样的,这就是OS的好处,不用再关心定时器初始化,串口编程,抹平了硬件差异,令编程如此简单,EASY。
下面是测试程序运行结果,Demo程序创建了3个任务A、B、C,优先级全为10,A每秒显示一次,B每3秒显示一次,C每6秒显示一次。从显示结果看,显示3个A后显示1个B,显示6个A和2个B后显示1个C,结果显然正确。
RedBoot> lo -b 0x81010000 -r -m xmodem
Raw file loaded 0x81010000-0x810252cb, assumed entry at 0x81010000
xyzModem - CRC mode, 679(SOH)/0(STX)/0(CAN) packets, 2 retries
RedBoot> go 0x81010000
+
*******************************
* Hello! The world. *
*******************************
AAAAAA111111 is active.thread data is 1.
BBBBBB333333 is active.thread data is 2.
CCCCCC666666 is active.thread data is 3.
AAAAAA111111 is active.thread data is 1.
AAAAAA111111 is active.thread data is 1.
BBBBBB333333 is active.thread data is 2.
AAAAAA111111 is active.thread data is 1.
AAAAAA111111 is active.thread data is 1.
AAAAAA111111 is active.thread data is 1.
CCCCCC666666 is active.thread data is 3.
BBBBBB333333 is active.thread data is 2.
......
完整的测试源程序如下:demo1.c
#include <cyg/kernel/kapi.h>
#define STACK_SIZE 4096
char stack[4][STACK_SIZE];
static cyg_thread thread_data[4];
static cyg_handle_t thread_handle[4];
void taska(cyg_addrword_t data)
{
int message = (int) data;
for(;;)
{
printf("\tAAAAAA111111 is active.thread data is %d.\n",message);
cyg_thread_delay(100);
}
}
void taskb(cyg_addrword_t data)
{
int message = (int) data;
for(;;)
{
printf("\tBBBBBB333333 is active.thread data is %d.\n",message);
cyg_thread_delay(300);
}
}
void taskc(cyg_addrword_t data)
{
int message = (int) data;
for(;;)
{
printf("\tCCCCCC666666 is active.thread data is %d.\n",message);
cyg_thread_delay(600);
}
}
void
test(cyg_addrword_t data)
{
printf("\n\n\n");
printf("\t *******************************\n");
printf("\t * Hello! The world. *\n");
printf("\t *******************************\n\n\n");
// Create a main thread, so we can run the scheduler and have time 'pass'
cyg_thread_create(10, // Priority - just a number
taska, // entry
1, // entry parameter
"taska", // Name
&stack[1], // Stack
STACK_SIZE, // Size
&thread_handle[1], // Handle
&thread_data[1] // Thread data structure
);
cyg_thread_resume(thread_handle[1]); // Start it
// Create a main thread, so we can run the scheduler and have time 'pass'
cyg_thread_create(10, // Priority - just a number
taskb, // entry
2, // entry parameter
"taskb", // Name
&stack[2], // Stack
STACK_SIZE, // Size
&thread_handle[2], // Handle
&thread_data[2] // Thread data structure
);
cyg_thread_resume(thread_handle[2]); // Start it
// Create a main thread, so we can run the scheduler and have time 'pass'
cyg_thread_create(10, // Priority - just a number
taskc, // entry
3, // entry parameter
"taskc", // Name
&stack[3], // Stack
STACK_SIZE, // Size
&thread_handle[3], // Handle
&thread_data[3] // Thread data structure
);
cyg_thread_resume(thread_handle[3]); // Start it
}
void
cyg_start(void)
{
// Create a main thread, so we can run the scheduler and have time 'pass'
cyg_thread_create(10, // Priority - just a number
test, // entry
0, // entry parameter
"test", // Name
&stack[0], // Stack
STACK_SIZE, // Size
&thread_handle[0], // Handle
&thread_data[0] // Thread data structure
);
cyg_thread_resume(thread_handle[0]); // Start it
cyg_scheduler_start();
}