X-Git-Url: http://cloudbase.mooo.com/gitweb/z180-stamp.git/blobdiff_plain/0d318092d9a4424aca61dd34de9658db08e09dfd..b30c4e8f1aef96f6fdc93da9f125545f5f74d06e:/stm32/z180-stamp-stm32.c?ds=sidebyside diff --git a/stm32/z180-stamp-stm32.c b/stm32/z180-stamp-stm32.c index ce161d8..888494d 100644 --- a/stm32/z180-stamp-stm32.c +++ b/stm32/z180-stamp-stm32.c @@ -1,15 +1,15 @@ /* + * (C) Copyright 2014 Leo C. + * + * SPDX-License-Identifier: GPL-2.0+ */ -#include #include -#include #include #include #include #include -#include #include #include #include @@ -18,13 +18,12 @@ #define IDR 0x08 - +#include "debug.h" +#include "serial.h" #include "z80-if.h" -#include "hdrom.h" - -#define USART_CONSOLE USART1 +#include "../z180/hdrom.h" -int _write(int fd, char *ptr, int len) __attribute__((used)); +#define ESCCHAR ('^'-0x40) #define S_10MS_TO (1<<0) @@ -90,27 +89,26 @@ static void clock_setup(void) /* Enable clocks for: GPIO port A (for GPIO_USART1_TX and Button) - GPIO port C (LEDs) + GPIO port C (LEDs) USART1 - TIM16 (RST-Pin) + TIM16 (RST-Pin) TIM1 (IOCS1) - TODO: USART1 --> USART_CONSOLE */ - rcc_peripheral_enable_clock(&RCC_APB2ENR, - RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN - | RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN + rcc_peripheral_enable_clock(&RCC_APB2ENR, + RCC_APB2ENR_IOPAEN | RCC_APB2ENR_IOPBEN + | RCC_APB2ENR_IOPCEN | RCC_APB2ENR_IOPDEN | RCC_APB2ENR_USART1EN | RCC_APB2ENR_AFIOEN | RCC_APB2ENR_TIM1EN | RCC_APB2ENR_TIM16EN); /* Enable clocks for: TIM3 */ - rcc_peripheral_enable_clock(&RCC_APB1ENR, + rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_TIM3EN); /* Enable clocks for: DMA1 */ - rcc_peripheral_enable_clock(&RCC_AHBENR, + rcc_peripheral_enable_clock(&RCC_AHBENR, RCC_AHBENR_DMA1EN); } @@ -134,19 +132,19 @@ static void nvic_setup(void) static void tim3_setup(void) { TIM3_CR1 = TIM_CR1_CMS_EDGE | TIM_CR1_DIR_UP; - + TIM3_CCMR2 = 0 - | TIM_CCMR2_OC4M_FORCE_LOW + | TIM_CCMR2_OC4M_FORCE_LOW /* | TIM_CCMR2_OC4M_FORCE_HIGH */ /* | TIM_CCMR2_OC4M_PWM2 */ - + /* | TIM_CCMR2_OC4PE */ /* | TIM_CCMR2_OC4FE */ | TIM_CCMR2_CC4S_OUT; - + TIM3_CCER = TIM_CCER_CC4E | TIM_CCER_CC4P; - + TIM3_ARR = 48; /* default */ TIM3_CCR4 = 1; /* */ } @@ -159,7 +157,7 @@ static void gpio_setup(void) Remap TIM3 (CH1/PC6, CH2/PC7, CH3/PC8, CH4/PC9) Port D0/Port D1 mapping on OSC_IN/OSC_OUT */ - gpio_primary_remap(AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_ON, + gpio_primary_remap(AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_ON, AFIO_MAPR_SPI1_REMAP | AFIO_MAPR_TIM3_REMAP_FULL_REMAP | AFIO_MAPR_PD01_REMAP); @@ -174,61 +172,12 @@ static void gpio_setup(void) } -static void usart_setup(void) -{ - /* Setup GPIO pin GPIO_USART1_TX/LED_GREEN_PIN on GPIO port A for transmit. */ - /* TODO: USART1 --> USART_CONSOLE */ - - gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, - GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO_USART1_TX); - - /* Setup UART parameters. */ -// usart_set_baudrate(USART_CONSOLE, 38400); - usart_set_baudrate(USART_CONSOLE, 115200); - usart_set_databits(USART_CONSOLE, 8); - usart_set_stopbits(USART_CONSOLE, USART_STOPBITS_1); - usart_set_mode(USART_CONSOLE, USART_MODE_TX_RX); - usart_set_parity(USART_CONSOLE, USART_PARITY_NONE); - usart_set_flow_control(USART_CONSOLE, USART_FLOWCONTROL_NONE); - - /* Finally enable the USART. */ - usart_enable(USART_CONSOLE); -} - -/*--------------------------------------------------------------------------*/ - -/** - * Use USART_CONSOLE as a console. - * This is a syscall for newlib - * @param fd - * @param ptr - * @param len - * @return - */ -int _write(int fd, char *ptr, int len) -{ - int i; - - if (fd == STDOUT_FILENO || fd == STDERR_FILENO) { - for (i = 0; i < len; i++) { - if (ptr[i] == '\n') { - usart_send_blocking(USART_CONSOLE, '\r'); - } - usart_send_blocking(USART_CONSOLE, ptr[i]); - } - return i; - } - errno = EIO; - return -1; -} - - /*--------------------------------------------------------------------------*/ void delay_systicks(int ticks) { int start, stop, now; - + start = STK_CVR; stop = start - ticks; if (stop < 0) { @@ -317,6 +266,7 @@ static uint16_t get_key_press(uint16_t key_mask) { return key_mask; } +/* static uint16_t get_key_rpt(uint16_t key_mask) { __disable_irq(); // read and clear atomic ! @@ -325,6 +275,7 @@ static uint16_t get_key_rpt(uint16_t key_mask) { __enable_irq(); return key_mask; } +*/ static uint16_t get_key_short(uint16_t key_mask) { __disable_irq(); @@ -350,13 +301,13 @@ static void key_timerproc() { // key_state = key_state & key_in | (key_state | key_in) & key_in_last; key_state = c | ((key_in_last | key_in) & key_state); - + // key_state = (key_state&key_in_last) | (key_state&key_in) | (key_in_last&key_in); key_press |= c; - + key_in_last = key_in; - + if ((key_state & REPEAT_MASK) == 0) // check repeat function rpt = REPEAT_START; @@ -365,36 +316,16 @@ static void key_timerproc() { key_rpt |= key_state & REPEAT_MASK; } - -#if 0 - -static char ds[30]; -int dsi = 0; - -ds[dsi++] = key_state & 1 ? '1' : '0'; -ds[dsi++] = key_in_last & 1 ? '1' : '0'; -ds[dsi++] = key_in & 1 ? '1' : '0'; -ds[dsi++] = ' '; - -//ds[dsi++] = key_state & 1 ? '1' : '0'; -//ds[dsi++] = key_in_last & 1 ? '1' : '0'; - -//ds[dsi++] = ' '; -//ds[dsi++] = ' '; -ds[dsi++] = 0; -puts(ds); -#endif - } /*--------------------------------------------------------------------------*/ void sys_tick_handler(void) { - static int tick_10ms = 0; - static int count_ms = 0; + static int_fast8_t tick_10ms = 0; + static int_fast16_t count_ms = 0; - int i; + int_fast8_t i; ++tick_10ms; if (tick_10ms == 10) @@ -402,7 +333,7 @@ void sys_tick_handler(void) Stat |= S_10MS_TO; tick_10ms = 0; - + i = led_timer[0]; if (i) led_timer[0] = i - 1; @@ -411,11 +342,11 @@ void sys_tick_handler(void) led_timer[1] = i - 1; key_timerproc(); - + /* Drive timer procedure of low level disk I/O module */ //disk_timerproc(); } - + count_ms++; if (count_ms == 1000) { count_ms = 0; @@ -438,7 +369,7 @@ void rtc_isr(void) void tim3_set(int mode) { uint16_t cc_mode; - + cc_mode = TIM_CCMR2_CC4S_OUT; TIM3_CR1 = TIM_CR1_CMS_EDGE | TIM_CR1_DIR_UP /*| TIM_CR1_OPM */ ; @@ -452,37 +383,37 @@ void tim3_set(int mode) TIM3_CCR4 = mode/2; cc_mode |= TIM_CCMR2_OC4M_PWM2; } - + TIM3_CCMR2 = cc_mode; - + if (mode > 0) TIM3_CR1 |= TIM_CR1_CEN; } /*--------------------------------------------------------------------------*/ -static uint32_t z80_sram_cmp(uint32_t addr, int length, uint8_t wval, int inc) +static uint32_t z80_sram_cmp(uint32_t addr, uint32_t length, uint8_t wval, int inc) { uint8_t rval; - int errors = 0; - - printf("SRAM: Check %#.5x byte... ", length); //fflush(stdout); + int_fast8_t errors = 0; + + DBG_P(1, "SRAM: Check %#.5x byte... ", length); while (length--) { if ((rval = z80_read(addr)) != wval) { - if (errors == 0) { + if (errors == 0) { printf("\nSRAM: Address W R\n" \ " -------------\n"); // 12345 00 11 } printf(" %.5lx %.2x %.2x\n", addr, wval, rval); - + if (++errors > 16 ) break; } addr++; wval += inc; } - printf("Done.\n"); + DBG_P(1, "Done.\n"); return addr; } @@ -493,7 +424,7 @@ static void z80_sram_fill(uint32_t addr, int length, uint8_t startval, int inc) printf("SRAM: Write %#.5x byte... ", length); //fflush(stdout); while (length--) { z80_write(addr, startval); - ++addr; + ++addr; startval += inc; } printf("Done.\n"); @@ -537,18 +468,18 @@ const char * const qbcat = "Zhe quick brown fox jumps over the lazy cat!"; uint8_t z80_get_byte(uint32_t adr) { uint8_t data; - + z80_request_bus(); data = z80_read(adr), z80_release_bus(); - + return data; } /*--------------------------------------------------------------------------*/ -static void do_10ms(void) +static void do_10ms(void) { for (uint_fast8_t i = 0; i < 2; i++) { switch (led_stat[i].mode) { @@ -574,210 +505,262 @@ static void do_10ms(void) } } -void wait_for_z80_init_done(void) +struct msg_item { + uint8_t fct; + uint8_t sub_min, sub_max; + void (*func)(uint8_t, int, uint8_t *); +}; + +uint32_t msg_to_addr(uint8_t *msg) +{ + uint32_t addr = msg[0] | (msg[1] << 8) | ((uint32_t)msg[2] << 16); + + return addr; + +} + +void do_msg_ini_msgfifo(uint8_t subf, int len, uint8_t * msg) +{ + (void)subf; (void)len; + + z80_init_msg_fifo(msg_to_addr(msg)); +} + + +void do_msg_ini_memfifo(uint8_t subf, int len, uint8_t * msg) { - uint8_t buf, out_i, in_i, mask; - int to; - - timeout_1s = 10; - to = 0; - while (timeout_1s) { - if (to != timeout_1s) { - buf = z80_get_byte(tx_fifo - 0); - out_i = z80_get_byte(tx_fifo - 1); - in_i = z80_get_byte(tx_fifo - 2); - mask = z80_get_byte(tx_fifo - 3); - printf(" %.2x %.2x %.2x %.2x\n", buf, out_i, in_i, mask); - to = timeout_1s; - - if ((out_i == 0) && (mask == 0x7f)) - timeout_1s = 0; + (void)len; + + z80_memfifo_init(subf - 1, msg_to_addr(msg)); +} + + +void do_msg_char_out(uint8_t subf, int len, uint8_t * msg) +{ + (void)subf; + + while (len--) + putchar(*msg++); +} + + +const struct msg_item z80_messages[] = +{ + { 0, /* fct nr. */ + 0, 0, /* sub fct nr. from, to */ + &do_msg_ini_msgfifo}, + { 0, + 1, 2, + &do_msg_ini_memfifo}, + { 1, + 1, 1, + &do_msg_char_out}, + { 0xff, /* end mark */ + 0, 0, + 0}, + +}; + + + + +void do_message(int len, uint8_t *msg) +{ + uint8_t fct, sub_fct; + int_fast8_t i = 0; + + if (len >= 2) { + fct = *msg++; + sub_fct = *msg++; + len -= 2; + + while (fct != z80_messages[i].fct) + ++i; + + if (z80_messages[i].fct == 0xff) { + DBG_P(1, "do_message: Unknown function: %i, %i\n", + fct, sub_fct); + return; /* TODO: unknown message # */ + } + + while (fct == z80_messages[i].fct) { + if (sub_fct >= z80_messages[i].sub_min && sub_fct <= z80_messages[i].sub_max ) + break; + ++i; + } + + if (z80_messages[i].fct != fct) { + DBG_P(1, "do_message: Unknown sub function: %i, %i\n", + fct, sub_fct); + return; /* TODO: unknown message sub# */ + } + + (z80_messages[i].func)(sub_fct, len, msg); + + + } else { + /* TODO: error */ + DBG_P(1, "do_message: to few arguments (%i); this shouldn't happen!\n", len); + } +} + + + +#define CTRBUF_LEN 256 + +void check_msg_fifo(void) +{ + int ch; + static int_fast8_t state; + static int msglen,idx; + static uint8_t buffer[CTRBUF_LEN]; + + while (state != 3 && (ch = z80_msg_fifo_getc()) >= 0) { + switch (state) { + case 0: /* wait for start of message */ + if (ch == 0x81) { + msglen = 0; + idx = 0; + state = 1; + } + break; + case 1: /* get msg len */ + if (ch > 0 && ch <= CTRBUF_LEN) { + msglen = ch; + state = 2; + } else + state = 0; + break; + case 2: /* get message */ + buffer[idx++] = ch; + if (idx == msglen) + state = 3; + break; } } + + if (state == 3) { + do_message(msglen, buffer); + state = 0; + } } + +void z80_load_mem(void) +{ + unsigned sec = 0; + uint32_t sec_base = hdrom_start; + + DBG_P(1, "Loading z80 memory... \n"); + + while (sec < hdrom_sections) { + DBG_P(2, " From: 0x%.5lX to: 0x%.5lX (%5li bytes)\n", + hdrom_address[sec], + hdrom_address[sec]+hdrom_length_of_sections[sec] - 1, + hdrom_length_of_sections[sec]); + + z80_write_block((unsigned char *) &hdrom[sec_base], /* src */ + hdrom_address[sec], /* dest */ + hdrom_length_of_sections[sec]); /* len */ + sec_base+=hdrom_length_of_sections[sec]; + sec++; + } +} /*--------------------------------------------------------------------------*/ int main(void) { - //uint32_t led_state = LED_BLUE_PIN; - //uint32_t rc; - //uint8_t startval = 0; - //int count; - int stat, ch; - uint8_t c; + int_fast8_t state = 0; + int ch; clock_setup(); gpio_setup(); tim3_setup(); setvbuf(stdout, NULL, _IONBF, 0); - usart_setup(); + serial_setup(); printf("\n(STM32F100+HD64180)_stamp Tester\n"); - z80_setup_io_infifo(); + DBG_P(1, "z80_setup_bus... "); + z80_setup_msg_fifo(); z80_setup_bus(); - printf("z80_setup_bus done.\n"); + DBG_P(1, "done.\n"); /* * If the RTC is pre-configured just allow access, don't reconfigure. * Otherwise enable it with the LSE as clock source and 0x7fff as * prescale value. */ - rtc_auto_awake(LSE, 0x7fff); + rtc_auto_awake(RCC_LSE, 0x7fff); systick_setup(); - ///* Setup the RTC interrupt. */ - //nvic_setup(); - - /* Enable the RTC interrupt to occur off the SEC flag. */ - //rtc_interrupt_enable(RTC_SEC); - printf("get bus..."); + DBG_P(1, "Get bus... "); z80_busreq(LOW); z80_reset(HIGH); z80_request_bus(); - printf(" got it!\n"); - + DBG_P(1, "got it!\n"); + z80_memset(0, 0x76, 0x80000); //z80_sram_fill(0, 512 * 1024, 0x76, 0); - z80_sram_cmp(0, 512 * 1024, 0x76, 0); - - z80_write_block((unsigned char *) hdrom, 0, hdrom_length); + z80_sram_cmp(0, (uint32_t)512 * 1024, 0x76, 0); + + z80_load_mem(); z80_reset(LOW); - printf("bus released!\n"); + DBG_P(1, "Bus released!\n"); z80_release_bus(); z80_reset(HIGH); - printf(" reset released!\n"); - - wait_for_z80_init_done(); - z80_memfifo_init(); - + DBG_P(1, "Reset released!\n"); + + ledset(0, BLINK1, 50); while (1) { -// static int tickstat = 0; - + if (Stat & S_10MS_TO) { Stat &= ~S_10MS_TO; do_10ms(); } - -// if (get_key_long(KEY0)) -// ledset(1, PULSE, 100); - if (get_key_short(KEY0)) { z80_reset_pulse(); - wait_for_z80_init_done(); - z80_memfifo_init(); } - -/* - switch (tickstat) { - + if ((ch = serial_getc()) >= 0) { + switch (state) { case 0: - if (BBIO_PERIPH(GPIOA+IDR, 0)) - { - tickstat = 1; - - LED_GREEN_ON(); - LED_GREEN_OFF(); - LED_GREEN_ON(); - delay_systicks(12); - LED_GREEN_OFF(); - } + if (ch == ESCCHAR) { + state = 1; + /* TODO: Timer starten */ + } else + z80_memfifo_putc(fifo_out, ch); break; - default: - if (!BBIO_PERIPH(GPIOA+IDR, 0)) - tickstat = 0; - } -*/ - - //BBIO_PERIPH(LED_PORT+0x0C, 9) = BBIO_PERIPH(GPIOA+0x08, 0); - - //BBIO_PERIPH(LED_PORT+0x0C, 9) = !z80_stat_halt(); - - //BBIO_PERIPH(LED_PORT+0x0C, 9) = (~key_state & KEY0) != 0; - + case 1: + switch (ch) { -/* - stat = z80_fifo_is_not_full(rx_fifo); - if(stat) { - z80_fifo_putc(rx_fifo, 'y'); - if (++count == 154) { - putchar('\n'); - putchar('\r'); - count = 0; - } - - } -*/ - - stat = usart_get_flag(USART_CONSOLE, USART_SR_RXNE); - if (stat) { - c = usart_recv(USART_CONSOLE) & 0xff; - switch (c) { - case 'H': + case 'h': /* test: green led on */ tim3_set(-1); break; - case 'L': + case 'l': /* test: green led off */ tim3_set(0); break; - case 'P': - tim3_set(24000000/1000000 * 5); /* 5 us */ + case 'p': /* test: pulse on led pin */ + tim3_set(24000000 / 1000000 * 5); /* 5 us */ + break; + case 'r': + z80_reset_pulse(); break; + + case ESCCHAR: default: - z80_memfifo_putc(fifo_out, c); + z80_memfifo_putc(fifo_out, ch); + } + state = 0; + break; } } - if (timeout_1s == 0) { - - while (!z80_memfifo_is_empty(fifo_in)) { -// LED_GREEN_ON(); - c = z80_memfifo_getc(fifo_in); - putchar(c); -// LED_GREEN_OFF(); - } - - timeout_1s = 1; - } - - while ((ch = z80_io_infifo_getc()) >= 0) { - static int linepos; - - if (linepos == 0) - printf("\n"); - printf(" 0x%.2X ", ch); - linepos = (linepos + 1) % 16; - } + check_msg_fifo(); } return 0; } - -#if 0 - -static char ds[30]; -int dsi = 0; - -ds[dsi++] = key_state1 & 1 ? '1' : '0'; -ds[dsi++] = key_in_last & 1 ? '1' : '0'; -ds[dsi++] = key_in & 1 ? '1' : '0'; -ds[dsi++] = ' '; -ds[dsi++] = key_state1 & 1 ? '1' : '0'; -ds[dsi++] = key_in_last & 1 ? '1' : '0'; - -ds[dsi++] = ' '; -ds[dsi++] = ' '; -ds[dsi++] = key_state & 1 ? '1' : '0'; -ds[dsi++] = ct1 & 1 ? '0' : '1'; -ds[dsi++] = ct0 & 1 ? '0' : '1'; -ds[dsi++] = ' '; -ds[dsi++] = key_state & 1 ? '1' : '0'; -//ds[dsi++] = '\r'; -//ds[dsi++] = '\n'; -ds[dsi++] = 0; -puts(ds); -#endif