]> cloudbase.mooo.com Git - z180-stamp.git/blame - stm32/z180-stamp-stm32.c
Card detect over cs pin: clean initialisation/power up
[z180-stamp.git] / stm32 / z180-stamp-stm32.c
CommitLineData
e64eba00
L
1/*
2 */
3
eded7ec4 4#include <stdio.h>
e64eba00
L
5
6#include <libopencmsis/core_cm3.h>
7#include <libopencm3/cm3/nvic.h>
8#include <libopencm3/cm3/systick.h>
9#include <libopencm3/stm32/rtc.h>
e64eba00
L
10#include <libopencm3/stm32/rcc.h>
11#include <libopencm3/stm32/gpio.h>
12#include <libopencm3/stm32/timer.h>
13
14#define ODR 0x0c
15#define IDR 0x08
16
17
6b81b39f
L
18#include "debug.h"
19#include "serial.h"
e64eba00 20#include "z80-if.h"
f4d5b4fe 21#include "../z180/hdrom.h"
e64eba00 22
6b81b39f 23#define ESCCHAR ('^'-0x40)
e64eba00
L
24
25#define S_10MS_TO (1<<0)
26
27/*
28 * LED Connections
29 */
30
31#define LED_PORT GPIOC
32#define LED_BLUE_PIN GPIO8
33#define BLUE 8
34#define LED_GREEN_PIN GPIO9
35#define GREEN 9
36
37
38#define LED_BLUE_ON() BBIO_PERIPH(LED_PORT+ODR, BLUE) = 1
39#define LED_BLUE_OFF() BBIO_PERIPH(LED_PORT+ODR, BLUE) = 0
40#define LED_BLUE_TOGGLE() BBIO_PERIPH(LED_PORT+ODR, BLUE) = !BBIO_PERIPH(LED_PORT+ODR, BLUE)
41
42#define LED_GREEN_ON() BBIO_PERIPH(LED_PORT+ODR, GREEN) = 1
43#define LED_GREEN_OFF() BBIO_PERIPH(LED_PORT+ODR, GREEN) = 0
44#define LED_GREEN_TOGGLE() BBIO_PERIPH(LED_PORT+ODR, GREEN) = !BBIO_PERIPH(LED_PORT+ODR, GREEN)
45
46
47/*
48 * Button connections
49 */
50
51//BBIO_PERIPH(GPIOA+IDR, 0);
52
53#define KEY_PORT GPIOA_IDR
54#define KEY0 GPIO0
55//#define KEY1 GPIO1
56//#define KEY2 GPIO2
57
58#define REPEAT_MASK KEY0 // repeat: key0
59#define REPEAT_START 100 // after 1s
60#define REPEAT_NEXT 20 // every 200ms
61
62
63typedef enum {
64 NOTHING, PULSE, BLINK1, BLINK2
65} LED_MODE;
66
67typedef struct {
68 uint8_t mode;
69 uint8_t ontime, offtime;
70} led_stat_t;
71
72volatile uint8_t led_timer[2];
73led_stat_t led_stat[2];
74
75volatile int timeout_1s;
76volatile uint32_t Stat;
77
78
79/*--------------------------------------------------------------------------*/
80
81
82static void clock_setup(void)
83{
0d318092
L
84 //rcc_clock_setup_in_hse_8mhz_out_24mhz();
85 rcc_clock_setup_in_hsi_out_24mhz();
e64eba00
L
86
87 /* Enable clocks for:
88 GPIO port A (for GPIO_USART1_TX and Button)
89 GPIO port C (LEDs)
90 USART1
91 TIM16 (RST-Pin)
0d318092 92 TIM1 (IOCS1)
e64eba00
L
93 */
94 rcc_peripheral_enable_clock(&RCC_APB2ENR,
95 RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN
96 | RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN
97 | RCC_APB2ENR_USART1EN | RCC_APB2ENR_AFIOEN
98 | RCC_APB2ENR_TIM1EN | RCC_APB2ENR_TIM16EN);
99 /* Enable clocks for:
100 TIM3
101 */
102 rcc_peripheral_enable_clock(&RCC_APB1ENR,
103 RCC_APB1ENR_TIM3EN);
104
105 /* Enable clocks for:
0d318092 106 DMA1
e64eba00
L
107 */
108 rcc_peripheral_enable_clock(&RCC_AHBENR,
109 RCC_AHBENR_DMA1EN);
110}
111
112static void systick_setup(void)
113{
114 /* SysTick interrupt every N clock pulses: set reload to N-1 */
115 STK_RVR = 24000000/1000 - 1;
116
117 /* Set source to core clock, enable int and start counting. */
118 STK_CSR = STK_CSR_CLKSOURCE_AHB | STK_CSR_TICKINT | STK_CSR_ENABLE;
119}
120
121#if 0
122static void nvic_setup(void)
123{
124// nvic_enable_irq(NVIC_RTC_IRQ);
125// nvic_set_priority(NVIC_RTC_IRQ, 1);
126}
127#endif
128
129static void tim3_setup(void)
130{
131 TIM3_CR1 = TIM_CR1_CMS_EDGE | TIM_CR1_DIR_UP;
132
133 TIM3_CCMR2 = 0
134 | TIM_CCMR2_OC4M_FORCE_LOW
135 /* | TIM_CCMR2_OC4M_FORCE_HIGH */
136 /* | TIM_CCMR2_OC4M_PWM2 */
137
138 /* | TIM_CCMR2_OC4PE */
139 /* | TIM_CCMR2_OC4FE */
140 | TIM_CCMR2_CC4S_OUT;
141
142 TIM3_CCER = TIM_CCER_CC4E
143 | TIM_CCER_CC4P;
144
145 TIM3_ARR = 48; /* default */
146 TIM3_CCR4 = 1; /* */
147}
148
149static void gpio_setup(void)
150{
151
152 /* Disable JTAG-DP, but leave SW-DP Enabled. (free PA15, PB3, PB4)
153 Remap SPI1 to PB3, PB4, PB5 and PA15.
154 Remap TIM3 (CH1/PC6, CH2/PC7, CH3/PC8, CH4/PC9)
0d318092 155 Port D0/Port D1 mapping on OSC_IN/OSC_OUT
e64eba00
L
156 */
157 gpio_primary_remap(AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_ON,
0d318092
L
158 AFIO_MAPR_SPI1_REMAP
159 | AFIO_MAPR_TIM3_REMAP_FULL_REMAP
160 | AFIO_MAPR_PD01_REMAP);
e64eba00
L
161
162 /* LEDs and User Button. */
163 gpio_set_mode(LED_PORT, GPIO_MODE_OUTPUT_2_MHZ,
164 GPIO_CNF_OUTPUT_PUSHPULL, LED_BLUE_PIN);
165 gpio_set_mode(LED_PORT, GPIO_MODE_OUTPUT_10_MHZ,
166 GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, LED_GREEN_PIN);
167 gpio_set_mode(GPIOA, GPIO_MODE_INPUT,
168 GPIO_CNF_INPUT_FLOAT, GPIO0);
169}
170
171
e64eba00
L
172/*--------------------------------------------------------------------------*/
173
174void delay_systicks(int ticks)
175{
176 int start, stop, now;
177
178 start = STK_CVR;
179 stop = start - ticks;
180 if (stop < 0) {
181 stop += STK_RVR;
182 do {
183 now = STK_CVR;
184 } while ((now > stop) || (now <= start));
185 } else {
186 do {
187 now = STK_CVR;
188 } while ((now > stop) && (now <= start));
189 }
190}
191
192
193/*--------------------------------------------------------------------------*/
194
195static void led_toggle(uint8_t lednr) {
196 if (lednr == 0)
197 LED_BLUE_TOGGLE();
198 else if (lednr == 1)
199 LED_GREEN_TOGGLE();
200}
201
202static void led_on(uint8_t lednr) {
203 if (lednr == 0)
204 LED_BLUE_ON();
205 else if (lednr == 1)
206 LED_GREEN_ON();
207}
208
209static void led_off(uint8_t lednr) {
210 if (lednr == 0)
211 LED_BLUE_OFF();
212 else if (lednr == 1)
213 LED_GREEN_OFF();
214}
215
216static uint8_t led_is_on(uint8_t lednr) {
217 if (lednr == 0)
218 return BBIO_PERIPH(LED_PORT+ODR, BLUE);
219 else if (lednr == 1)
220 return BBIO_PERIPH(LED_PORT+ODR, GREEN);
221 else
222 return 0;
223}
224
225static void ledset(uint8_t lednr, uint8_t what, uint8_t len) {
226
227 led_stat[lednr].mode = what;
228 switch (what) {
229 case PULSE:
230 led_stat[lednr].ontime = len;
231 led_stat[lednr].offtime = 0;
232 led_timer[lednr] = len;
233 led_on(lednr);
234 break;
235 case BLINK1:
236 case BLINK2:
237 if (what == BLINK1)
238 led_stat[lednr].offtime = 100 - len;
239 else
240 led_stat[lednr].offtime = 200 - len;
241 led_stat[lednr].ontime = len;
242 led_timer[lednr] = len;
243 led_on(lednr);
244 break;
245 default:
246 break;
247 }
248}
249
250/*--------------------------------------------------------------------------*/
251
252static volatile uint16_t key_state,
253 key_press, // key press detect
254 key_rpt; // key long press and repeat
255
256
257static uint16_t get_key_press(uint16_t key_mask) {
258 __disable_irq();
259 // read and clear atomic !
260 key_mask &= key_press; // read key(s)
261 key_press ^= key_mask; // clear key(s)
262 __enable_irq();
263 return key_mask;
264}
265
6b81b39f 266/*
e64eba00
L
267static uint16_t get_key_rpt(uint16_t key_mask) {
268 __disable_irq();
269 // read and clear atomic !
270 key_mask &= key_rpt; // read key(s)
271 key_rpt ^= key_mask; // clear key(s)
272 __enable_irq();
273 return key_mask;
274}
6b81b39f 275*/
e64eba00
L
276
277static uint16_t get_key_short(uint16_t key_mask) {
278 __disable_irq();
279 // read key state and key press atomic !
280 return get_key_press(key_state & key_mask);
281}
282
283/*
284static uint16_t get_key_long(uint16_t key_mask) {
285 return get_key_press(get_key_rpt(key_mask));
286}
287*/
288
289static void key_timerproc() {
290 static uint16_t key_in_last, rpt;
291 uint16_t key_in, c;
292
293 key_in = KEY_PORT;
294
295 c = key_in_last & key_in & ~key_state;
296
297// key_state = key_state & key_in_last | (key_state | key_in_last) & key_in;
298// key_state = key_state & key_in | (key_state | key_in) & key_in_last;
299
300 key_state = c | ((key_in_last | key_in) & key_state);
301
302// key_state = (key_state&key_in_last) | (key_state&key_in) | (key_in_last&key_in);
303
304 key_press |= c;
305
306 key_in_last = key_in;
307
308
309 if ((key_state & REPEAT_MASK) == 0) // check repeat function
310 rpt = REPEAT_START;
311 if (--rpt == 0) {
312 rpt = REPEAT_NEXT; // repeat delay
313 key_rpt |= key_state & REPEAT_MASK;
314 }
315
e64eba00
L
316}
317
318/*--------------------------------------------------------------------------*/
319
320void sys_tick_handler(void)
321{
0c5890bb
L
322 static int_fast8_t tick_10ms = 0;
323 static int_fast16_t count_ms = 0;
e64eba00 324
0c5890bb 325 int_fast8_t i;
e64eba00
L
326
327 ++tick_10ms;
328 if (tick_10ms == 10)
329 {
330 Stat |= S_10MS_TO;
331
332 tick_10ms = 0;
333
334 i = led_timer[0];
335 if (i)
336 led_timer[0] = i - 1;
337 i = led_timer[1];
338 if (i)
339 led_timer[1] = i - 1;
340
341 key_timerproc();
342
343 /* Drive timer procedure of low level disk I/O module */
344 //disk_timerproc();
345 }
346
347 count_ms++;
348 if (count_ms == 1000) {
349 count_ms = 0;
350
0d318092
L
351 i = timeout_1s;
352 if (i)
353 timeout_1s = i - 1;
e64eba00
L
354 }
355}
356
357void rtc_isr(void)
358{
359 /* The interrupt flag isn't cleared by hardware, we have to do it. */
360 rtc_clear_flag(RTC_SEC);
361
362}
363
364/*--------------------------------------------------------------------------*/
365
366void tim3_set(int mode)
367{
368 uint16_t cc_mode;
369
370 cc_mode = TIM_CCMR2_CC4S_OUT;
371
0d318092 372 TIM3_CR1 = TIM_CR1_CMS_EDGE | TIM_CR1_DIR_UP /*| TIM_CR1_OPM */ ;
e64eba00
L
373
374 if (mode < 0)
375 cc_mode |= TIM_CCMR2_OC4M_FORCE_LOW;
376 else if (mode == 0)
377 cc_mode |= TIM_CCMR2_OC4M_FORCE_HIGH;
378 else {
379 TIM3_ARR = mode;
0d318092 380 TIM3_CCR4 = mode/2;
e64eba00
L
381 cc_mode |= TIM_CCMR2_OC4M_PWM2;
382 }
383
384 TIM3_CCMR2 = cc_mode;
385
386 if (mode > 0)
387 TIM3_CR1 |= TIM_CR1_CEN;
388}
389
390/*--------------------------------------------------------------------------*/
391
0c5890bb 392static uint32_t z80_sram_cmp(uint32_t addr, uint32_t length, uint8_t wval, int inc)
e64eba00
L
393{
394 uint8_t rval;
0c5890bb 395 int_fast8_t errors = 0;
e64eba00 396
eded7ec4 397 DBG_P(1, "SRAM: Check %#.5x byte... ", length);
e64eba00
L
398 while (length--) {
399 if ((rval = z80_read(addr)) != wval) {
400 if (errors == 0) {
401 printf("\nSRAM: Address W R\n" \
402 " -------------\n");
403// 12345 00 11
404 }
405 printf(" %.5lx %.2x %.2x\n", addr, wval, rval);
406
407 if (++errors > 16 )
408 break;
409 }
410 addr++;
411 wval += inc;
412 }
6b81b39f 413 DBG_P(1, "Done.\n");
e64eba00
L
414
415 return addr;
416}
417
418#if 0
419static void z80_sram_fill(uint32_t addr, int length, uint8_t startval, int inc)
420{
421 printf("SRAM: Write %#.5x byte... ", length); //fflush(stdout);
422 while (length--) {
423 z80_write(addr, startval);
424 ++addr;
425 startval += inc;
426 }
427 printf("Done.\n");
428}
429
430
431void z80_sram_fill_string(uint32_t addr, int length, const char *text)
432{
433 char c;
434 const char *p = text;
435
436 while (length--) {
437 z80_write(addr++, c = *p++);
438 if (c == 0)
439 p = text;
440 }
441}
442
443
444uint32_t z80_sram_cmp_string(uint32_t addr, int length, const char *text)
445{
446 char c;
447 const char *p = text;
448
449 while (length--) {
450 c = *p++;
451 if (z80_read(addr) != c)
452 break;
453 ++addr;
454 if (c == 0)
455 p = text;
456 }
457 return addr;
458}
459
460const char * const qbfox = "Zhe quick brown fox jumps over the lazy dog!";
461const char * const qbcat = "Zhe quick brown fox jumps over the lazy cat!";
462
463#endif
464
465uint8_t z80_get_byte(uint32_t adr)
466{
467 uint8_t data;
468
0d318092 469 z80_request_bus();
e64eba00
L
470 data = z80_read(adr),
471 z80_release_bus();
472
473 return data;
474}
475
476
477/*--------------------------------------------------------------------------*/
478
479static void do_10ms(void)
480{
0d318092 481 for (uint_fast8_t i = 0; i < 2; i++) {
e64eba00
L
482 switch (led_stat[i].mode) {
483 case PULSE:
484 if (led_timer[i] == 0) {
485 led_off(i);
486 led_stat[i].mode = NOTHING;
487 }
488 break;
489 case BLINK1:
490 case BLINK2:
491 if (led_timer[i] == 0) {
492 if (led_is_on(i))
493 led_timer[i] = led_stat[i].offtime;
494 else
495 led_timer[i] = led_stat[i].ontime;
496 led_toggle(i);
497 }
498 break;
499 default:
500 break;
501 }
502 }
503}
504
d9c2b1b6
L
505struct msg_item {
506 uint8_t fct;
507 uint8_t sub_min, sub_max;
508 void (*func)(uint8_t, int, uint8_t *);
509};
510
511uint32_t msg_to_addr(uint8_t *msg)
6b81b39f 512{
0c5890bb 513 uint32_t addr = msg[0] | (msg[1] << 8) | ((uint32_t)msg[2] << 16);
d9c2b1b6
L
514
515 return addr;
516
6b81b39f
L
517}
518
d9c2b1b6 519void do_msg_ini_msgfifo(uint8_t subf, int len, uint8_t * msg)
6b81b39f 520{
d9c2b1b6
L
521 (void)subf; (void)len;
522
523 z80_init_msg_fifo(msg_to_addr(msg));
524}
525
526
527void do_msg_ini_memfifo(uint8_t subf, int len, uint8_t * msg)
528{
529 (void)len;
530
531 z80_memfifo_init(subf - 1, msg_to_addr(msg));
6b81b39f
L
532}
533
d9c2b1b6
L
534
535void do_msg_char_out(uint8_t subf, int len, uint8_t * msg)
536{
537 (void)subf;
538
539 while (len--)
540 putchar(*msg++);
541}
542
543
544const struct msg_item z80_messages[] =
545{
0c5890bb
L
546 { 0, /* fct nr. */
547 0, 0, /* sub fct nr. from, to */
d9c2b1b6
L
548 &do_msg_ini_msgfifo},
549 { 0,
550 1, 2,
551 &do_msg_ini_memfifo},
552 { 1,
553 1, 1,
554 &do_msg_char_out},
555 { 0xff, /* end mark */
556 0, 0,
557 0},
558
559};
560
561
562
563
6b81b39f
L
564void do_message(int len, uint8_t *msg)
565{
d9c2b1b6 566 uint8_t fct, sub_fct;
0c5890bb 567 int_fast8_t i = 0;
6b81b39f 568
d9c2b1b6
L
569 if (len >= 2) {
570 fct = *msg++;
571 sub_fct = *msg++;
572 len -= 2;
573
574 while (fct != z80_messages[i].fct)
575 ++i;
576
577 if (z80_messages[i].fct == 0xff) {
578 DBG_P(1, "do_message: Unknown function: %i, %i\n",
579 fct, sub_fct);
580 return; /* TODO: unknown message # */
581 }
582
583 while (fct == z80_messages[i].fct) {
584 if (sub_fct >= z80_messages[i].sub_min && sub_fct <= z80_messages[i].sub_max )
585 break;
586 ++i;
6b81b39f 587 }
d9c2b1b6
L
588
589 if (z80_messages[i].fct != fct) {
590 DBG_P(1, "do_message: Unknown sub function: %i, %i\n",
591 fct, sub_fct);
592 return; /* TODO: unknown message sub# */
593 }
594
595 (z80_messages[i].func)(sub_fct, len, msg);
596
597
6b81b39f 598 } else {
d9c2b1b6
L
599 /* TODO: error */
600 DBG_P(1, "do_message: to few arguments (%i); this shouldn't happen!\n", len);
6b81b39f
L
601 }
602}
603
604
6b81b39f 605
d9c2b1b6
L
606#define CTRBUF_LEN 256
607
608void check_msg_fifo(void)
0d318092 609{
6b81b39f 610 int ch;
0c5890bb 611 static int_fast8_t state;
6b81b39f
L
612 static int msglen,idx;
613 static uint8_t buffer[CTRBUF_LEN];
614
615 while (state != 3 && (ch = z80_msg_fifo_getc()) >= 0) {
616 switch (state) {
617 case 0: /* wait for start of message */
618 if (ch == 0x81) {
619 msglen = 0;
620 idx = 0;
621 state = 1;
622 }
623 break;
624 case 1: /* get msg len */
625 if (ch > 0 && ch <= CTRBUF_LEN) {
626 msglen = ch;
627 state = 2;
628 } else
629 state = 0;
630 break;
631 case 2: /* get message */
632 buffer[idx++] = ch;
633 if (idx == msglen)
634 state = 3;
635 break;
0d318092
L
636 }
637 }
6b81b39f
L
638
639 if (state == 3) {
640 do_message(msglen, buffer);
641 state = 0;
642 }
0d318092
L
643}
644
6b81b39f
L
645
646void z80_load_mem(void)
647{
6b81b39f
L
648 unsigned sec = 0;
649 uint32_t sec_base = hdrom_start;
650
0c5890bb
L
651 DBG_P(1, "Loading z80 memory... \n");
652
6b81b39f
L
653 while (sec < hdrom_sections) {
654 DBG_P(2, " From: 0x%.5lX to: 0x%.5lX (%5li bytes)\n",
655 hdrom_address[sec],
656 hdrom_address[sec]+hdrom_length_of_sections[sec] - 1,
657 hdrom_length_of_sections[sec]);
658
659 z80_write_block((unsigned char *) &hdrom[sec_base], /* src */
660 hdrom_address[sec], /* dest */
661 hdrom_length_of_sections[sec]); /* len */
662 sec_base+=hdrom_length_of_sections[sec];
663 sec++;
664 }
665}
e64eba00
L
666/*--------------------------------------------------------------------------*/
667
668int main(void)
669{
0c5890bb 670 int_fast8_t state = 0;
6b81b39f 671 int ch;
e64eba00
L
672
673 clock_setup();
674 gpio_setup();
675 tim3_setup();
676 setvbuf(stdout, NULL, _IONBF, 0);
6b81b39f 677 serial_setup();
0d318092 678 printf("\n(STM32F100+HD64180)_stamp Tester\n");
e64eba00 679
6b81b39f
L
680 DBG_P(1, "z80_setup_bus... ");
681 z80_setup_msg_fifo();
e64eba00 682 z80_setup_bus();
6b81b39f 683 DBG_P(1, "done.\n");
e64eba00
L
684
685 /*
686 * If the RTC is pre-configured just allow access, don't reconfigure.
687 * Otherwise enable it with the LSE as clock source and 0x7fff as
688 * prescale value.
689 */
690 rtc_auto_awake(LSE, 0x7fff);
691
692 systick_setup();
e64eba00 693
6b81b39f 694 DBG_P(1, "Get bus... ");
e64eba00
L
695 z80_busreq(LOW);
696 z80_reset(HIGH);
0d318092 697 z80_request_bus();
6b81b39f 698 DBG_P(1, "got it!\n");
e64eba00
L
699
700 z80_memset(0, 0x76, 0x80000);
701 //z80_sram_fill(0, 512 * 1024, 0x76, 0);
0c5890bb 702 z80_sram_cmp(0, (uint32_t)512 * 1024, 0x76, 0);
e64eba00 703
6b81b39f 704 z80_load_mem();
e64eba00 705 z80_reset(LOW);
6b81b39f 706 DBG_P(1, "Bus released!\n");
e64eba00
L
707 z80_release_bus();
708 z80_reset(HIGH);
6b81b39f 709 DBG_P(1, "Reset released!\n");
e64eba00 710
e64eba00
L
711
712 ledset(0, BLINK1, 50);
713
714 while (1) {
6b81b39f 715
e64eba00
L
716 if (Stat & S_10MS_TO) {
717 Stat &= ~S_10MS_TO;
718 do_10ms();
719 }
720
0d318092 721 if (get_key_short(KEY0)) {
e64eba00 722 z80_reset_pulse();
0d318092 723 }
e64eba00 724
6b81b39f
L
725 if ((ch = serial_getc()) >= 0) {
726 switch (state) {
e64eba00 727 case 0:
6b81b39f
L
728 if (ch == ESCCHAR) {
729 state = 1;
730 /* TODO: Timer starten */
731 } else
732 z80_memfifo_putc(fifo_out, ch);
e64eba00 733 break;
6b81b39f
L
734 case 1:
735 switch (ch) {
e64eba00 736
6b81b39f 737 case 'h': /* test: green led on */
e64eba00
L
738 tim3_set(-1);
739 break;
6b81b39f 740 case 'l': /* test: green led off */
e64eba00
L
741 tim3_set(0);
742 break;
6b81b39f
L
743 case 'p': /* test: pulse on led pin */
744 tim3_set(24000000 / 1000000 * 5); /* 5 us */
745 break;
746 case 'r':
747 z80_reset_pulse();
e64eba00 748 break;
e64eba00 749
6b81b39f
L
750 case ESCCHAR:
751 default:
752 z80_memfifo_putc(fifo_out, ch);
753 }
754 state = 0;
755 break;
e64eba00 756 }
e64eba00 757 }
0d318092 758
6b81b39f 759 check_msg_fifo();
e64eba00
L
760 }
761
762 return 0;
763}