51单片机操作系统
; ; sudochen@163.com ; This OS Just for Studing ; Please contact the author for commercial use ; All Right Reserved ; This program is distributed in the hope that it will be useful, ; but WITHOUT ANY WARRANTY NAME ?C_STARTUP EXTRN CODE (?C_START) EXTRN CODE (task_switch) EXTRN CODE (uart_irq) PUBLIC ?C_STARTUP PUBLIC TIMER_SYS ORG 0000H ;absolute code at addr 0x00 ?C_STARTUP: LJMP START ORG 000BH ;absolute code at addr 0x0B timer_0_irq SETB F0 LJMP TIMER_SYS ORG 0023H LJMP UART_SYS START: MOV R0, #0FFH CLB: MOV @R0, #00H DJNZ R0, CLB MOV SP, #0D0H LJMP ?C_START UART_SYS: ; all we save 13 system registers CLR EA PUSH ACC PUSH B PUSH PSW PUSH DPL PUSH DPH USING 0 PUSH AR0 PUSH AR1 PUSH AR2 PUSH AR3 PUSH AR4 PUSH AR5 PUSH AR6 PUSH AR7 CALL uart_irq ; we restore 13 system registers POP AR7 POP AR6 POP AR5 POP AR4 POP AR3 POP AR2 POP AR1 POP AR0 POP DPH POP DPL POP PSW POP B POP ACC SETB EA RETI TIMER_SYS: ; all we save 13 system registers CLR EA PUSH ACC PUSH B PUSH PSW PUSH DPL PUSH DPH USING 0 PUSH AR0 PUSH AR1 PUSH AR2 PUSH AR3 PUSH AR4 PUSH AR5 PUSH AR6 PUSH AR7 CALL task_switch MOV SP, R7 ; we restore 13 system registers POP AR7 POP AR6 POP AR5 POP AR4 POP AR3 POP AR2 POP AR1 POP AR0 POP DPH POP DPL POP PSW POP B POP ACC SETB EA RETI END
/* * sudochen@163.com * This OS Just for Studing * Please contact the author for commercial use * All Right Reserved * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY */ #include <reg51.h> #include <string.h> #include "STC8X_SYSDEF.H" sbit Led1=P3^4; sbit Led2=P3^5; sbit Led3=P3^6; sbit Led4=P3^7; #define ON 0 #define OFF 1 #define CONFIG_TASK_MAX 3 #define FOSC 11059200UL #define BRT (256 - FOSC / 115200 / 32) typedef void (*pfunc)(void); extern void TIMER_SYS(void); #define schedule() TIMER_SYS() struct task_struct { pfunc func; unsigned int ticks; unsigned char ipc; unsigned char sp_top; unsigned char sp[20]; }; struct task_struct task_led1; struct task_struct task_led2; struct task_struct task_idle; struct task_struct *task_list[CONFIG_TASK_MAX] = {0}; xdata unsigned char pid = 0; xdata unsigned char pid_max = 0; xdata struct task_struct *current = 0; /* timer mode 1 and timeout is 10ms * */ void enable_timer0(void) { #if 1 AUXR &= 0x7F; //¶¨Ê±Æ÷ʱÖÓ12Tģʽ TMOD &= 0xF0; //ÉèÖö¨Ê±Æ÷ģʽ TL0 = 0x00; //ÉèÖö¨Ê±³õʼֵ TH0 = 0xb8; //20ms ET0 = 0; //½ûÓö¨Ê±Æ÷ TF0 = 0; //Çå³ýTF0±êÖ¾ TR0 = 0; //¶¨Ê±Æ÷0¿ªÊ¼¼Æʱ #else TMOD = 0x01; // work mode TH0 = 0xf0; // high value TL0 = 0xd8; // low value ET0 = 1; // enable timer_interrupt TR0 = 0; // disable timer0 #endif } #define BUFFER_LEN 16 bit busy; xdata char wptr; xdata char buffer[BUFFER_LEN]; xdata char console[BUFFER_LEN]; xdata char console_len; void serial_init(void) //115200bps@11.0592MHz { SCON = 0x50; //8???,????? AUXR &= 0xBF; //?????12T?? AUXR &= 0xFE; //??1?????1??????? TMOD &= 0x0F; //??????? TL1 = 0xFE; //??????? TH1 = 0xFF; //??????? ET1 = 0; //?????%d?? TR1 = 1; //???1???? ES = 1; wptr = 0; console_len = 0; } void uart_irq() { if (TI) { TI = 0; busy = 0; } if (RI) { RI = 0; buffer[wptr] = SBUF; if (0x0a == buffer[wptr] || 0x0d == buffer[wptr]) { buffer[wptr] = 0; console_len = wptr + 1; wptr = 0; memcpy(console, buffer, console_len); return; } wptr ++; wptr &= 0x0f; } } void serial_putc(char dat) { while (busy); busy = 1; SBUF = dat; } void serial_printf(char *p) { while (*p) { serial_putc(*p++); } } void task_init(struct task_struct *task, pfunc func) { task->func = func; task->ticks = 0; task->ipc = 0; task->sp[1] = ((int)func) >> 8; // hign task->sp[0] = ((int)func) ; // low task->sp_top = (unsigned char)(task->sp) + 14; task_list[pid_max++] = task; } char task_switch(void) { // NOW SP is address of "task switch function" // SP - 2 is the current task runtime address current->sp_top = (unsigned char)(SP - 2); if (F0) { for (pid = 0; pid < pid_max; pid++) { if (task_list[pid]) { if (task_list[pid]->ticks) { task_list[pid]->ticks--; } } } F0 = 0; } for (pid = 0; pid < pid_max; pid++) { if (task_list[pid]) { if (!task_list[pid]->ticks) { if (current != task_list[pid]) { current = task_list[pid]; break; } } } } return current->sp_top; } void task_start(void) { // when task_init we set task sp_top is sp+14 // SP = sp+1, the address of the function of task[0] start address SP = (unsigned char )((task_list[0]->sp_top) - 13); current = task_list[0]; TF0 = 0; TR0 = 1; ET0 = 1; } void delay_500ms(void) //@11.0592MHz { unsigned char i, j, k; i = 8; j = 3; k = 67; do { do { while (--k); } while (--j); } while (--i); } void sleep(int ticks) { EA = 0; current->ticks = ticks; EA = 1; schedule(); } void func_led1(void) { xdata unsigned char c = 0; xdata struct task_struct *task_led2 = task_list[1]; while(1) { Led1=ON; sleep(25); Led1=OFF; sleep(25); if (++c > 10) { c = 0; EA = 0; task_led2->ipc = 1; EA = 1; serial_printf("PID: 0 Led2 Turn over\n\r"); } } } void func_led2(void) { xdata unsigned char ipc = 0; xdata unsigned char recv = 0; xdata char buff[16]; xdata unsigned char i = 0; while(1) { EA = 0; ipc = current->ipc; if (ipc) { current->ipc = 0; } EA = 1; if (ipc) { serial_printf("PID: 1 Recive [counter] Message\n\r"); Led2=!Led2; if (!Led2) { serial_printf("PID: 1 Led2 Turn On\n\r"); } else { serial_printf("PID: 1 Led2 Turn Off\n\r"); } } EA = 0; recv = console_len; memcpy(buff, console, console_len); console_len = 0; EA = 1; if (recv) { serial_printf(buff); if (!strcmp(buff, "LED3ON")) { Led3 = ON; serial_printf(buff); } if (!strcmp(buff, "LED3OFF")) { Led3 = OFF; serial_printf(buff); } } schedule(); } } void func_idle(void) { while(1) { Led4 = !Led4; } } void enable_interrupt() { EA = 1; } void main() { xdata int i = 0; P0M0 = 0x00; P0M1 = 0x00; P1M0 = 0x00; P1M1 = 0x00; P2M0 = 0x00; P2M1 = 0x00; P3M1 = 0x00; P3M0 = 0x00; //ÉèÖÃΪ׼˫Ïò¿Ú P4M0 = 0x00; P4M1 = 0x00; P5M0 = 0x00; P5M1 = 0x00; enable_timer0(); serial_init(); for (i = 0; i < 10; i++) { Led1=!Led1; Led2=!Led2; Led3=!Led3; Led4=!Led4; delay_500ms(); } for (i = 0; i < 10; i++) { delay_500ms(); } Led1 = OFF; Led2 = OFF; Led3 = OFF; Led4 = OFF; task_init(&task_led1, func_led1); task_init(&task_led2, func_led2); task_init(&task_idle, func_idle); task_start(); enable_interrupt(); while(1); }
上面的函数在某些编译条件下会出错,需要调节C51的优化项,同时由于函数指针的存在会导致函数调用树的问题,具体可搜索C51 调用树 关键字进行检索,修改如下:
/* * sudochen@163.com * This OS Just for Studing * Please contact the author for commercial use * All Right Reserved * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY */ #include <reg51.h> #include <string.h> #include <intrins.h> #include "STC8X_SYSDEF.H" sbit Led1=P3^4; sbit Led2=P3^5; sbit Led3=P3^6; sbit Led4=P3^7; #define ON 0 #define OFF 1 #define CONFIG_TASK_MAX 3 #define FOSC 11059200UL #define BRT (256 - FOSC / 115200 / 32) typedef void (*pfunc)(void); extern void TIMER_SYS(void); #define schedule() TIMER_SYS() struct task_struct { pfunc func; unsigned int ticks; unsigned char ipc; unsigned char sp_top; unsigned char sp[20]; }; #define PREFIX xdata #define TO_TASKSTRUCT(p) ((struct task_struct *)(p)) struct task_struct task_led1; struct task_struct task_led2; struct task_struct task_idle; PREFIX unsigned char pid = 0; PREFIX unsigned char pid_max = 0; PREFIX unsigned int task_list[CONFIG_TASK_MAX] = {0}; PREFIX unsigned int current = 0; //PREFIX struct task_struct *current = 0; /* timer mode 1 and timeout is 10ms * */ void enable_timer0(void) { #if 1 AUXR &= 0x7F; //¶¨Ê±Æ÷ʱÖÓ12Tģʽ TMOD &= 0xF0; //ÉèÖö¨Ê±Æ÷ģʽ TL0 = 0x00; //ÉèÖö¨Ê±³õʼֵ TH0 = 0xb8; //20ms ET0 = 0; //½ûÓö¨Ê±Æ÷ TF0 = 0; //Çå³ýTF0±êÖ¾ TR0 = 0; //¶¨Ê±Æ÷0¿ªÊ¼¼Æʱ #else TMOD = 0x01; // work mode TH0 = 0xf0; // high value TL0 = 0xd8; // low value ET0 = 1; // enable timer_interrupt TR0 = 0; // disable timer0 #endif } #define BUFFER_LEN 16 bit busy; PREFIX char wptr; PREFIX char buffer[BUFFER_LEN]; PREFIX char console[BUFFER_LEN]; PREFIX char console_len; void serial_init(void) //115200bps@11.0592MHz { SCON = 0x50; //8???,????? AUXR &= 0xBF; //?????12T?? AUXR &= 0xFE; //??1?????1??????? TMOD &= 0x0F; //??????? TL1 = 0xFE; //??????? TH1 = 0xFF; //??????? ET1 = 0; //?????%d?? TR1 = 1; //???1???? ES = 1; wptr = 0; console_len = 0; } void uart_irq() { if (TI) { TI = 0; busy = 0; } if (RI) { RI = 0; buffer[wptr] = SBUF; if (0x0a == buffer[wptr] || 0x0d == buffer[wptr]) { buffer[wptr] = 0; console_len = wptr + 1; wptr = 0; memcpy(console, buffer, console_len); return; } wptr ++; wptr &= 0x0f; } } void serial_putc(char dat) { while (busy); busy = 1; SBUF = dat; } void serial_printf(char *p) { while (*p) { serial_putc(*p++); } } void task_init(struct task_struct *task, pfunc func) { task->func = func; task->ticks = 0; task->ipc = 0; task->sp[1] = ((int)func) >> 8; // hign task->sp[0] = ((int)func) ; // low task->sp_top = (unsigned char)(task->sp) + 14; task_list[pid_max++] = (unsigned int)task; } char task_switch(void) { // NOW SP is address of "task switch function" // SP - 2 is the current task runtime address TO_TASKSTRUCT(current)->sp_top = (unsigned char)(SP - 2); if (F0) { for (pid = 0; pid < pid_max; pid++) { if (task_list[pid]) { if (TO_TASKSTRUCT(task_list[pid])->ticks) { TO_TASKSTRUCT(task_list[pid])->ticks--; } } } F0 = 0; } for (pid = 0; pid < pid_max; pid++) { if (task_list[pid]) { if (!TO_TASKSTRUCT(task_list[pid])->ticks) { if (current != task_list[pid]) { current = task_list[pid]; break; } } } } return TO_TASKSTRUCT(current)->sp_top; } void task_start(void) { // when task_init we set task sp_top is sp+14 // SP = sp+1, the address of the function of task[0] start address SP = (unsigned char )((TO_TASKSTRUCT(task_list[0])->sp_top) - 13); current = (unsigned int)task_list[0]; TF0 = 0; TR0 = 1; ET0 = 1; } void Delay10ms() //@11.0592MHz { unsigned char i, j; i = 108; j = 145; do { while (--j); } while (--i); } void delay_500ms(void) //@11.0592MHz { PREFIX unsigned char i, j, k; i = 8; j = 3; k = 67; do { do { while (--k); } while (--j); } while (--i); } void sleep(int ticks) { EA = 0; TO_TASKSTRUCT(current)->ticks = ticks; EA = 1; schedule(); } void func_led1(void) { PREFIX unsigned char c = 0; PREFIX unsigned int task_led2 = (unsigned int)task_list[1]; //PREFIX struct task_struct *task_led2 = task_list[1]; while(1) { Led1=ON; sleep(25); Led1=OFF; sleep(25); if (++c > 10) { c = 0; EA = 0; TO_TASKSTRUCT(task_led2)->ipc = 1; EA = 1; serial_printf("PID: 0 Led2 Turn over\n\r"); } } } void func_led2(void) { PREFIX unsigned char ipc = 0; PREFIX unsigned char recv = 0; PREFIX char buff[16]; PREFIX unsigned char i = 0; while(1) { EA = 0; ipc = TO_TASKSTRUCT(current)->ipc; if (ipc) { TO_TASKSTRUCT(current)->ipc = 0; } EA = 1; if (ipc) { serial_printf("PID: 1 Recive [counter] Message\n\r"); Led2=!Led2; if (!Led2) { serial_printf("PID: 1 Led2 Turn On\n\r"); } else { serial_printf("PID: 1 Led2 Turn Off\n\r"); } } EA = 0; recv = console_len; memcpy(buff, console, console_len); console_len = 0; EA = 1; if (recv) { serial_printf(buff); if (!strcmp(buff, "LED3ON")) { Led3 = ON; serial_printf(buff); } if (!strcmp(buff, "LED3OFF")) { Led3 = OFF; serial_printf(buff); } } schedule(); } } void func_idle(void) { while(1) { Led4 = !Led4; Delay10ms(); } } void enable_interrupt() { EA = 1; } void main() { PREFIX int i = 0; P0M0 = 0x00; P0M1 = 0x00; P1M0 = 0x00; P1M1 = 0x00; P2M0 = 0x00; P2M1 = 0x00; P3M1 = 0x00; P3M0 = 0x00; //ÉèÖÃΪ׼˫Ïò¿Ú P4M0 = 0x00; P4M1 = 0x00; P5M0 = 0x00; P5M1 = 0x00; enable_timer0(); serial_init(); for (i = 0; i < CONFIG_TASK_MAX; i++) { task_list[i] = 0; } for (i = 0; i < 10; i++) { Led1=!Led1; Led2=!Led2; Led3=!Led3; Led4=!Led4; delay_500ms(); } for (i = 0; i < 10; i++) { delay_500ms(); } Led1 = OFF; Led2 = OFF; Led3 = OFF; Led4 = OFF; task_init(&task_led1, func_led1); task_init(&task_led2, func_led2); task_init(&task_idle, func_idle); task_start(); enable_interrupt(); while(1); }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律