rp2040

RP2040 Programming without SDK
Log | Files | Refs

main.c (2432B)


      1 #define NULL 0L // TODO: Should fail when dereferenced.
      2 
      3 void init(void);
      4 int puts(char *);
      5 void printh(unsigned int);
      6 void set_alarm(unsigned int);
      7 void halt(void);
      8 void wfi(void);
      9 void print_sp(void);
     10 void *memcpy(void *s1, void *s2, long n);
     11 void restore_context(unsigned int [17]);
     12 void set_psp(void);
     13 
     14 // A proc represents a process in execution.
     15 typedef struct proc {
     16 	// Id is the unique identifier of the process.
     17 	unsigned int id;
     18 	// R is the registers of the process with
     19 	// r[13] be sp, r[14] lr, r[15] pc, r16 xspr.
     20 	unsigned int r[17];
     21 	// Next is the next process to execute.
     22 	struct proc *next;
     23 } proc;
     24 
     25 void save_context(unsigned int r[17]);
     26 
     27 extern char proc0_start, proc0_size;
     28 extern char proc1_start, proc1_size;
     29 extern void proc0(void), proc1(void);
     30 extern char msg0, msg1;
     31 
     32 
     33 // A proc_tab is the queue of waiting processes.
     34 typedef struct proc_tab {
     35 	// Head is the head of the queue.
     36 	proc *head;
     37 	// Tail is the tail of the queue.
     38 	proc *tail;
     39 } proc_tab;
     40 
     41 proc_tab ptab;
     42 proc p0, p1;
     43 
     44 int
     45 main(void) {
     46 	init();
     47 
     48 	memcpy((void *)0x20000000, &proc0_start, (long) &proc0_size);
     49 	memcpy((void *)0x20000100, &proc1_start, (long) &proc1_size);
     50 
     51 	ptab.head = &p0;
     52 	ptab.tail = &p1;
     53 
     54 	p0.id = 0;
     55 	p0.r[13] = 0x20000100; // sp
     56 	p0.r[14] = (unsigned int) halt; // lr
     57 	p0.r[15] = (unsigned int) proc0; // pc
     58 	p0.r[16] = 0x01000000; // EPSR's thumb bit
     59 	p0.next = &p1;
     60 
     61 	p1.id = 1;
     62 	p1.r[13] = 0x20000200; // sp
     63 	p1.r[14] = (unsigned int) halt; // lr
     64 	p1.r[15] = (unsigned int) proc1; // pc
     65 	p1.r[16] = 0x01000000; // EPSR's thumb bit
     66 	p1.next = NULL;
     67 
     68 	set_psp();
     69 
     70 	proc0();
     71 
     72 	return 0;
     73 }
     74 
     75 void
     76 scheduler(void) {
     77 	puts("scheduler called");
     78 }
     79 
     80 // Switch_context saves registers r to the currently executing proc struct
     81 // and then move it to the tail of task queue.
     82 // It returns the next PC of the next task in the queue
     83 unsigned int *
     84 switch_context(unsigned int r[17]) {
     85 	proc *p;
     86 
     87 	puts("switch_context:");
     88 	for (int i = 0; i < 17; i++) {
     89 		printh(r[i]);
     90 		puts("");
     91 	}
     92 
     93 	// save context
     94 	int i;
     95 	for (i = 0; i < 17; i++) {
     96 		ptab.head->r[i] = r[i];
     97 	}
     98 	// update task queue
     99 	p = ptab.head;
    100 	ptab.head = ptab.head->next;
    101 	ptab.tail->next = p;
    102 	ptab.tail = p;
    103 	ptab.tail->next = NULL;
    104 
    105 	puts("next context:");
    106 	for (int i = 0; i < 17; i++) {
    107 		printh(ptab.head->r[i]);
    108 		puts("");
    109 	}
    110 
    111 	return ptab.head->r;
    112 }
    113 
    114 void
    115 isr_hard_fault(void) {
    116 	puts("hard fault");
    117 	halt();
    118 }
    119 
    120 void
    121 isr_svcall(void) {
    122 	puts("svcall");
    123 }