├── .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