4 #define TIMED_ACCESS(sfr,value) { TA=0xaa; TA=0x55; sfr=value; }
6 unsigned char _sdcc_external_startup(void)
8 IE=0; // disable ALL interrupts
10 // use A19..16 and !CE3..0, no CAN
11 TIMED_ACCESS(P4CNT,0x3f);
13 // use !PCE3..0, serial 1 at P5.2/3
14 TIMED_ACCESS(P5CNT,0x27);
19 // watchdog set to 9.1 seconds
22 // default stretch cycles for MOVX
23 CKCON = (CKCON&0xf8)|(CPU_MOVX_STRETCH&0x07);
25 // use internal 4k RAM as data(stack) memory at 0x400000 and
26 // move CANx memory access to 0x401000 and upwards
27 // use !CE* for program and/or data memory access
28 TIMED_ACCESS(MCON,0xaf);
30 // select default cpu speed
34 ; save the 24-bit return address
40 mov _ESP,#0x00; reinitialize the stack
43 mov _TA,#0xaa; timed access
45 mov _ACON,#0x06; 24 bit addresses, 10 bit stack at 0x400000
47 ; restore the 24-bit return address
53 // Copy the Interrupt Vector Table (128 bytes) from 0x10000 to 0x100000
54 // This isn't needed for older bootloaders than the 0515, but it won't harm
62 mov dps,#0x00 ; make sure no autoincrement in progress
63 mov dptr,#0x10000 ; from
64 inc dps ; switch to alternate dptr
65 mov dptr,#0x100000 ; to
75 djnz b,_Startup390CopyIVT
85 // global interrupt enable, all masks cleared
86 // let the Gods be with us :)
89 Serial0Init(SERIAL_0_BAUD,1);
90 //Serial1Init(SERIAL_1_BAUD,1);
95 // signal _sdcc_gsinit_startup to initialize data (call _sdcc_init_data)
99 /* Set the cpu speed in clocks per machine cycle, valid values are:
100 1024: Power management mode
102 2: Use frequency multiplier (2x)
103 1: Use frequency multiplier (4x) (Don't do this on a TINI at 18.432MHz)
105 TODO: TINI seems to support only 2 and 4: write only bits in PMR ?
108 unsigned int cpuSpeed;
110 void CpuSpeed(unsigned int speed) {
112 while (0 && (EXIF&0x04))
113 ; // cpu operates from ring buffer
114 PMR = 0x80; // div4, CTM off, multiplier 2x
118 PMR=0x88; // div4, CTM off, multiplier 4x
119 PMR=0x98; // div4, CTM on, multiplier 4x
120 while ((EXIF&0x08)==0) {
121 ; // wait for the multiplier to be ready
123 PMR = 0x18; // use multiplier
127 PMR=0x90; // div4, CTM on, multilier 2x
128 while ((EXIF&0x08)==0) {
129 ; // wait for the multiplier to be ready
131 PMR = 0x10; // use multiplier
139 PMR = 0xc0; // div1024, CTM off
145 // now the serial0 stuff
147 // just to make the code more readable
148 #define S0RBS SERIAL_0_RECEIVE_BUFFER_SIZE
150 // this is a ring buffer and can overflow at anytime!
151 static volatile unsigned char receive0Buffer[S0RBS];
152 static volatile int receive0BufferHead=0;
153 static volatile int receive0BufferTail=0;
154 // no buffering for transmit
155 static volatile char transmit0IsBusy=0;
157 static data unsigned char serial0Buffered;
159 /* Initialize serial0.
161 Available baudrates are from 110 upto 115200 (using 16-bit timer 2)
162 If baud==0, the port is disabled.
164 If buffered!=0, characters received are buffered using an interrupt
167 void Serial0Init (unsigned long baud, unsigned char buffered) {
170 ES0=0; // disable interrupts
171 SCON0 &= 0xef; // disable receiver
175 ES0 = 0; // disable serial channel 0 interrupt
176 TR2 = 0; // stop timer 2
178 // set 8 bit uart with variable baud from timer 1/2
179 // enable receiver and clear RI and TI
182 PCON |= 0x80; // clock is 16x bitrate
183 CKCON|=0x20; // timer uses xtal/4
185 T2MOD=0; // no fancy functions
186 T2CON=0x34; // start timer as a baudrate generator for serial0
191 serial0Buffered=buffered;
194 RI_0=TI_0=0; // clear "pending" interrupts
195 ES0 = 1; // enable serial channel 0 interrupt
197 RI_0=0; // receive buffer empty
198 TI_0=1; // transmit buffer empty
202 void Serial0Baud(unsigned long baud) {
204 baud=-((long)OSCILLATOR/(32*baud));
207 TF2=0; // clear overflow flag
208 TR2=1; // start timer
211 void Serial0IrqHandler (void) interrupt 4 {
213 receive0Buffer[receive0BufferHead]=SBUF0;
214 receive0BufferHead=(receive0BufferHead+1)&(S0RBS-1);
215 if (receive0BufferHead==receive0BufferTail) {
216 /* buffer overrun, sorry :) */
217 receive0BufferTail=(receive0BufferTail+1)&(S0RBS-1);
227 char Serial0CharArrived(void) {
228 if (serial0Buffered) {
229 if (receive0BufferHead!=receive0BufferTail)
230 return receive0Buffer[receive0BufferTail];
238 void Serial0PutChar (char c)
240 if (serial0Buffered) {
241 while (transmit0IsBusy)
253 char Serial0GetChar (void)
256 if (serial0Buffered) {
257 while (receive0BufferHead==receive0BufferTail)
259 c=receive0Buffer[receive0BufferTail];
260 ES0=0; // disable serial interrupts
261 receive0BufferTail=(receive0BufferTail+1)&(S0RBS-1);
262 ES0=1; // enable serial interrupts
272 void Serial0SendBreak() {
274 ClockMilliSecondsDelay(2);
278 void Serial0Flush() {
279 ES0=0; // disable interrupts
280 receive0BufferHead=receive0BufferTail=0;
282 if (serial0Buffered) {
284 ES0=1; // enable interrupts
290 /* now let's go for the serial1 stuff, basically it's a replicate of
291 serial0 except it uses timer 1
294 // just to make the code more readable
295 #define S1RBS SERIAL_1_RECEIVE_BUFFER_SIZE
297 // this is a ring buffer and can overflow at anytime!
298 static volatile unsigned char receive1Buffer[S1RBS];
299 static volatile int receive1BufferHead=0;
300 static volatile int receive1BufferTail=0;
301 // no buffering for transmit
302 static volatile char transmit1IsBusy=0;
304 static data unsigned char serial1Buffered;
306 /* Initialize serial1.
308 Available baudrates are from 4800 upto 115200 (using 8-bit timer 1)
309 If baud==0, the port is disabled.
311 If buffered!=0, characters received are buffered using an interrupt
314 void Serial1Init (unsigned long baud, unsigned char buffered) {
317 ES1=0; // disable interrupt
318 SCON1 &= 0xef; // disable receiver
321 ES1 = 0; // disable channel 1 interrupt
322 TR1 = 0; // stop timer 1
324 // set 8 bit uart with variable baud from timer 1
325 // enable receiver and clear RI and TI
328 WDCON |= 0x80; // clock is 16x bitrate
329 CKCON|=0x10; // timer uses xtal/4
331 TMOD = (TMOD&0x0f) | 0x20; // timer 1 is an 8bit auto-reload counter
336 serial0Buffered=buffered;
339 RI_1=TI_1=0; // clear "pending" interrupts
340 ES1 = 1; // enable serial channel 1 interrupt
342 RI_1=0; // receive buffer empty
343 TI_1=1; // transmit buffer empty
347 void Serial1Baud(unsigned long baud) {
349 baud=-((long)OSCILLATOR/(32*baud));
351 TF1=0; // clear overflow flag
352 TR1=1; // start timer
355 void Serial1IrqHandler (void) interrupt 7 {
357 receive1Buffer[receive1BufferHead]=SBUF1;
358 receive1BufferHead=(receive1BufferHead+1)&(S1RBS-1);
359 if (receive1BufferHead==receive1BufferTail) /* buffer overrun, sorry :) */
360 receive1BufferTail=(receive1BufferTail+1)&(S1RBS-1);
369 char Serial1CharArrived(void) {
370 if (serial1Buffered) {
371 if (receive1BufferHead!=receive1BufferTail)
372 return receive1Buffer[receive1BufferTail];
380 void Serial1PutChar (char c)
382 if (serial1Buffered) {
383 while (transmit1IsBusy)
395 char Serial1GetChar (void)
398 if (serial1Buffered) {
399 while (receive1BufferHead==receive1BufferTail)
401 c=receive1Buffer[receive1BufferTail];
402 ES1=0; // disable serial interrupts
403 receive1BufferTail=(receive1BufferTail+1)&(S1RBS-1);
404 ES1=1; // enable serial interrupts
414 void Serial1SendBreak() {
416 ClockMilliSecondsDelay(2);
420 void Serial1Flush() {
421 ES1=0; // disable interrupts
422 receive1BufferHead=receive1BufferTail=0;
424 if (serial1Buffered) {
426 ES1=1; // enable interrupts
432 // now let's go for the clock stuff
434 //#define TIMER_0_RELOAD_VALUE 18432000L/2/1000 // appr. 1ms
436 static data unsigned long milliSeconds=0;
437 static data unsigned int timer0ReloadValue;
440 unsigned long timerReloadValue=OSCILLATOR/1000;
443 case 4: timerReloadValue/=4; break;
444 case 1: // not tested yet
445 case 2: // not tested yet
446 default: timerReloadValue/=2; break;
448 timer0ReloadValue=timerReloadValue;
449 // initialise timer 0
450 ET0=0; // disable timer interrupts initially
451 TCON = (TCON&0xcc)|0x00; // stop timer, clear overflow
452 TMOD = (TMOD&0xf0)|0x01; // 16 bit counter
453 CKCON|=0x80; // timer uses xtal/4
455 TL0=~(timer0ReloadValue&0xff);
456 TH0=~(timer0ReloadValue>>8);
458 ET0=1; // enable timer interrupts
459 TR0=1; // start timer
462 void ClockIrqHandler (void) interrupt 1 {
463 // we have lost some time here
464 TL0=~(timer0ReloadValue&0xff);
465 TH0=~(timer0ReloadValue>>8);
467 // that's all for now :)
470 // we can't just use milliSeconds
471 unsigned long ClockTicks(void) {
479 void ClockMilliSecondsDelay(unsigned long delay) {
480 long ms=ClockTicks()+delay;
482 while (ms>ClockTicks())
486 // stolen from Kevin Vigor, works only for TINI at default speed
487 void ClockMicroSecondsDelay(unsigned int delay) {
488 delay; /* shut compiler up. */
492 ; delay is in dpl/dph
497 orl a, r1 ; quick out for zero case.
501 cjne r0, #0, _usDelayLoop
512 djnz r0, _usDelayLoop ; 3 cycles x 1 = 3 cycles
514 ; we want 9.216, but more is better
516 djnz r1, _usDelayLoop