Context switchの様子
今回は、文字が少ないです。次回から解説したいと思います。
main()は、task0()に相当
各関数内にfor()の無限ループの記述がありますが、context switchを行うことで、無限ループから抜けて、続くタスクに処理を移しています。スタックとそのポインタってこの様にも使うのだと今更目からうろこです。
かつてPICのOSを弄っていた時期もありましたが、そこまで突っ込んでいませんでした。
/************************************************************
* Sample program using round robin like scheduling *
* modified & written by jk1brk *
* Last update 2019/3/24 *
***********************************************************/
#include <stdio.h>
#include <stdbool.h>
#include "myint.h"
#include "z80.h"
#include "aki80.h"
#include "task.h"
#define putchr(c) SIOB_putc(c)
#define transmitNow(void) SIOB_transmitNow(void)
// Declare functions regarding task
extern bool init_task(uchar no,void (*func)(void));
extern unsigned int switch_reg(unsigned int reg_sp);
extern void task_switch(void);
static int gCount; // Counter for showing #
void SIOB_putc(c)
char c;
{
volatile unsigned char status;
do{
status=inp(SIOB_CMD); // RR0
}while((status & 0x04)==0); // Check send buf. empty
outp(SIOB_DATA, c);
}
bool SIOB_transmitNow(void)
{
volatile unsigned char status2;
outp(SIOB_CMD, SIO_CMD_Null | 1); // Select WR1
status2=inp(SIOB_CMD);
if(status2 & 0x01) return 0; // All char.s not sent yet
else return 1; // Ready to send
}
/********************************************************
* each task *
********************************************************/
void task1(void)
{
static unsigned char lCount_1 = 1;
for(;;){
printf("task1 %d\n\r", gCount++);
putbyt(lCount_1++);
putnwl();
task_switch();
// PC is for the next task after task_switch()
}
}
void task2(void)
{
static unsigned char lCount_2 = 2;
for(;;){
printf("task2 %d\n\r", gCount++);
putbyt(lCount_2++);
putnwl();
task_switch();
// PC is for the next task after task_switch()
}
}
void task3(void)
{
static unsigned char lCount_3 = 3;
for(;;){
printf("task3 %d\n\r", gCount++);
putbyt(lCount_3++);
putnwl();
task_switch();
// PC is for the next task after task_switch()
}
}
/********************************************************
* main() *
********************************************************/
main(void)
{
unsigned char c;
gCount = 0;
printf("Multi task sample program Ver. 1.4\n\r");
init_task(1, task1);
init_task(2, task2);
init_task(3, task3);
for(c = 0; c < MAX_TASK+1; c++) {
// for(;;) {
printf("main %d\n\r", gCount++);
task_switch();
__EI();
}
;
return printf("Return to monitor\n\r");
}
/*******************************************************/
putwrd(n)
int n;
{
char c, buf[5];
int i;
for(i = 3; i >= 0; i--){
c = n & 15;
n = (n >> 4 ) & 4095;
if(c < 10) buf[i] = c + 48;
else buf[i] = c + 55;
}
buf[4] = 0;
putstr(buf);
}
putbyt(n)
char n;
{
char c,buf[3];
int i;
for(i = 1; i >= 0; i--){
c = n & 15;
n = (n >> 4 ) & 4095;
if(c < 10) buf[i] = c + 48;
else buf[i] = c + 55;
}
buf[2] = 0;
putstr(buf);
}
putnwl( )
{
putstr("\15\12");
}
putstr(b)
char *b;
{
while(*b)
putchr(*b++);
}