1     #include <Mega32.h>
2     #include <delay.h>
3     #include <math.h>
4     #include <stdlib.h>
5     #include <stdio.h>
6     #include "os.h"
7     #include "os.c"
8     #include "thread.c"
9     #include "semaphore.c"
10    #include "message.c"
11    #include "spm.c"
12    #include "mmc.c"
13
14    void initialize(void);
15    void sdthread(void);
16
17    void main(void)
18    {
19       DDRC = 0xFF;
20       initialize();
21
22       // how did we get here???
23       while (1)
24       {
25          PORTC ^= 0xFF;
26          delay_ms(1000);
27       }
28    }
29    os_thread *tt1;
30    #asm
31    .cseg
32    .equ oldpc1=pc
33    .org 0x3000
34    #endasm
35
36    void sdthread()
37    {
38       os_thread *thread, *temp_thread, *next_thread;
39       char c;
40       UCHAR *buffer;
41       UINT *ibuffer;
42       register UINT progSize, i;
43       thread = g_currthread;
44
45       PORTC = 0xFF;
46
47       while (1)
48       {
49          c = MmcInit();
50          if (c == 0)
51          {
52             PORTC &= 0b11111110;
53          }
54          else
55          {
56             PORTC |= 0b00000001;
57          }
58          if (c == 0 && PINB.1 == 0)
59          {
60             // we want to load a new program
61             temp_thread = g_usedthreads;
62             while (temp_thread != NULL)
63             {
64                // kill any thread but the null/sd thread
65                if (temp_thread != thread)
66                {
67                   next_thread = temp_thread->next;
68                   TerminateThread(temp_thread);
69                   temp_thread = next_thread;
70                }
71                else
72                {
73                   temp_thread = temp_thread->next;
74                }
75             }
76             os_reset_stack();
77
78             // grab some stack space
79             buffer = (UCHAR*)os_alloc_stack(512);
80
81             // read in the first sector. The first 2 bytes are the size of the program
82             mmc_read_sector(0, buffer);
83             progSize = (((int)buffer[0]) << 8) | buffer[1];
84
85             // just write 0x00 and jmp to 0x01
86             buffer[0] = buffer[1] = 0;
87
88             // write the first sector
89             WriteSector(0, buffer);
90
91             for (i = 512; i < progSize; i += 512)
92             {
93                mmc_read_sector(i, buffer);
94                   WriteSector(i, buffer);
95             }
96             os_reset_stack();
97             #asm("cli");
98             temp_thread = CreateThread(1, 255, 150, 150);
99             #asm("sei");
100         }
101      }
102   }
103
104   //********************************************************** 
105   //Set it all up
106
107   void init_api(void)
108   {
109       SleepThreadPtr      = SleepThread;
110       CreateThreadPtr     = CreateThread;
111       SuspendThreadPtr    = SuspendThread;
112       ResumeThreadPtr     = ResumeThread;
113       TerminateThreadPtr  = TerminateThread;
114       FindThreadPtr       = FindThread;
115
116       CreateSemaphorePtr  = CreateSemaphore;
117       WaitSemaphorePtr    = WaitSemaphore;
118       SignalSemaphorePtr  = SignalSemaphore;
119
120       SendMessagePtr      = SendMessage;
121       ReceiveMessagePtr   = ReceiveMessage;
122   }
123   void init_structures(void)
124   {
125       register char i;
126       os_thread *temp_thread, *prev_thread;
127       os_semaphore *temp_semaphore, *prev_semaphore;
128      os_threadsem *temp_threadsem;
129      os_message *temp_message;
130
131      g_threadcount = 0;
132
133      // initialize list of threads
134       g_freethreads = &g_allthreads[0];
135       prev_thread = NULL;
136       temp_thread = g_freethreads;
137      for (i = 1; i < THREAD_COUNT; ++i)
138      {
139           temp_thread->next = &g_allthreads[i];
140         temp_thread->prev = prev_thread;
141         temp_thread->threadID = i;
142
143         prev_thread = temp_thread;
144         temp_thread = temp_thread->next;
145      }
146      temp_thread->threadID = i;
147      temp_thread->prev = prev_thread;
148      temp_thread->next = NULL;
149
150      // initialize list of semaphores
151       g_freesemaphores = &g_allsemaphores[0];
152       prev_semaphore = NULL;
153       temp_semaphore = g_freesemaphores;
154      for (i = 1; i < SEMAPHORE_COUNT; ++i)
155      {
156           temp_semaphore->next = &g_allsemaphores[i];
157         temp_semaphore->prev = prev_semaphore;
158
159         prev_semaphore = temp_semaphore;
160         temp_semaphore = temp_semaphore->next;
161      }
162      temp_semaphore->prev = prev_semaphore;
163      temp_semaphore->next = NULL;
164
165      // initialize list of thread/semaphore holders
166       g_freethreadsems = &g_allthreadsems[0];
167       temp_threadsem = g_freethreadsems;
168      for (i = 1; i < THREADSEM_COUNT; ++i)
169      {
170           temp_threadsem->next = &g_allthreadsems[i];
171         temp_threadsem = temp_threadsem->next;
172      }
173      temp_threadsem->next = NULL;
174
175      // initialize list of message holders
176       g_freemessages = &g_allmessages[0];
177       temp_message = g_freemessages;
178      for (i = 1; i < MESSAGE_COUNT; ++i)
179      {
180           temp_message->next = &g_allmessages[i];
181         temp_message = temp_message->next;
182      }
183      temp_threadsem->next = NULL;
184
185      // allocate the stack
186      g_stkCurrent = g_stkStart = &g_stkBlock[0];
187      g_stkEnd = g_stkStart + TOTAL_STACK_SIZE;
188   }
189   void initialize(void)
190   {
191       UCHAR *sd_swstack, *sd_hwstack;
192
193       // set up UART   
194       UCSRB = 0x18;
195       UBRRL = 51;
196
197       // set up Timer0 for scheduling every 10ms
198       TCNT0 = 0x00;
199       OCR0  = 15.6 * 10;
200       TIMSK = 0x02;
201       TCCR0 = 0b00001101;
202
203       init_api();
204      init_structures();
205
206       // create some uart semaphores
207      g_uart_t_semaphore = CreateSemaphore(1);
208      g_uart_r_semaphore = CreateSemaphore(1);
209
210       // create the SD card thread
211      g_currthread = CreateThread(sdthread, 255, 150, 150);
212
213      // We never want to free the sd threads stack
214      g_stkStart += 200;
215
216      sd_swstack = g_currthread->swstack;
217      sd_hwstack = g_currthread->hwstack;
218
219       #asm
220           ; Load new HW stack pointer, low first
221           LDD   R30,Y+0
222           OUT   SPL,R30
223           LDD   R30,Y+1
224           OUT   SPH,R30
225
226           ; Load new data stack pointer, low first
227           LDD      R30,Y+2
228           LDD      R31,Y+3
229           MOV      R28,R30
230           MOV      R29,R31
231       #endasm
232
233
234       // OUT SREG, R0      will enable interrupts, so CPU control will
235       // yield here to the other thread. It will return when control
236       // is switched back to the null thread.
237       #asm
238           POP      R0
239           OUT      SREG,R0
240           POP      R31
241           POP      R30
242           POP      R27
243           POP      R26
244           POP      R25
245           POP      R24
246           POP      R23
247           POP      R22
248           POP      R21
249           POP      R20
250           POP      R19
251           POP      R18
252           POP      R17
253           POP      R16
254           POP      R15
255           POP      R14
256           POP      R13
257           POP      R12
258           POP      R11
259           POP      R10
260           POP      R9
261           POP      R8
262           POP      R7
263           POP      R6
264           POP      R5
265           POP      R4
266           POP      R3
267           POP      R2
268           POP      R1
269           POP      R0
270
271           RETI
272       #endasm
273   }
274   #asm
275   .org oldpc1
276   #endasm