1、多任务编程
ecos增值软件包的详细使用说明
一些网友来信反映说ecos增值软件包的范例比较少,不太会用,希望增加详细的使用说明。其实很多关于ecos的书上都有使用方法的介绍,不过考虑到很多用户第一次使用ecos,我还是觉得有必要再给出一些详细的使用说明。因为网友的问题重复的比较多,就不一一回信了,统一写成文档共享。主要想说明线程、IO操作、中断、TCP/IP协议栈、文件系统、GUI等的使用方法及其他感觉有必要阐述的内容。
在开始前先回答网友的几个问题。
1、ecos for smartarm2200经常死机的原因是PSRM读写速度比较慢(它内部用SDRAM,外部是SRAM接口,性价比高?),用较高速度访问时容易出现采样错误,把PSRAM读写访问长度各增加1个时钟周期后,系统就很稳定了,不再出现死机现象,升级版本已经提供。
2、关于在裸机上跑ping、TFTP、xmodem,我没有单独做过,不过redboot本身就是不带内核的ecos应用程序,其源码可以直接用在裸机上,这部分源码在ecos中已经提供了,自己看看吧。您发来的程序,我实在没时间分析了:-(
3、关于单片机实现“TELNET服务端”方面的程序资料,我没有具体的文字资料,不过redboot支持telnet,建议直接看源码。
4、关于monitor监控程序的实现原理,主要就是用软件中断指令替换断点处的语句,引发异常中断后进入处理程序,收集现场信息,然后通过通信接口部分传送到宿主机显示出来。难点是单步step调试断点的插入需要知道下一条语句的位置,不过好在有跟踪T标志,实现就容易多了。GDB的使用和串行通信协议见《Debugging with GDB》。软件包里提供了全部实现源码。
*********************
* 第一讲 多任务编程 *
*********************
第一次使用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
#i nclude <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();
}
来源:http://www.cnblogs.com/kuainiao/archive/2013/01/10/2854928.html