├── .gitignore
├── project.uvproj
└── src
├── STARTUP.A51
├── STC15Fxxxx.H
├── adsensor.c
├── adsensor.h
├── bit_ops.h
├── button.c
├── button.h
├── config.h
├── ds1302.c
├── ds1302.h
├── events.c
├── events.h
├── global.h
├── main.c
├── random.c
├── random.h
├── rs485.c
├── rs485.h
├── scheduler.c
├── scheduler.h
├── seg_led.c
├── seg_led.h
├── semaphore.c
├── semaphore.h
├── spin.c
├── spin.h
├── stack.c
├── stack.h
├── stack.inc
├── stc15fxxxx.inc
├── syscall.a51
├── syscall.h
├── syscall_c.c
├── timer0_isr.a51
├── timer0_isr.h
├── timer0_isr_c.c
├── usbcom.c
├── usbcom.h
├── xbp_helper.a51
├── xstack.c
├── xstack.h
└── xstack.inc
/.gitignore:
--------------------------------------------------------------------------------
1 | /Listings
2 | /Objects
3 | *.bak
4 | *.uvgui.*
5 | *.uvopt
6 |
--------------------------------------------------------------------------------
/project.uvproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | 1.1
5 |
6 | ### uVision Project, (C) Keil Software
7 |
8 |
9 |
10 | Target 1
11 | 0x0
12 | MCS-51
13 |
14 |
15 | STC15F2K60S2
16 | STC
17 | IRAM(0-0xFF) XRAM(0-0x6FF) IROM(0-0xEFF8) CLOCK(35000000) MODP2
18 |
19 | "LIB\STARTUP.A51" ("Standard 8051 Startup Code")
20 |
21 | 62472
22 | STC15F2K60S2.H
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 | 0
34 |
35 |
36 |
37 | STC\
38 | STC\
39 |
40 | 0
41 | 0
42 | 0
43 | 0
44 | 1
45 |
46 | .\Objects\
47 | project
48 | 1
49 | 0
50 | 1
51 | 1
52 | 1
53 | .\Listings\
54 | 0
55 | 0
56 | 0
57 |
58 | 0
59 | 0
60 |
61 |
62 | 0
63 | 0
64 | 0
65 | 0
66 |
67 |
68 | 0
69 | 0
70 |
71 |
72 | 0
73 | 0
74 |
75 |
76 | 0
77 | 0
78 |
79 |
80 | 0
81 | 0
82 |
83 | 0
84 |
85 |
86 |
87 | 0
88 | 0
89 | 0
90 | 0
91 | 0
92 | 1
93 | 0
94 | 0
95 | 0
96 | 0
97 | 3
98 |
99 |
100 | 65535
101 |
102 |
103 | S8051.DLL
104 |
105 | DP51.DLL
106 | -pDP8051
107 | S8051.DLL
108 |
109 | TP51.DLL
110 | -p51
111 |
112 |
113 |
114 | 0
115 | 0
116 | 0
117 | 0
118 | 16
119 |
120 |
121 | 1
122 | 1
123 | 1
124 | 1
125 | 1
126 | 1
127 | 1
128 | 1
129 | 0
130 |
131 |
132 | 0
133 | 1
134 | 0
135 | 1
136 | 1
137 | 1
138 | 0
139 | 1
140 | 1
141 |
142 | 0
143 | -1
144 |
145 |
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
159 |
160 |
161 |
162 | 0
163 | 0
164 | 0
165 | 0
166 | 0
167 | -1
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 | 2
176 | 0
177 | 2
178 | 0
179 | 0
180 | 0
181 | 0
182 | 0
183 | 0
184 | 1
185 | 1
186 | 1
187 | 0
188 | 0
189 | 1
190 | 0
191 | 0
192 | 0
193 | 0
194 | 0
195 | 1
196 | 1
197 | 0
198 | 0
199 | 0
200 | 0
201 | 0
202 | 0
203 | 0
204 | 0
205 | 0
206 | 0
207 | 0
208 | 0
209 | 0
210 | 0
211 | 0
212 | 0
213 | 0
214 | 0
215 | 0
216 |
217 |
218 | 0
219 | 0x0
220 | 0xffff
221 |
222 |
223 | 0
224 | 0x0
225 | 0x0
226 |
227 |
228 | 0
229 | 0x0
230 | 0x0
231 |
232 |
233 | 0
234 | 0x0
235 | 0x0
236 |
237 |
238 | 0
239 | 0x0
240 | 0x0
241 |
242 |
243 | 0
244 | 0x0
245 | 0x0
246 |
247 |
248 | 0
249 | 0x0
250 | 0x0
251 |
252 |
253 | 0
254 | 0x0
255 | 0x0
256 |
257 |
258 | 1
259 | 0x0
260 | 0xeff9
261 |
262 |
263 | 0
264 | 0x0
265 | 0x100
266 |
267 |
268 | 0
269 | 0x0
270 | 0x700
271 |
272 |
273 | 0
274 | 0x0
275 | 0x0
276 |
277 |
278 | 0
279 | 0x0
280 | 0x0
281 |
282 |
283 |
284 |
285 | 0
286 | 0
287 | 1
288 | 0
289 | 1
290 | 3
291 | 0
292 | 2
293 | 1
294 | 1
295 | 0
296 | 0
297 |
298 |
299 |
300 |
301 |
302 |
303 |
304 |
305 | 0
306 | 1
307 | 0
308 | 0
309 |
310 |
311 |
312 |
313 |
314 |
315 |
316 |
317 | 0
318 | 0
319 | 1
320 | 0
321 | 2
322 | 1
323 |
324 |
325 |
326 |
327 |
328 |
329 |
330 |
331 |
332 |
333 |
334 |
335 |
336 |
337 |
338 |
339 |
340 |
341 |
342 |
343 |
344 |
345 |
346 |
347 |
348 |
349 |
350 |
351 | stack
352 |
353 |
354 | stack.c
355 | 1
356 | .\src\stack.c
357 |
358 |
359 | stack.inc
360 | 5
361 | .\src\stack.inc
362 |
363 |
364 | stack.h
365 | 5
366 | .\src\stack.h
367 |
368 |
369 |
370 |
371 | xstack
372 |
373 |
374 | xstack.c
375 | 1
376 | .\src\xstack.c
377 |
378 |
379 | xstack.h
380 | 5
381 | .\src\xstack.h
382 |
383 |
384 | xstack.inc
385 | 5
386 | .\src\xstack.inc
387 |
388 |
389 | xbp_helper.a51
390 | 2
391 | .\src\xbp_helper.a51
392 |
393 |
394 |
395 |
396 | utils
397 |
398 |
399 | random.c
400 | 1
401 | .\src\random.c
402 |
403 |
404 | spin.c
405 | 1
406 | .\src\spin.c
407 |
408 |
409 | random.h
410 | 5
411 | .\src\random.h
412 |
413 |
414 | spin.h
415 | 5
416 | .\src\spin.h
417 |
418 |
419 | bit_ops.h
420 | 5
421 | .\src\bit_ops.h
422 |
423 |
424 |
425 |
426 | drivers
427 |
428 |
429 | adsensor.c
430 | 1
431 | .\src\adsensor.c
432 |
433 |
434 | button.c
435 | 1
436 | .\src\button.c
437 |
438 |
439 | ds1302.c
440 | 1
441 | .\src\ds1302.c
442 |
443 |
444 | rs485.c
445 | 1
446 | .\src\rs485.c
447 |
448 |
449 | usbcom.c
450 | 1
451 | .\src\usbcom.c
452 |
453 |
454 | adsensor.h
455 | 5
456 | .\src\adsensor.h
457 |
458 |
459 | button.h
460 | 5
461 | .\src\button.h
462 |
463 |
464 | ds1302.h
465 | 5
466 | .\src\ds1302.h
467 |
468 |
469 | rs485.h
470 | 5
471 | .\src\rs485.h
472 |
473 |
474 | usbcom.h
475 | 5
476 | .\src\usbcom.h
477 |
478 |
479 | seg_led.c
480 | 1
481 | .\src\seg_led.c
482 |
483 |
484 | seg_led.h
485 | 5
486 | .\src\seg_led.h
487 |
488 |
489 |
490 |
491 | semaphore
492 |
493 |
494 | semaphore.c
495 | 1
496 | .\src\semaphore.c
497 |
498 |
499 | semaphore.h
500 | 5
501 | .\src\semaphore.h
502 |
503 |
504 |
505 |
506 | events
507 |
508 |
509 | events.c
510 | 1
511 | .\src\events.c
512 |
513 |
514 | events.h
515 | 5
516 | .\src\events.h
517 |
518 |
519 |
520 |
521 | scheduler
522 |
523 |
524 | scheduler.c
525 | 1
526 | .\src\scheduler.c
527 |
528 |
529 | scheduler.h
530 | 5
531 | .\src\scheduler.h
532 |
533 |
534 |
535 |
536 | timer0_isr
537 |
538 |
539 | timer0_isr_c.c
540 | 1
541 | .\src\timer0_isr_c.c
542 |
543 |
544 | timer0_isr.h
545 | 5
546 | .\src\timer0_isr.h
547 |
548 |
549 | timer0_isr.a51
550 | 2
551 | .\src\timer0_isr.a51
552 |
553 |
554 |
555 |
556 | syscall
557 |
558 |
559 | syscall_c.c
560 | 1
561 | .\src\syscall_c.c
562 |
563 |
564 | syscall.h
565 | 5
566 | .\src\syscall.h
567 |
568 |
569 | syscall.a51
570 | 2
571 | .\src\syscall.a51
572 |
573 |
574 |
575 |
576 | startup
577 |
578 |
579 | main.c
580 | 1
581 | .\src\main.c
582 |
583 |
584 | STARTUP.A51
585 | 2
586 | .\src\STARTUP.A51
587 |
588 |
589 |
590 |
591 | stc
592 |
593 |
594 | global.h
595 | 5
596 | .\src\global.h
597 |
598 |
599 | STC15Fxxxx.H
600 | 5
601 | .\src\STC15Fxxxx.H
602 |
603 |
604 | stc15fxxxx.inc
605 | 5
606 | .\src\stc15fxxxx.inc
607 |
608 |
609 | config.h
610 | 5
611 | .\src\config.h
612 |
613 |
614 |
615 |
616 |
617 |
618 |
619 |
620 |
--------------------------------------------------------------------------------
/src/STARTUP.A51:
--------------------------------------------------------------------------------
1 | $NOMOD51
2 | ;------------------------------------------------------------------------------
3 | ; This file is part of the C51 Compiler package
4 | ; Copyright (c) 1988-2005 Keil Elektronik GmbH and Keil Software, Inc.
5 | ; Version 8.01
6 | ;
7 | ; *** <<< Use Configuration Wizard in Context Menu >>> ***
8 | ;------------------------------------------------------------------------------
9 | ; STARTUP.A51: This code is executed after processor reset.
10 | ;
11 | ; To translate this file use A51 with the following invocation:
12 | ;
13 | ; A51 STARTUP.A51
14 | ;
15 | ; To link the modified STARTUP.OBJ file to your application use the following
16 | ; Lx51 invocation:
17 | ;
18 | ; Lx51 your object file list, STARTUP.OBJ controls
19 | ;
20 | ;------------------------------------------------------------------------------
21 | ;
22 | ; User-defined Power-On Initialization of Memory
23 | ;
24 | ; With the following EQU statements the initialization of memory
25 | ; at processor reset can be defined:
26 | ;
27 | ; IDATALEN: IDATA memory size <0x0-0x100>
28 | ; Note: The absolute start-address of IDATA memory is always 0
29 | ; The IDATA space overlaps physically the DATA and BIT areas.
30 | IDATALEN EQU 256
31 | ;
32 | ; XDATASTART: XDATA memory start address <0x0-0xFFFF>
33 | ; The absolute start address of XDATA memory
34 | XDATASTART EQU 0
35 | ;
36 | ; XDATALEN: XDATA memory size <0x0-0xFFFF>
37 | ; The length of XDATA memory in bytes.
38 | XDATALEN EQU 2048-256
39 | ;
40 | ; PDATASTART: PDATA memory start address <0x0-0xFFFF>
41 | ; The absolute start address of PDATA memory
42 | PDATASTART EQU 0H
43 | ;
44 | ; PDATALEN: PDATA memory size <0x0-0xFF>
45 | ; The length of PDATA memory in bytes.
46 | PDATALEN EQU 0H
47 | ;
48 | ;
49 | ;------------------------------------------------------------------------------
50 | ;
51 | ; Reentrant Stack Initialization
52 | ;
53 | ; The following EQU statements define the stack pointer for reentrant
54 | ; functions and initialized it:
55 | ;
56 | ; Stack Space for reentrant functions in the SMALL model.
57 | ; IBPSTACK: Enable SMALL model reentrant stack
58 | ; Stack space for reentrant functions in the SMALL model.
59 | IBPSTACK EQU 0 ; set to 1 if small reentrant is used.
60 | ; IBPSTACKTOP: End address of SMALL model stack <0x0-0xFF>
61 | ; Set the top of the stack to the highest location.
62 | IBPSTACKTOP EQU 0xFF +1 ; default 0FFH+1
63 | ;
64 | ;
65 | ; Stack Space for reentrant functions in the LARGE model.
66 | ; XBPSTACK: Enable LARGE model reentrant stack
67 | ; Stack space for reentrant functions in the LARGE model.
68 | XBPSTACK EQU 1 ; set to 1 if large reentrant is used.
69 | ; XBPSTACKTOP: End address of LARGE model stack <0x0-0xFFFF>
70 | ; Set the top of the stack to the highest location.
71 | XBPSTACKTOP EQU 0xFFFF +1 ; default 0FFFFH+1
72 | ;
73 | ;
74 | ; Stack Space for reentrant functions in the COMPACT model.
75 | ; PBPSTACK: Enable COMPACT model reentrant stack
76 | ; Stack space for reentrant functions in the COMPACT model.
77 | PBPSTACK EQU 0 ; set to 1 if compact reentrant is used.
78 | ;
79 | ; PBPSTACKTOP: End address of COMPACT model stack <0x0-0xFFFF>
80 | ; Set the top of the stack to the highest location.
81 | PBPSTACKTOP EQU 0xFF +1 ; default 0FFH+1
82 | ;
83 | ;
84 | ;------------------------------------------------------------------------------
85 | ;
86 | ; Memory Page for Using the Compact Model with 64 KByte xdata RAM
87 | ; Compact Model Page Definition
88 | ;
89 | ; Define the XDATA page used for PDATA variables.
90 | ; PPAGE must conform with the PPAGE set in the linker invocation.
91 | ;
92 | ; Enable pdata memory page initalization
93 | PPAGEENABLE EQU 0 ; set to 1 if pdata object are used.
94 | ;
95 | ; PPAGE number <0x0-0xFF>
96 | ; uppermost 256-byte address of the page used for PDATA variables.
97 | PPAGE EQU 0
98 | ;
99 | ; SFR address which supplies uppermost address byte <0x0-0xFF>
100 | ; most 8051 variants use P2 as uppermost address byte
101 | PPAGE_SFR DATA 0A0H
102 | ;
103 | ;
104 | ;------------------------------------------------------------------------------
105 |
106 | ; Standard SFR Symbols
107 | ACC DATA 0E0H
108 | B DATA 0F0H
109 | SP DATA 81H
110 | DPL DATA 82H
111 | DPH DATA 83H
112 |
113 | NAME ?C_STARTUP
114 |
115 |
116 | ?C_C51STARTUP SEGMENT CODE
117 | ?STACK SEGMENT IDATA
118 |
119 | RSEG ?STACK
120 | DS 1
121 |
122 | EXTRN CODE (?C_START)
123 | PUBLIC ?C_STARTUP
124 |
125 | CSEG AT 0
126 | ?C_STARTUP: LJMP STARTUP1
127 |
128 | RSEG ?C_C51STARTUP
129 |
130 | STARTUP1:
131 |
132 | IF IDATALEN <> 0
133 | MOV R0,#IDATALEN - 1
134 | CLR A
135 | IDATALOOP: MOV @R0,A
136 | DJNZ R0,IDATALOOP
137 | ENDIF
138 |
139 | IF XDATALEN <> 0
140 | MOV DPTR,#XDATASTART
141 | MOV R7,#LOW (XDATALEN)
142 | IF (LOW (XDATALEN)) <> 0
143 | MOV R6,#(HIGH (XDATALEN)) +1
144 | ELSE
145 | MOV R6,#HIGH (XDATALEN)
146 | ENDIF
147 | CLR A
148 | XDATALOOP: MOVX @DPTR,A
149 | INC DPTR
150 | DJNZ R7,XDATALOOP
151 | DJNZ R6,XDATALOOP
152 | ENDIF
153 |
154 | IF PPAGEENABLE <> 0
155 | MOV PPAGE_SFR,#PPAGE
156 | ENDIF
157 |
158 | IF PDATALEN <> 0
159 | MOV R0,#LOW (PDATASTART)
160 | MOV R7,#LOW (PDATALEN)
161 | CLR A
162 | PDATALOOP: MOVX @R0,A
163 | INC R0
164 | DJNZ R7,PDATALOOP
165 | ENDIF
166 |
167 | IF IBPSTACK <> 0
168 | EXTRN DATA (?C_IBP)
169 |
170 | MOV ?C_IBP,#LOW IBPSTACKTOP
171 | ENDIF
172 |
173 | IF XBPSTACK <> 0
174 | EXTRN DATA (?C_XBP)
175 |
176 | MOV ?C_XBP,#HIGH XBPSTACKTOP
177 | MOV ?C_XBP+1,#LOW XBPSTACKTOP
178 | ENDIF
179 |
180 | IF PBPSTACK <> 0
181 | EXTRN DATA (?C_PBP)
182 | MOV ?C_PBP,#LOW PBPSTACKTOP
183 | ENDIF
184 |
185 | MOV SP,#?STACK-1
186 |
187 | ; This code is required if you use L51_BANK.A51 with Banking Mode 4
188 | ; Code Banking
189 | ; Select Bank 0 for L51_BANK.A51 Mode 4
190 | #if 0
191 | ; Initialize bank mechanism to code bank 0 when using L51_BANK.A51 with Banking Mode 4.
192 | EXTRN CODE (?B_SWITCH0)
193 | CALL ?B_SWITCH0 ; init bank mechanism to code bank 0
194 | #endif
195 | ;
196 | LJMP ?C_START
197 |
198 | END
199 |
--------------------------------------------------------------------------------
/src/STC15Fxxxx.H:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FishyFizz/STC-B-OS/743279ab40fb298dc0140349a8d9971048b70a1b/src/STC15Fxxxx.H
--------------------------------------------------------------------------------
/src/adsensor.c:
--------------------------------------------------------------------------------
1 | #include "adsensor.h"
2 |
3 | XDATA u8 adc_initialized = 0;
4 | void adc_init()
5 | {
6 | if(adc_initialized)
7 | return;
8 |
9 | /*
10 | Initalize ADC:
11 | P1.2 for HALL sensor
12 | P1.3 for Temperature sensor
13 | P1.4 for Light sensor
14 | P1.7 for Button3 and Navigation Button
15 | */
16 | P1ASF = ADC_P12 | ADC_P13 | ADC_P14 | ADC_P17;
17 |
18 | ADC_CONTR |= 0x80; //Power On
19 | ADC_CONTR = (ADC_CONTR & ~ADC_90T) | ADC_90T; //Speed select
20 | PCON2 &= ~(1<<5); //result byte order: high->ADC_RES
21 | EADC = 0; //use polling, no interrupt
22 |
23 | adc_initialized = 1;
24 | }
25 |
26 | u8 adc_read(u8 channel) //u8
27 | {
28 | XDATA u8 timeout;
29 | ADC_RES = 0;
30 |
31 | ADC_CONTR = (ADC_CONTR & 0xe0) | ADC_START | channel; //select channel
32 | NOP(4);
33 |
34 | //poll
35 | for(timeout=0; timeout<250; timeout++)
36 | {
37 | if(ADC_CONTR & ADC_FLAG)
38 | {
39 | ADC_CONTR &= ~ADC_FLAG;
40 | return ADC_RES;
41 | }
42 | }
43 |
44 | return 0;
45 | }
--------------------------------------------------------------------------------
/src/adsensor.h:
--------------------------------------------------------------------------------
1 | #ifndef _ADSENSOR_H_
2 | #define _ADSENSOR_H_
3 |
4 | #include "global.h"
5 |
6 | #define ADC_P12 0x04 //HALL
7 | #define ADC_P13 0x08 //Temperature
8 | #define ADC_P14 0x10 //Light
9 | #define ADC_P17 0x80 //Button3 / Nav
10 | #define ADC_90T (3<<5)
11 |
12 | #define ADC_HALL 2
13 | #define ADC_TEMP 3
14 | #define ADC_LIGHT 4
15 | #define ADC_NAV 7
16 |
17 | #define ADC_FLAG (1<<4) //ADC OK (flag reset by software)
18 | #define ADC_START (1<<3) //ADC Start (flag reset by hardware)
19 |
20 | extern XDATA u8 adc_initialized;
21 | void adc_init();
22 | u8 adc_read(u8 channel);
23 |
24 | #endif
--------------------------------------------------------------------------------
/src/bit_ops.h:
--------------------------------------------------------------------------------
1 |
2 | #define BIT(x) ((u8)(1<<(x)))
3 | #define CLEARBIT(var, bit) {(var) &= ~(1<<(bit));}
4 | #define SETBIT(var, bit) {(var) |= (1<<(bit));}
5 | #define INVOF(bit) ((bit==0)?1:0)
6 | #define WRITEBIT(var, bit, wrt) {CLEARBIT(var,bit); var|=(((u8)(wrt))<<(bit));}
7 | #define GETBIT(var,bit) (((var)&BIT(bit))?1:0)
8 |
9 | #define RSL(var) (((var)<<1) + ((var)>>7))
10 | #define HIGH8(x) ((x)&0xff00)
11 | #define LOW8(x) ((x)&0x00ff)
12 | #define HIGH16(x) (((x)&0xffff0000)>>16)
13 | #define LOW16(x) ((x)&0x0000ffff)
--------------------------------------------------------------------------------
/src/button.c:
--------------------------------------------------------------------------------
1 | #include "button.h"
2 |
3 | XDATA u8 __nav_btn3_state = 0xff;
4 | XDATA u8 btnstate_posedge =0;
5 | XDATA u8 btnstate_negedge =0;
6 | XDATA u8 last_btn_states[BTN_DENOISE_LEVEL];
7 |
8 | void buttons_init()
9 | {
10 | //Initialize ADC for Nav and Button3
11 | adc_init();
12 |
13 | //Set Button1 and Button2 pin to Weak Pullup (M1 = 0, M0 = 0)
14 | P3M1 &= 0xF3; // 1111 0011
15 | P3M0 &= 0xF3; // 1111 0011
16 |
17 | //Set P17 to Weak Pullup (M1 = 0, M0 = 0)
18 | //P17 Pullup -> Key3 -> Nav Button(different resistance) -> GND
19 | P1M1 &= 0x7F; // 0111 1111
20 | P1M0 &= 0x7F; // 0111 1111
21 | }
22 |
23 | void update_button_state()
24 | {
25 | XDATA u8 i; //Only use this function in timer0 isr. this variable prevents reentrancy.
26 |
27 | btnstate_posedge = btnstate_negedge = 0;
28 |
29 | //rotate previous button states. older one replaced by newer one.
30 | for(i = BTN_DENOISE_LEVEL-1; i>=1; i--)
31 | last_btn_states[i] = last_btn_states[i-1];
32 |
33 | //update current button state, and cauculate bit flags
34 | update_nav_btn3_state();
35 | last_btn_states[0] = 0;
36 | last_btn_states[0] |= BUTTON1 ?BTNSTATE_B1 :0;
37 | last_btn_states[0] |= BUTTON2 ?BTNSTATE_B2 :0;
38 | last_btn_states[0] |= IS_BTN3_PUSH ?BTNSTATE_B3 :0;
39 | last_btn_states[0] |= IS_NAV_LEFT ?BTNSTATE_LEFT :0;
40 | last_btn_states[0] |= IS_NAV_RIGHT ?BTNSTATE_RIGHT :0;
41 | last_btn_states[0] |= IS_NAV_UP ?BTNSTATE_UP :0;
42 | last_btn_states[0] |= IS_NAV_DOWN ?BTNSTATE_DOWN :0;
43 | last_btn_states[0] |= IS_NAV_PUSH ?BTNSTATE_PUSH :0;
44 |
45 | //check new state hold
46 | for(i=0;i posedge
53 | btnstate_posedge = (last_btn_states[0] ^ last_btn_states[BTN_DENOISE_LEVEL-1]) & (last_btn_states[0]);
54 |
55 | //different from old states, and previously set -> negedge
56 | btnstate_negedge = (last_btn_states[0] ^ last_btn_states[BTN_DENOISE_LEVEL-1]) & (last_btn_states[BTN_DENOISE_LEVEL-1]);
57 | }
--------------------------------------------------------------------------------
/src/button.h:
--------------------------------------------------------------------------------
1 | #ifndef _BUTTON_H_
2 | #define _BUTTON_H_
3 |
4 | #include "global.h"
5 | #include "adsensor.h"
6 |
7 | //Button is connected to Weak Pullup pin. When pushed, the pin is pulled down.
8 | //True if button is pushed down.
9 | #define BUTTON1 (~P32)
10 | #define BUTTON2 (~P33)
11 |
12 | //Navigation Button and Button3 are connected to analog input.
13 |
14 | //Get raw analog data.
15 | #define nav_btn3_adc() adc_read(ADC_NAV)
16 |
17 |
18 | #define BTNSTATE_B1 0x1
19 | #define BTNSTATE_B2 0x2
20 | #define BTNSTATE_B3 0x4
21 | #define BTNSTATE_UP 0x8
22 | #define BTNSTATE_DOWN 0x10
23 | #define BTNSTATE_LEFT 0x20
24 | #define BTNSTATE_RIGHT 0x40
25 | #define BTNSTATE_PUSH 0x80
26 |
27 | #define BTN_DENOISE_LEVEL 20
28 |
29 | extern XDATA u8 btnstate_posedge;
30 | extern XDATA u8 btnstate_negedge;
31 | extern XDATA u8 last_btn_states[BTN_DENOISE_LEVEL];
32 |
33 | /*
34 | Usage:
35 |
36 | update_nav_btn3_state();
37 | if(IS_NAV_LEFT)
38 | ......
39 |
40 | */
41 | extern XDATA u8 __nav_btn3_state;
42 | #define update_nav_btn3_state() {__nav_btn3_state = adc_read(ADC_NAV);}
43 |
44 | #define IS_NAV_BTN3_IDLE ((__nav_btn3_state) >> 5 >= 6) // 110 or 111
45 | #define IS_NAV_UP ((__nav_btn3_state) >> 5 == 5) // 101
46 | #define IS_NAV_LEFT ((__nav_btn3_state) >> 5 == 4) // 100
47 | #define IS_NAV_PUSH ((__nav_btn3_state) >> 5 == 3) // 011
48 | #define IS_NAV_DOWN ((__nav_btn3_state) >> 5 == 2) // 010
49 | #define IS_NAV_RIGHT ((__nav_btn3_state) >> 5 == 1) // 001
50 | #define IS_BTN3_PUSH ((__nav_btn3_state) >> 5 == 0) // 000
51 |
52 | void buttons_init();
53 | void update_button_state();
54 |
55 | #endif //_BUTTON_H_
--------------------------------------------------------------------------------
/src/config.h:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/FishyFizz/STC-B-OS/743279ab40fb298dc0140349a8d9971048b70a1b/src/config.h
--------------------------------------------------------------------------------
/src/ds1302.c:
--------------------------------------------------------------------------------
1 | #include "ds1302.h"
2 | #include "seg_led.h"
3 |
4 | void ds1302_writebyte(u8 addr, u8 write)
5 | {
6 | ds1302_dout();
7 |
8 | DS1302_RST = 1; //Initiate communication
9 |
10 | DS1302_IO = 0; //WRITE
11 | ds1302_clockpulse();
12 |
13 | //address
14 | {
15 | DS1302_IO = GETBIT(addr,0);
16 | ds1302_clockpulse();
17 |
18 | DS1302_IO = GETBIT(addr,1);
19 | ds1302_clockpulse();
20 |
21 | DS1302_IO = GETBIT(addr,2);
22 | ds1302_clockpulse();
23 |
24 | DS1302_IO = GETBIT(addr,3);
25 | ds1302_clockpulse();
26 |
27 | DS1302_IO = GETBIT(addr,4);
28 | ds1302_clockpulse();
29 |
30 | DS1302_IO = GETBIT(addr,5); // 0-> Time, 1-> RAM
31 | ds1302_clockpulse();
32 | }
33 |
34 | DS1302_IO = 1;
35 | ds1302_clockpulse();
36 |
37 |
38 | //data
39 | {
40 | DS1302_IO = GETBIT(write,0);
41 | ds1302_clockpulse();
42 |
43 | DS1302_IO = GETBIT(write,1);
44 | ds1302_clockpulse();
45 |
46 | DS1302_IO = GETBIT(write,2);
47 | ds1302_clockpulse();
48 |
49 | DS1302_IO = GETBIT(write,3);
50 | ds1302_clockpulse();
51 |
52 | DS1302_IO = GETBIT(write,4);
53 | ds1302_clockpulse();
54 |
55 | DS1302_IO = GETBIT(write,5);
56 | ds1302_clockpulse();
57 |
58 | DS1302_IO = GETBIT(write,6);
59 | ds1302_clockpulse();
60 |
61 | DS1302_IO = GETBIT(write,7);
62 | ds1302_clockpulse();
63 | }
64 |
65 |
66 | //reset pins
67 | DS1302_SCLK = 0;
68 | DS1302_IO = 0;
69 | DS1302_RST = 0;
70 | }
71 |
72 |
73 | u8 ds1302_readbyte(u8 addr)
74 | {
75 | XDATA u8 read = 0;
76 |
77 | ds1302_dout();
78 |
79 | DS1302_RST = 1; //Initiate communication
80 |
81 | DS1302_IO = 1; //READ
82 | ds1302_clockpulse();
83 |
84 | //address
85 | {
86 | DS1302_IO = GETBIT(addr,0);
87 | ds1302_clockpulse();
88 |
89 | DS1302_IO = GETBIT(addr,1);
90 | ds1302_clockpulse();
91 |
92 | DS1302_IO = GETBIT(addr,2);
93 | ds1302_clockpulse();
94 |
95 | DS1302_IO = GETBIT(addr,3);
96 | ds1302_clockpulse();
97 |
98 | DS1302_IO = GETBIT(addr,4);
99 | ds1302_clockpulse();
100 |
101 | DS1302_IO = GETBIT(addr,5); // 0-> Time, 1-> RAM
102 | ds1302_clockpulse();
103 | }
104 |
105 | DS1302_IO = 1;
106 | ds1302_clockpulse();
107 |
108 | ds1302_din();
109 | //data
110 | {
111 | WRITEBIT(read, 0, DS1302_IO);
112 | ds1302_clockpulse();
113 |
114 | WRITEBIT(read, 1, DS1302_IO);
115 | ds1302_clockpulse();
116 |
117 | WRITEBIT(read, 2, DS1302_IO);
118 | ds1302_clockpulse();
119 |
120 | WRITEBIT(read, 3, DS1302_IO);
121 | ds1302_clockpulse();
122 |
123 | WRITEBIT(read, 4, DS1302_IO);
124 | ds1302_clockpulse();
125 |
126 | WRITEBIT(read, 5, DS1302_IO);
127 | ds1302_clockpulse();
128 |
129 | WRITEBIT(read, 6, DS1302_IO);
130 | ds1302_clockpulse();
131 |
132 | WRITEBIT(read, 7, DS1302_IO);
133 | ds1302_clockpulse();
134 | }
135 |
136 | //reset pins
137 | DS1302_RST = 0;
138 | DS1302_SCLK = 0;
139 | DS1302_IO = 0;
140 |
141 | return read;
142 | }
143 |
--------------------------------------------------------------------------------
/src/ds1302.h:
--------------------------------------------------------------------------------
1 | #ifndef _DS1302_H_
2 | #define _DS1302_H_
3 |
4 | #include "global.h"
5 | #include "bit_ops.h"
6 | #include "scheduler.h"
7 |
8 | #define DS1302_RST P16
9 | #define DS1302_SCLK P15
10 | #define DS1302_IO P54
11 |
12 | #define DS1302_SEC 0
13 | #define DS1302_MIN 1
14 | #define DS1302_HR 2
15 |
16 | #define DS1302_DATE 3
17 | #define DS1302_MON 4
18 | #define DS1302_DAY 5
19 | #define DS1302_YEAR 6
20 |
21 | #define DS1302_WP 7
22 |
23 | void ds1302_writebyte(u8 addr, u8 write);
24 |
25 | u8 ds1302_readbyte(u8 addr);
26 |
27 | // P54->HiZ
28 | #define ds1302_din() {SETBIT(P5M1, 4); CLEARBIT(P5M0, 4);}
29 |
30 | // P54->Push-Pull
31 | #define ds1302_dout() {CLEARBIT(P5M1, 4); CLEARBIT(P5M0, 4);}
32 |
33 | // P15,P16 -> Push-Pull, P54 -> Push-Pull
34 | #define ds1302_init()\
35 | {\
36 | ds1302_dout();\
37 | CLEARBIT(P1M1,5); SETBIT(P1M0,5);\
38 | CLEARBIT(P1M1,6); SETBIT(P1M0,6);\
39 | DS1302_RST = 0;\
40 | DS1302_SCLK = 0;\
41 | DS1302_IO = 0;\
42 | }
43 |
44 | #define ds1302_clockpulse()\
45 | {\
46 | DS1302_SCLK = 1;\
47 | DS1302_SCLK = 0;\
48 | }
49 |
50 | #define DS1302_CONVERTSEC(x) (((x)&0x0f) + ((x&0x70)>>4)*10)
51 | #define DS1302_CONVERTMIN(x) DS1302_CONVERTSEC(x)
52 | #define DS1302_CONVERTHOUR(x) ((x&0x80) ? \
53 | (((x&0x0f)+((x&0x10)>>4)*10)+((x&0x20)?12:0)) : \
54 | ((x&0x30>>4)*10+(x&0x0f)))
55 | #define DS1302_CONVERTDATE(x) DS1302_CONVERTSEC(x)
56 | #define DS1302_CONVERTMONTH(x) DS1302_CONVERTSEC(x)
57 | #define DS1302_CONVERTDAY(x) (x)
58 | #define DS1302_CONVERTYEAR(x) (((x)&0x0f)+((((x)&0xf0)>>4) *10))
59 |
60 | #endif
--------------------------------------------------------------------------------
/src/events.c:
--------------------------------------------------------------------------------
1 | #include "events.h"
2 |
3 | XDATA u32 curr_events = 0;
4 | XDATA u8 proc_waiting_evt = 0;
5 | XDATA u32 proc_listening_list[8] = {0,0,0,0,0,0,0,0};
6 | /*
7 | Example: process P waiting on event EVT_XXX and EVT_YYY
8 | proc_waiting_evt.bit[P] = 1;
9 | proc_listening_list[P] = EVT_XXX | EVT_YYY;
10 | */
11 |
12 | void dispatch_events(u8 pid)
13 | {
14 | if(proc_waiting_evt & BIT(pid))
15 | {
16 | if(proc_listening_list[pid] & curr_events)
17 | {
18 | /*
19 | process can read this to know which of
20 | the listened events is actually occured.
21 | */
22 | proc_listening_list[pid] = curr_events;
23 | CLEARBIT(proc_waiting_evt, pid);
24 | }
25 | else if((proc_listening_list[pid] & EVT_TIMER) && (proc_sleep_countdown[pid]==0))
26 | {
27 | proc_listening_list[pid] = EVT_TIMER;
28 | CLEARBIT(proc_waiting_evt, pid);
29 | }
30 | }
31 | }
32 |
33 | void collect_btnevts()
34 | {
35 | update_button_state();
36 |
37 | if(btnstate_posedge & BTNSTATE_B1) curr_events |= EVT_BTN1_DN;
38 | if(btnstate_posedge & BTNSTATE_B2) curr_events |= EVT_BTN2_DN;
39 | if(btnstate_posedge & BTNSTATE_B3) curr_events |= EVT_BTN3_DN;
40 | if(btnstate_posedge & BTNSTATE_UP) curr_events |= EVT_NAV_U;
41 | if(btnstate_posedge & BTNSTATE_DOWN) curr_events |= EVT_NAV_D;
42 | if(btnstate_posedge & BTNSTATE_LEFT) curr_events |= EVT_NAV_L;
43 | if(btnstate_posedge & BTNSTATE_RIGHT) curr_events |= EVT_NAV_R;
44 | if(btnstate_posedge & BTNSTATE_PUSH) curr_events |= EVT_NAV_PUSH;
45 |
46 | if(btnstate_negedge & BTNSTATE_B1) curr_events |= EVT_BTN1_UP;
47 | if(btnstate_negedge & BTNSTATE_B2) curr_events |= EVT_BTN2_UP;
48 | if(btnstate_negedge & BTNSTATE_B3) curr_events |= EVT_NAV_BTN3_RESET;
49 | if(btnstate_negedge & BTNSTATE_UP) curr_events |= EVT_NAV_BTN3_RESET;
50 | if(btnstate_negedge & BTNSTATE_DOWN) curr_events |= EVT_NAV_BTN3_RESET;
51 | if(btnstate_negedge & BTNSTATE_LEFT) curr_events |= EVT_NAV_BTN3_RESET;
52 | if(btnstate_negedge & BTNSTATE_RIGHT) curr_events |= EVT_NAV_BTN3_RESET;
53 | if(btnstate_negedge & BTNSTATE_PUSH) curr_events |= EVT_NAV_BTN3_RESET;
54 | }
55 |
56 |
57 | void collect_uartevts() //VOID
58 | {
59 | if(rs485_evtstate)
60 | {
61 | rs485_evtstate = 0;
62 | curr_events |= EVT_UART2_RECV;
63 | }
64 | if(usbcom_evtstate)
65 | {
66 | usbcom_evtstate = 0;
67 | curr_events |= EVT_UART1_RECV;
68 | }
69 | }
70 |
71 |
72 | void process_events() //VOID
73 | {
74 | curr_events = 0;
75 |
76 | collect_btnevts();
77 | collect_uartevts();
78 |
79 | dispatch_events(0);
80 | dispatch_events(1);
81 | dispatch_events(2);
82 | dispatch_events(3);
83 | dispatch_events(4);
84 | dispatch_events(5);
85 | dispatch_events(6);
86 | dispatch_events(7);
87 | }
--------------------------------------------------------------------------------
/src/events.h:
--------------------------------------------------------------------------------
1 | #ifndef _EVENTS_H_
2 | #define _EVENTS_H_
3 |
4 | #include "global.h"
5 | #include "button.h"
6 | #include "bit_ops.h"
7 | #include "scheduler.h"
8 | #include "syscall.h"
9 | #include "usbcom.h"
10 | #include "rs485.h"
11 |
12 |
13 | //BUTTON EVENTS================================
14 | #define EVT_BTN1_DN 0x1
15 | #define EVT_BTN1_UP 0x2
16 |
17 | #define EVT_BTN2_DN 0x4
18 | #define EVT_BTN2_UP 0x8
19 |
20 | #define EVT_BTN3_DN 0x10
21 | #define EVT_NAV_L 0x20
22 | #define EVT_NAV_R 0x40
23 | #define EVT_NAV_U 0x80
24 | #define EVT_NAV_D 0x100
25 | #define EVT_NAV_PUSH 0x200
26 |
27 | #define EVT_NAV_BTN3_RESET 0x400
28 |
29 |
30 | //UART EVENTS==================================
31 | #define EVT_UART1_RECV 0x800
32 | #define EVT_UART2_RECV 0x1000
33 |
34 | //TIMER EVENT==================================
35 | #define EVT_TIMER 0x2000
36 |
37 | //USER EVENT===================================
38 | #define EVT_USER1 0x4000
39 | #define EVT_USER2 0x8000
40 | #define EVT_USER3 0x10000
41 | #define EVT_USER4 0x20000
42 |
43 | extern XDATA u32 curr_events;
44 | extern XDATA u8 proc_waiting_evt;
45 | extern XDATA u32 proc_listening_list[8];
46 | #define MY_EVENTS (proc_listening_list[current_process])
47 |
48 | void process_events();
49 | void dispatch_events(u8);
50 | void collect_btnevts();
51 | void collect_uartevts();
52 |
53 | #endif //_EVENTS_H_
--------------------------------------------------------------------------------
/src/global.h:
--------------------------------------------------------------------------------
1 | #ifndef _GLOBAL_H_
2 | #define _GLOBAL_H_
3 |
4 | #include "config.h"
5 |
6 | #define STC
7 |
8 | #ifndef STC
9 | #define XDATA
10 | #define IDATA
11 | #define DATA
12 | #define CODE
13 | #define INTERRUPT
14 | #define VFUNC
15 | #else
16 | #define XDATA xdata
17 | #define IDATA idata
18 | #define DATA data
19 | #define CODE code
20 | #define INTERRUPT interrupt
21 | #define VFUNC small
22 | #endif
23 |
24 |
25 | #endif //_GLOBAL_H_
--------------------------------------------------------------------------------
/src/main.c:
--------------------------------------------------------------------------------
1 | #include "global.h"
2 | #include "stack.h"
3 | #include "xstack.h"
4 | #include "scheduler.h"
5 | #include "bit_ops.h"
6 | #include "timer0_isr.h"
7 | #include "syscall.h"
8 | #include "semaphore.h"
9 | #include "events.h"
10 | #include "seg_led.h"
11 | #include "button.h"
12 | #include "usbcom.h"
13 | #include "rs485.h"
14 | #include "random.h"
15 |
16 | #define TIMESLICE_MS 1
17 | #define T12RL (65536 - MAIN_Fosc*TIMESLICE_MS/12/1000)
18 |
19 |
20 | void testproc(u16 param) large reentrant
21 | {
22 | while(1)
23 | {
24 | if((timer0_cnt>>5) & BIT(param))
25 | {
26 | SETBIT(led_display_content, param);
27 | }
28 | else
29 | {
30 | CLEARBIT(led_display_content, param);
31 | }
32 | }
33 | }
34 |
35 | void testproc2(u16 param) large reentrant
36 | {
37 | while(1)
38 | {
39 | proc_sleep(param);
40 | led_display_content = ~led_display_content;
41 | }
42 | }
43 |
44 | void testproc3(u16 param) large reentrant
45 | {
46 | while(1)
47 | {
48 | proc_sleep(param);
49 | led_display_content ^= 0x0f;
50 | }
51 | }
52 |
53 | void testproc4() large reentrant
54 | {
55 | while(1)
56 | {
57 | proc_sleep(500);
58 | sem_post(0);
59 | led_display_content |= 0x80;
60 | sem_wait(0);
61 | led_display_content &= ~0x80;
62 | }
63 | }
64 |
65 | void testproc5() large reentrant
66 | {
67 | sem_init(0,0);
68 | while(1)
69 | {
70 | sem_wait(0);
71 | led_display_content |= 0x40;
72 | proc_sleep(500);
73 | sem_post(0);
74 | led_display_content &= ~0x40;
75 | }
76 | }
77 |
78 | void testproc6(u16 param) large reentrant
79 | {
80 | while(1)
81 | {
82 | proc_wait_evts(EVT_BTN1_DN);
83 | seg_set_str("HELLO ");
84 | usbcom_write("hello \0",0);
85 | proc_wait_evts(EVT_NAV_R);
86 | seg_set_str("WORLD ");
87 | usbcom_write("world\r\n\0",0);
88 | proc_wait_evts(EVT_UART1_RECV);
89 | seg_set_str(usbcom_buf);
90 | }
91 | }
92 |
93 | void testproc7(u16 param) large reentrant
94 | {
95 | while(1)
96 | {
97 | proc_wait_evts(EVT_UART2_RECV | EVT_BTN1_DN);
98 | if(MY_EVENTS & EVT_BTN1_DN)
99 | {
100 | *((u32 *)rs485_buf) = rand32();
101 | rs485_write(rs485_buf, 4);
102 | seg_set_number(*((u32 *)rs485_buf));
103 | }
104 | else
105 | {
106 | seg_set_number(*((u32 *)rs485_buf));
107 | }
108 | }
109 | }
110 |
111 | main()
112 | {
113 | //initialize kernel stack and xstack pointer
114 | SP = kernel_stack;
115 | setxbp(kernel_xstack + KERNEL_XSTACKSIZE);
116 |
117 | //set process stacks and swap stacks owner
118 | process_stack[0][PROCESS_STACKSIZE-1] = 0;
119 | process_stack[1][PROCESS_STACKSIZE-1] = 1;
120 | process_stack[2][PROCESS_STACKSIZE-1] = 2;
121 | process_stack[3][PROCESS_STACKSIZE-1] = 3;
122 | process_stack[4][PROCESS_STACKSIZE-1] = 4;
123 | process_stack_swap[0][PROCESS_STACKSIZE-1] = 5;
124 | process_stack_swap[1][PROCESS_STACKSIZE-1] = 6;
125 | process_stack_swap[2][PROCESS_STACKSIZE-1] = 7;
126 |
127 | //initialize LED pins
128 | P0M1 &= 0x00;
129 | P0M0 |= 0xff;
130 | P2M1 &= 0xf0;
131 | P2M0 |= 0x0f;
132 | //select LED, set all off
133 | P23 = 1;
134 | P0 = 0;
135 |
136 | //initialize buttons
137 | buttons_init();
138 |
139 | //initialize serial ports
140 | usbcom_init(115200);
141 | rs485_init(115200);
142 |
143 | //start process
144 |
145 |
146 |
147 | //initialize PCA2 interrupt (as syscall interrupt)
148 | //clear CCF2
149 | CCON &= ~0x04;
150 | //disable PCA2 module and set ECCF2
151 | CCAPM2 = 1;
152 | //low priority interrupt
153 | PPCA = 0;
154 |
155 | //start main timer
156 | TR0 = 0; //stop timer
157 | TMOD &= 0xF0; //timer mode, 16b autoreload
158 | AUXR &= 0x7F; //12T mode
159 | TL0 = T12RL & 0xff; //set reload value
160 | TH0 = (T12RL & 0xff00) >> 8;
161 | ET0 = EA = 1; //set interrupt enable
162 | PT0 = 0; //set priority to low
163 | TR0 = 1; //start timer
164 |
165 | //spin
166 | while(1);
167 | }
--------------------------------------------------------------------------------
/src/random.c:
--------------------------------------------------------------------------------
1 | #include "random.h"
2 |
3 | XDATA u32 __rndseed = 0xf2e0062c;
4 |
5 | u32 rand32() large reentrant
6 | {
7 | //LCG: (aX+c)%m
8 | __rndseed = ((__rndseed * 1103515245) + 12345) & 0x7fffffff;
9 | return __rndseed;
10 | }
11 |
12 |
13 | void srand()
14 | {
15 | XDATA u8 tmp;
16 | tmp = ds1302_readbyte(DS1302_SEC);
17 | __rndseed = tmp;
18 | tmp = ds1302_readbyte(DS1302_MIN);
19 | __rndseed += tmp;
20 | tmp = ds1302_readbyte(DS1302_HR);
21 | __rndseed += tmp;
22 | }
23 |
--------------------------------------------------------------------------------
/src/random.h:
--------------------------------------------------------------------------------
1 | #ifndef _RANDOM_H_
2 | #define _RANDOM_H_
3 |
4 | #include "global.h"
5 | #include "ds1302.h"
6 |
7 | u32 rand32() large reentrant;
8 | void srand();
9 |
10 | #endif
--------------------------------------------------------------------------------
/src/rs485.c:
--------------------------------------------------------------------------------
1 | #include "rs485.h"
2 |
3 | void rs485_init(u32 baudrate)
4 | {
5 | //Set TX/DR pins (P37, P47) to Push-Pull, RX pin (P46) to input.
6 | {
7 | P4M1 &= 0x3F; // 0111 1111
8 | P4M0 |= 0xC0; // 1000 0000
9 |
10 | P3M1 &= 0x7F; // 0111 1111
11 | P3M0 |= 0x80; // 1000 0000
12 |
13 | P4M1 |= 0x40; // 0100 0000
14 | P4M0 &= 0xBF; // 1011 1111
15 | }
16 |
17 | //Configure baudrate timer
18 | {
19 | XDATA u16 reload = 65536 - ((MAIN_Fosc / 4) / baudrate); //1T
20 | AUXR &= ~(1<<4); //Timer stop
21 | AUXR &= ~(1<<3); //Timer2 set As Timer
22 | AUXR |= (1<<2); //Timer2 set as 1T mode
23 | IE2 &= ~(1<<2); //Disable interrupt
24 |
25 | TH2 = (u8)(reload>>8);
26 | TL2 = (u8)reload;
27 | AUXR |= (1<<4); //Timer run enable
28 | }
29 |
30 | //Initialize UART2 on P46 and P47
31 | {
32 | IP2 |= 1; //High priority interrupt
33 | S2CON &= ~(1<<7); //8bit mode
34 | S2CON |= (1<<4); //Enable Rx
35 | P_SW2 = (P_SW2 & ~1) | (1 & 0x01); //Select IO port P46/P47
36 | RS485_STATE = RS485_R; //Half duplex mode set to Rx
37 | IE2 |= 1; //Enable interrupt (wait for incoming data)
38 | }
39 | }
40 |
41 | //this function blocks current process until all data is sent
42 | void __rs485_write(u8* buf, u8 len)
43 | {
44 | u8 i;
45 | //Tx enable.
46 | RS485_STATE = RS485_D;
47 | //Disable UART2 interrupt (Tx uses polling mode)
48 | IE2 &= ~1;
49 |
50 | if(len)
51 | {
52 | for(i=0;i>8;
20 | process_context[pid][14] = ((u16)process_xstack[pid] + PROCESS_XSTACKSIZE)&0x00ff;
21 |
22 | //PCH, PCL
23 | process_context[pid][15] = (entry&0xff00) >> 8;
24 | process_context[pid][16] = (entry&0x00ff);
25 |
26 |
27 | //SP
28 | if(get_stack_index(pid)!=-1)
29 | process_context[pid][17] = process_stack[get_stack_index(pid)]; //stack present in memory, use absolute address
30 | else
31 | process_context[pid][17] = 0; //stack in stackswap space, use address relative to stack start
32 |
33 | //R4-R7 (param)
34 | process_context[pid][9] = (param & 0xff000000) >> 24;
35 | process_context[pid][10] = (param & 0x00ff0000) >> 16;
36 | process_context[pid][11] = (param & 0x0000ff00) >> 8;
37 | process_context[pid][12] = (param & 0x000000ff);
38 |
39 | proc_time_share[pid] = DEFAULT_TIMESLICES;
40 | process_slot |= BIT(pid);
41 | }
42 |
43 |
44 | u8 select_process()
45 | {
46 | XDATA u8 tmp_process;
47 |
48 | //current_process can be 8 (kernel startup) or 9 (idle spin)
49 | //so we have to set current_process to 0 in that situation.
50 | if(current_process >= 8) current_process = 0;
51 | tmp_process = current_process;
52 |
53 |
54 | //sequentially check other processes
55 | while((tmp_process = NEXT(tmp_process)) != current_process)
56 | if(process_ready(tmp_process))
57 | goto SCHEDULER_END;
58 |
59 | //if no other process can run, check if current process can run again
60 | if (process_ready(current_process))
61 | {
62 | tmp_process = current_process;
63 | goto SCHEDULER_END;
64 | }
65 |
66 | //Can't find a process to run, reuturn 9(invalid)
67 | //ISR should recognize this and put system to spin until next interrupt
68 | tmp_process = 9;
69 |
70 | SCHEDULER_END:;
71 | return tmp_process;
72 | }
73 |
74 | u8 process_ready(u8 pid)
75 | {
76 | //Check process exists
77 | if(!PROC_EXISTS(pid))
78 | return 0;
79 |
80 | //Check process is not waiting for semaphore
81 | if(proc_waiting_sem & BIT(pid))
82 | return 0;
83 |
84 | //Check process is not sleeping or waitiong for events
85 | if(proc_waiting_evt & BIT(pid))
86 | return 0;
87 |
88 | return 1;
89 | }
90 |
91 | //ONLY CALL THIS FUNCTION ATOMICALLY IN ISR!!!
92 | void reschedule()
93 | {
94 | //kernel or spin context doesn't need to be saved
95 | if(current_process < 8)
96 | save_current_context();
97 |
98 | //select a process to run
99 | current_process = select_process();
100 | if(current_process == 9) goto IDLE_SPIN;
101 |
102 | //allocate timeslices and load context
103 | remaining_timeslices = proc_time_share[current_process];
104 | if(get_stack_index(current_process) == -1)
105 | stackswap(get_stackswap_index(current_process));
106 | //do stack swap.
107 | load_current_context();
108 | return;
109 |
110 | IDLE_SPIN:;
111 | //load address of spin() into interrupt context.
112 | //allocate 1 timeslice to it.
113 | interrupt_context[15] = HIGH16((u16)spin);
114 | interrupt_context[16] = LOW16((u16)spin);
115 | remaining_timeslices = 1;
116 | return;
117 | }
118 |
119 | void decrement_sleep_counters()
120 | {
121 | COUNTDOWN(proc_sleep_countdown[0], interrupt_counter);
122 | COUNTDOWN(proc_sleep_countdown[1], interrupt_counter);
123 | COUNTDOWN(proc_sleep_countdown[2], interrupt_counter);
124 | COUNTDOWN(proc_sleep_countdown[3], interrupt_counter);
125 | COUNTDOWN(proc_sleep_countdown[4], interrupt_counter);
126 | COUNTDOWN(proc_sleep_countdown[5], interrupt_counter);
127 | COUNTDOWN(proc_sleep_countdown[6], interrupt_counter);
128 | COUNTDOWN(proc_sleep_countdown[7], interrupt_counter);
129 | }
130 |
131 |
132 |
133 |
--------------------------------------------------------------------------------
/src/scheduler.h:
--------------------------------------------------------------------------------
1 | #ifndef _SCHEDULER_H_
2 | #define _SCHEDULER_H_
3 |
4 | #include "global.h"
5 | #include "timer0_isr.h"
6 | #include "xstack.h"
7 | #include "stack.h"
8 | #include "bit_ops.h"
9 | #include "spin.h"
10 | #include "semaphore.h"
11 | #include "events.h"
12 | /*
13 |
14 | #include "mem.h"
15 | #include "vstack.h"
16 |
17 | #include "semaphore.h"
18 | #include "spin.h"
19 | */
20 |
21 | #define DEFAULT_TIMESLICES 3
22 | #define NEXT(x) (((x)+1) & 0x7)
23 | #define PROC_EXISTS(x) ((process_slot & BIT(x))>0)
24 |
25 |
26 | extern XDATA u8 process_context[8][18];
27 |
28 | extern XDATA u8 current_process;
29 | extern DATA u32 timer0_cnt;
30 | extern XDATA u8 process_slot;
31 |
32 | extern XDATA u8 remaining_timeslices;
33 | extern XDATA u8 proc_time_share[8];
34 |
35 | #define COUNTDOWN(from, cnt) {if((from)>=(cnt)) (from)-=(cnt); else (from)=0;}
36 | extern XDATA u16 proc_sleep_countdown[8];
37 |
38 | /*
39 | PUSH32 arg32
40 | */
41 | void start_process(u16 entry, u16 pid, u32 param);
42 | u8 select_process();
43 | u8 process_ready(u8 pid);
44 | void decrement_sleep_counters();
45 | void reschedule();
46 |
47 |
48 | /*
49 | This variable MUST be in DATA memory, because write or read to this
50 | variable must be done atomically (single instruction), otherwise
51 | rescheduel may happen during data access.
52 |
53 | When set to 1, no rescheduling is performed in ISR, but system time
54 | counter is incremented.
55 | */
56 | extern DATA u8 flag_nosched;
57 | #define ATOMIC_START() {flag_nosched = 1;}
58 | #define ATOMIC_END() {flag_nosched = 0;}
59 | #define ATOMIC(atomic_code)\
60 | {\
61 | flag_nosched = 1;\
62 | {atomic_code;}\
63 | flag_nosched = 0;\
64 | }
65 |
66 | #define NOINT_ATOMIC_START(){TR0 = 0;}
67 | #define NOINT_ATOMIC_END(){TR0 = 1;}
68 | #define NOINT_ATOMIC(atomic_code)\
69 | {\
70 | TR0 = 0;\
71 | {atomic_code;}\
72 | TR0 = 1;\
73 | }
74 |
75 |
76 | #endif
--------------------------------------------------------------------------------
/src/seg_led.c:
--------------------------------------------------------------------------------
1 | #include "seg_led.h"
2 |
3 | XDATA u8 seg_display_content[8] = {0,0,0,0,0,0,0,0};
4 | XDATA u8 led_display_content = 0;
5 | XDATA u8 seg_led_current = 0;
6 |
7 | CODE u8 seg_decoder[128] ={
8 | 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, 0x77,0x7c,0x39,0x5e,0x79,0x71, //hex 0~F
9 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
10 |
11 | 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, //space and others
12 | 0x3f, 0x06, 0x5b, 0x4f, 0x66, 0x6d, 0x7d, 0x07, 0x7f, 0x6f, //numbers
13 | 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, //others
14 | 0x77,0x7c,0x39,0x5e,0x79,0x71,0x3d,0x76,0x0f,0x0e,0x75,0x38,0x37,0x54,0x5c,0x73,0x67,0x31,0x6d/*s:0x49, 5:0x6d*/,0x78,0x3e,0x1c,0x7e,0x64,0x6e,0x59, //A-Z
15 | 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, //others
16 | 0x77,0x7c,0x39,0x5e,0x79,0x71,0x3d,0x76,0x0f,0x0e,0x75,0x38,0x37,0x54,0x5c,0x73,0x67,0x31,0x6d/*s:0x49, 5:0x6d*/,0x78,0x3e,0x1c,0x7e,0x64,0x6e,0x59, //a-z
17 | 0x80, 0x80, 0x80, 0x80, 0x80 //others
18 | };
19 |
20 | void seg_set_str(char* str) large reentrant
21 | {
22 | seg_display_content[0] = seg_decoder[str[0]];
23 | seg_display_content[1] = seg_decoder[str[1]];
24 | seg_display_content[2] = seg_decoder[str[2]];
25 | seg_display_content[3] = seg_decoder[str[3]];
26 | seg_display_content[4] = seg_decoder[str[4]];
27 | seg_display_content[5] = seg_decoder[str[5]];
28 | seg_display_content[6] = seg_decoder[str[6]];
29 | seg_display_content[7] = seg_decoder[str[7]];
30 | }
31 |
32 | void seg_set_number(u32 n) large reentrant
33 | {
34 | seg_display_content[7] = seg_decoder[n%10]; n/=10;
35 | seg_display_content[6] = seg_decoder[n%10]; n/=10;
36 | seg_display_content[5] = seg_decoder[n%10]; n/=10;
37 | seg_display_content[4] = seg_decoder[n%10]; n/=10;
38 | seg_display_content[3] = seg_decoder[n%10]; n/=10;
39 | seg_display_content[2] = seg_decoder[n%10]; n/=10;
40 | seg_display_content[1] = seg_decoder[n%10]; n/=10;
41 | seg_display_content[0] = seg_decoder[n%10]; n/=10;
42 | }
43 |
44 | //this function should be called in system timer ISR
45 | //no reentrancy is supported
46 | void seg_led_scan_next()
47 | {
48 | switch(seg_led_current)
49 | {
50 | case 0: DISP_SEG(0) seg_led_current++; break;
51 | case 1: DISP_SEG(1) seg_led_current++; break;
52 | case 2: DISP_SEG(2) seg_led_current++; break;
53 | case 3: DISP_SEG(3) seg_led_current++; break;
54 | case 4: DISP_SEG(4) seg_led_current++; break;
55 | case 5: DISP_SEG(5) seg_led_current++; break;
56 | case 6: DISP_SEG(6) seg_led_current++; break;
57 | case 7: DISP_SEG(7) seg_led_current++; break;
58 | case 8: DISP_LED() seg_led_current=0; break;
59 | default: seg_led_current = 0;
60 | }
61 | }
--------------------------------------------------------------------------------
/src/seg_led.h:
--------------------------------------------------------------------------------
1 | #ifndef _SEG_LED_H_
2 | #define _SEG_LED_H_
3 |
4 | #include "global.h"
5 |
6 | //LED Pins:
7 | #define LED0 P00
8 | #define LED1 P01
9 | #define LED2 P02
10 | #define LED3 P03
11 | #define LED4 P04
12 | #define LED5 P05
13 | #define LED6 P06
14 | #define LED7 P07
15 | #define LEDs P0
16 |
17 | //Segment Selection Pins:
18 | #define SEGA P00
19 | #define SEGB P01
20 | #define SEGC P02
21 | #define SEGD P03
22 | #define SEGE P04
23 | #define SEGF P05
24 | #define SEGG P06
25 | #define SEGH P07
26 | #define SEGs P0
27 |
28 | //Digit Selection Pins:
29 | #define SEG_DIGIT_SEL0 P20
30 | #define SEG_DIGIT_SEL1 P21
31 | #define SEG_DIGIT_SEL2 P22
32 |
33 | /*
34 | Board Tracing:
35 | P23 -> NOT -> EN_138_Decoder -> Segments
36 | `--> VDD_LEDs
37 | */
38 |
39 | #define LED_SEG_SWITCH P23 // USE_LED or USE_SEG
40 | #define USE_LED 1
41 | #define USE_SEG 0
42 |
43 | //set all related pins to Push-Pull mode (P0, P20-P23)
44 | #define seg_led_init()\
45 | {\
46 | P0M1 &= 0x00;\
47 | P0M0 |= 0xff;\
48 | P2M1 &= 0xf0;\
49 | P2M0 |= 0x0f;\
50 | }
51 |
52 | #define seg_digit_sel(x)\
53 | {\
54 | SEG_DIGIT_SEL0 = x&1;\
55 | SEG_DIGIT_SEL1 = (x&2) > 0;\
56 | SEG_DIGIT_SEL2 = (x&4) > 0;\
57 | }
58 |
59 | #define DISP_SEG(x)\
60 | {\
61 | SEGs = seg_display_content[x];\
62 | seg_digit_sel(x);\
63 | LED_SEG_SWITCH = USE_SEG;\
64 | }
65 |
66 | #define DISP_LED()\
67 | {\
68 | LEDs = led_display_content;\
69 | LED_SEG_SWITCH = USE_LED;\
70 | }
71 |
72 | extern XDATA u8 seg_display_content[8];
73 | extern XDATA u8 led_display_content;
74 | extern CODE u8 seg_decoder[128];
75 | extern XDATA u8 seg_led_current;
76 |
77 | //VPUSH void* str
78 | void seg_set_str(char* str) large reentrant;
79 | void seg_set_number(u32 n) large reentrant;
80 | void seg_led_scan_next();
81 |
82 | #endif
--------------------------------------------------------------------------------
/src/semaphore.c:
--------------------------------------------------------------------------------
1 | #include "semaphore.h"
2 |
3 |
4 | XDATA char semaphores[MAX_SEMAPHORES];
5 | XDATA u8 proc_sem_wait_flag[MAX_SEMAPHORES];
6 | XDATA u8 sem_wake_round[MAX_SEMAPHORES];
7 | XDATA u8 proc_waiting_sem = 0;
8 |
9 | void __sem_init(u8 sem_id, char val)
10 | {
11 | proc_sem_wait_flag[sem_id] = 0;
12 | sem_wake_round[sem_id] = 1;
13 | semaphores[sem_id] = val;
14 | }
15 |
16 | void __sem_post(u8 sem_id)
17 | {
18 | XDATA u8 select_wake;
19 |
20 | //No process is waiting, only increment semaphore
21 | if(!proc_sem_wait_flag[sem_id])
22 | {
23 | semaphores[sem_id]++;
24 | return;
25 | }
26 |
27 | //Find first process waiting on the semaphore
28 | select_wake = RSL(sem_wake_round[sem_id]);
29 | while ((select_wake & proc_sem_wait_flag[sem_id]) == 0)
30 | select_wake = RSL(select_wake);
31 |
32 | //Remove the waiting flag of the process
33 | proc_sem_wait_flag[sem_id] &= ~select_wake;
34 | proc_waiting_sem &= ~select_wake;
35 |
36 | //Record the last waked process
37 | sem_wake_round[sem_id] = select_wake;
38 | }
39 |
40 | u8 __sem_wait(u8 sem_id)
41 | {
42 | //semaphore currently idle, decrement value and return.
43 | if(semaphores[sem_id])
44 | {
45 | semaphores[sem_id] --;
46 | return 1;
47 | }
48 |
49 | /*
50 | set current process waiting on semaphore, yield
51 | (and the process won't be selected by scheduler
52 | until wait flag is cleared by some sem_post)
53 | */
54 | proc_sem_wait_flag[sem_id] |= BIT(current_process);
55 | proc_waiting_sem |= BIT(current_process);
56 |
57 | return 0; //returning 0 means a reschedule should be done.
58 | }
59 |
--------------------------------------------------------------------------------
/src/semaphore.h:
--------------------------------------------------------------------------------
1 | #ifndef _SEMAPHORE_H_
2 | #define _SEMAPHORE_H_
3 |
4 | #include "global.h"
5 | #include "bit_ops.h"
6 | #include "scheduler.h"
7 |
8 | #define MAX_SEMAPHORES 8
9 |
10 | extern XDATA char semaphores[MAX_SEMAPHORES];
11 | extern XDATA u8 proc_sem_wait_flag[MAX_SEMAPHORES];
12 | extern XDATA u8 sem_wake_round[MAX_SEMAPHORES];
13 | extern XDATA u8 proc_waiting_sem;
14 | /*
15 | If process P is waiting for semaphore SEM,
16 | then bit P of proc_sem_wait_flag[SEM] is set,
17 | and
18 |
19 | If process P is the last process that has
20 | been waked by semaphore SEM, then bit P of
21 | sem_wake_round[SEM] is set.
22 |
23 | When a semaphore is waking up a process, it
24 | will find the first process waiting for it,
25 | starting from the [pid last waked]+1.
26 |
27 | For example, when SEM1 waked up PROC3 last time,
28 | it will find a process to wake up from PROC4,5,6,...
29 | This behaviour can prevent starving some process.
30 | */
31 |
32 | void __sem_init(u8 sem_id, char val);
33 | void __sem_post(u8 sem_id);
34 | u8 __sem_wait(u8 sem_id);
35 |
36 | #endif
--------------------------------------------------------------------------------
/src/spin.c:
--------------------------------------------------------------------------------
1 | #include "spin.h"
2 |
3 | void spin()
4 | {
5 | while(1)
6 | {
7 | }
8 | }
9 |
--------------------------------------------------------------------------------
/src/spin.h:
--------------------------------------------------------------------------------
1 | #ifndef _SPIN_H_
2 | #define _SPIN_H_
3 | #include "global.h"
4 | void spin();
5 |
6 | #endif
--------------------------------------------------------------------------------
/src/stack.c:
--------------------------------------------------------------------------------
1 | #include "stack.h"
2 |
3 | IDATA u8 kernel_stack[KERNEL_STACKSIZE];
4 | IDATA u8 process_stack[5][PROCESS_STACKSIZE];
5 | XDATA u8 process_stack_swap[3][PROCESS_STACKSIZE];
6 |
7 | /*
8 | OS allows 8 processes maximum, but there are only
9 | 5 process stacks allowed in memory due to size
10 | limitations.
11 |
12 | the process stacks can be swapped out to xdata
13 | swap area if there are more than 5 processes at
14 | the same time.
15 | */
16 |
17 | char get_stack_index(u8 pid)
18 | {
19 | XDATA u8 i;
20 | for(i=0;i<5;i++)
21 | if(process_stack[i][PROCESS_STACKSIZE-1] == pid)
22 | return i;
23 |
24 | return -1;
25 | }
26 |
27 | char get_stackswap_index(u8 pid)
28 | {
29 | XDATA u8 i;
30 | for(i=0;i<3;i++)
31 | if(process_stack_swap[i][PROCESS_STACKSIZE-1] == pid)
32 | return i;
33 |
34 | return -1;
35 | }
36 |
37 |
38 | extern XDATA u8 process_context[8][18];
39 | extern XDATA u8 process_slot;
40 | void stackswap(u8 swap_index)
41 | {
42 | XDATA u8 i, temp, physical_index;
43 |
44 | //first try to find a stack slot that's not being used
45 | physical_index = 0xff;
46 | for(i=0;i<5;i++)
47 | {
48 | if(process_slot & BIT(process_stack[i][PROCESS_STACKSIZE-1]) == 0)
49 | {
50 | physical_index = i;
51 | break;
52 | }
53 | }
54 |
55 | //if there's no free stack slot, select random victim
56 | physical_index = rand32()%5;
57 |
58 | for(i=0; i syscall
85 | if(CCON & 4)
86 | {
87 | CCON &= ~4;
88 | syscall_c();
89 | }
90 | else
91 | {
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/src/timer0_isr.a51:
--------------------------------------------------------------------------------
1 | #include "stc15fxxxx.inc"
2 | #include "xstack.inc"
3 | #include "stack.inc"
4 |
5 | EXTERN DATA (INTERRUPT_COUNTER, FLAG_NOSCHED, INTERRUPT_CONTEXT)
6 |
7 | SEG_TIMER0_ISR_ENTRY SEGMENT CODE AT 000Bh
8 | RSEG SEG_TIMER0_ISR_ENTRY
9 | LJMP TIMER0_ISR
10 |
11 | SEG_TIMER0_ISR SEGMENT CODE
12 | RSEG SEG_TIMER0_ISR
13 | TIMER0_ISR:
14 | INC INTERRUPT_COUNTER
15 | XCH A, FLAG_NOSCHED
16 | JNZ T0ISR_SKIP
17 | XCH A, FLAG_NOSCHED
18 | ;SAVE CURRENT STATE
19 | MOV INTERRUPT_CONTEXT, DPH
20 | MOV INTERRUPT_CONTEXT+1, DPL
21 | MOV INTERRUPT_CONTEXT+2, A
22 | MOV INTERRUPT_CONTEXT+3, B
23 | MOV INTERRUPT_CONTEXT+4, PSW
24 | MOV INTERRUPT_CONTEXT+5, R0
25 | MOV INTERRUPT_CONTEXT+6, R1
26 | MOV INTERRUPT_CONTEXT+7, R2
27 | MOV INTERRUPT_CONTEXT+8, R3
28 | MOV INTERRUPT_CONTEXT+9, R4
29 | MOV INTERRUPT_CONTEXT+10, R5
30 | MOV INTERRUPT_CONTEXT+11, R6
31 | MOV INTERRUPT_CONTEXT+12, R7
32 | MOV INTERRUPT_CONTEXT+13, ?C_XBP
33 | MOV INTERRUPT_CONTEXT+14, ?C_XBP + 1
34 |
35 | POP INTERRUPT_CONTEXT+15
36 | POP INTERRUPT_CONTEXT+16
37 | MOV INTERRUPT_CONTEXT+17, SP
38 | ;STATE SAVED
39 |
40 | ;START TO MOVE TO KERNEL CONTEXT
41 | ;Kernel uses it's own stack and xstack
42 | MOV SP, #KERNEL_STACK
43 | MOV ?C_XBP , #HIGH (KERNEL_STACK + KERNEL_XSTACKSIZE)
44 | MOV ?C_XBP + 1 , #LOW (KERNEL_STACK + KERNEL_XSTACKSIZE)
45 |
46 | EXTERN CODE (TIMER0_ISR_C)
47 | CALL TIMER0_ISR_C
48 | ;Kernel processing end.
49 |
50 | ;Load process state.
51 | MOV SP, INTERRUPT_CONTEXT+17
52 | PUSH INTERRUPT_CONTEXT+16
53 | PUSH INTERRUPT_CONTEXT+15
54 |
55 | MOV DPH, INTERRUPT_CONTEXT
56 | MOV DPL, INTERRUPT_CONTEXT+1
57 | MOV A, INTERRUPT_CONTEXT+2
58 | MOV B, INTERRUPT_CONTEXT+3
59 | MOV PSW, INTERRUPT_CONTEXT+4
60 | MOV R0, INTERRUPT_CONTEXT+5
61 | MOV R1, INTERRUPT_CONTEXT+6
62 | MOV R2, INTERRUPT_CONTEXT+7
63 | MOV R3, INTERRUPT_CONTEXT+8
64 | MOV R4, INTERRUPT_CONTEXT+9
65 | MOV R5, INTERRUPT_CONTEXT+10
66 | MOV R6, INTERRUPT_CONTEXT+11
67 | MOV R7, INTERRUPT_CONTEXT+12
68 | MOV ?C_XBP, INTERRUPT_CONTEXT+13
69 | MOV ?C_XBP + 1, INTERRUPT_CONTEXT+14
70 | RETI
71 |
72 | T0ISR_SKIP:
73 | XCH A, FLAG_NOSCHED
74 | RETI
75 |
76 | END
77 |
78 |
--------------------------------------------------------------------------------
/src/timer0_isr.h:
--------------------------------------------------------------------------------
1 | #ifndef _TIMER0_ISR_H_
2 | #define _TIMER0_ISR_H_
3 |
4 | #include "global.h"
5 | #include "scheduler.h"
6 | #include "spin.h"
7 | #include "seg_led.h"
8 | /*
9 | #include "vstack.h"
10 | #include "bit_ops.h"
11 | #include "events.h"
12 | */
13 |
14 | extern DATA u32 timer0_cnt;
15 | extern DATA u8 interrupt_counter;
16 | extern DATA u8 interrupt_context[18];
17 |
18 | void timer0_isr_c();
19 | void save_current_context();
20 | void load_current_context();
21 |
22 | #endif
--------------------------------------------------------------------------------
/src/timer0_isr_c.c:
--------------------------------------------------------------------------------
1 | #include "timer0_isr.h"
2 |
3 | DATA u32 timer0_cnt = 0;
4 | DATA u8 interrupt_counter = 0;
5 | DATA u8 interrupt_context[18];
6 |
7 |
8 | void save_current_context()
9 | {
10 | XDATA u8 i;
11 | for(i=0;i<18;i++)
12 | process_context[current_process][i] = interrupt_context[i];
13 | }
14 |
15 | void load_current_context()
16 | {
17 | XDATA u8 i;
18 | for(i=0;i<18;i++)
19 | interrupt_context[i] = process_context[current_process][i];
20 | }
21 |
22 | void timer0_isr_c()
23 | {
24 | //increment system time, and update all counters
25 | timer0_cnt += interrupt_counter;
26 | COUNTDOWN(remaining_timeslices, interrupt_counter);
27 | decrement_sleep_counters();
28 | interrupt_counter = 0;
29 |
30 | //Update display
31 | seg_led_scan_next();
32 |
33 | //Process events
34 | process_events();
35 |
36 | /*
37 | Timer0 and Syscall interrupt at the same CPU cycle.
38 | If a task switch is done, current_process is modified,
39 | syscall won't be able to determine the correct process
40 | calling it.
41 | */
42 | if (CCON&4)
43 | goto SKIPSCHED;
44 | if(remaining_timeslices > 0)
45 | goto SKIPSCHED;
46 |
47 | reschedule();
48 |
49 | SKIPSCHED:
50 | return;
51 | }
52 |
--------------------------------------------------------------------------------
/src/usbcom.c:
--------------------------------------------------------------------------------
1 | #include "usbcom.h"
2 |
3 |
4 | void usbcom_init(u32 baudrate)
5 | {
6 | XDATA u16 reload;
7 |
8 | //Set TXD(P31) to Push-Pull RXD(P30) to HiZ
9 | {
10 | CLEARBIT(P3M1, 1);
11 | SETBIT(P3M0, 1);
12 |
13 | SETBIT(P3M1, 0);
14 | CLEARBIT(P3M0, 0);
15 | }
16 |
17 | //Configure baudrate timer
18 | {
19 | reload = 65536 - (MAIN_Fosc / 4) / baudrate;
20 |
21 | AUXR |= 0x01; //S1 BRT Use Timer2;
22 | AUXR &= ~(1<<4); //Timer stop
23 | AUXR &= ~(1<<3); //Timer2 set As Timer
24 | AUXR |= (1<<2); //Timer2 set as 1T mode
25 | IE2 &= ~(1<<2); //Disable interrup
26 |
27 | TH2 = (u8)(reload>>8);
28 | TL2 = (u8)reload;
29 | AUXR |= (1<<4); //Timer run enable
30 | }
31 |
32 | //Initialize UART1 on P30 and P31
33 | {
34 | PS = 1; //High priority interrupt
35 | SCON = (SCON & 0x3f) | (1<<6); //8bit mode
36 | REN = 1; //Enable Rx
37 | P_SW1 = (P_SW1 & 0x3f) | (0 & 0xc0); //Select IO port P30/P31
38 | ES = 1; //Enable interrupt (wait for incoming data)
39 | }
40 | }
41 |
42 |
43 | //this function blocks current process until all data is sent
44 | //not a VFUNC because there's no reentrancy support
45 | void __usbcom_write(u8* buf, u8 len) small
46 | {
47 | u8 i;
48 |
49 | //Disable interrupt (Tx uses polling mode)
50 | ES = 0;
51 |
52 | //length is set
53 | if(len)
54 | {
55 | for(i=0;i