/* * (C) Copyright 2014 Leo C. * * SPDX-License-Identifier: GPL-2.0 */ #include "common.h" #include #include #include #include "config.h" #include "ff.h" #include "z80-if.h" #include "i2c.h" #include "con-utils.h" #include "serial.h" #include "timer.h" #include "cli.h" #include "env.h" #include "z180-serv.h" #include "gpio.h" #include "time.h" #include "rtc.h" #include "debug.h" uint8_t mcusr __attribute__ ((section (".noinit"))); #if DEBUG __attribute__ ((naked)) __attribute__ ((section (".init3"))) void preset_ram (void) { for (uint8_t *p = (uint8_t *) RAMSTART; p <= (uint8_t *) RAMEND; p++) *p = 0xdd; } #endif __attribute__ ((naked)) __attribute__ ((section (".init3"))) void get_mcusr (void) { /* save and clear reset reason(s) */ /* TODO: move to init section? */ mcusr = MCUSR; MCUSR = 0; wdt_disable(); } /*--------------------------------------------------------------------------*/ #if DEBUG static const FLASH char * const FLASH rreasons[] = { FSTR("Power on"), FSTR("External"), FSTR("Brown out"), FSTR("Watchdog"), FSTR("JTAG"), }; static void print_reset_reason(void) { uint8_t r = mcusr & 0x1f; const FLASH char * const FLASH *p = rreasons; printf_P(PSTR("### Reset reason(s): %s"), r ? "" : "none"); for ( ; r; p++, r >>= 1) { if (r & 1) { my_puts_P(*p); if (r & ~1) printf_P(PSTR(", ")); } } printf_P(PSTR(".\n")); } #endif ISR(INT5_vect) { Stat |= S_MSG_PENDING; } ISR(INT6_vect) { Stat |= S_CON_PENDING; } static void setup_avr(void) { /* CPU */ /* Disable JTAG Interface regardless of the JTAGEN fuse setting. */ MCUCR = _BV(JTD); MCUCR = _BV(JTD); /* Disable peripherals. Enable individually in respective init function. */ PRR0 = _BV(PRTWI) | _BV(PRTIM2) | _BV(PRTIM0) | _BV(PRTIM1) | _BV(PRSPI) | _BV(PRUSART0) | _BV(PRADC); PRR1 = _BV(PRTIM5) | _BV(PRTIM4) | _BV(PRTIM3) | _BV(PRUSART3) | _BV(PRUSART2) | _BV(PRUSART1); /* disable analog comparator */ ACSR = _BV(ACD); /* Ports */ /* Clock */ CLKPR = _BV(CLKPCE); CLKPR = 0; /* Timer */ PRR1 &= ~_BV(PRTIM4); OCR4A = F_CPU / 1000 - 1; /* Timer4: 1000Hz interval */ TCCR4B = (0b00<= 0) printf_P(PSTR("Hit any key to stop autoboot: %2d "), bootdelay); #if defined CONFIG_ZERO_BOOTDELAY_CHECK /* * Check if key already pressed * Don't check if bootdelay < 0 */ if (bootdelay >= 0) { if (tstc()) { /* we got a key press */ (void) my_getchar(1); /* consume input */ my_puts_P(PSTR("\b\b\b 0")); abort = 1; /* don't auto boot */ } } #endif while ((bootdelay > 0) && (!abort)) { --bootdelay; /* delay 1000 ms */ ts = get_timer(0); do { if (tstc()) { /* we got a key press */ abort = 1; /* don't auto boot */ bootdelay = 0; /* no more delay */ break; } udelay(10000); } while (!abort && get_timer(ts) < 1000); printf_P(PSTR("\b\b\b%2d "), bootdelay); } putchar('\n'); return abort; } static const char *bootdelay_process(void) { char *s; int bootdelay; bootdelay = (int) getenv_ulong(PSTR(ENV_BOOTDELAY), 10, CONFIG_BOOTDELAY); debug("### main_loop entered: bootdelay=%d\n\n", bootdelay); _delay_ms(20); s = getenv_str(PSTR(ENV_BOOTCMD)); stored_bootdelay = bootdelay; return s; } static void autoboot_command(const char *s) { debug("### main_loop: bootcmd=\"%s\"\n", s ? s : ""); _delay_ms(20); if (stored_bootdelay != -1 && s && !abortboot(stored_bootdelay)) { run_command_list(s, -1); } } static void main_loop(void) { const char *s; s = bootdelay_process(); autoboot_command(s); cli_loop(); } int main(void) { extern void setup_mmc(void); setup_avr(); for (int i = 0; i < GPIO_MAX; i++) gpio_config(i, INPUT_PULLUP); setup_mmc(); env_init(); z80_setup_bus(); if (reset_reason_is_power_on()) _delay_ms(CONFIG_PWRON_DELAY); serial_setup(getenv_ulong(PSTR(ENV_BAUDRATE), 10, CONFIG_BAUDRATE)); sei(); #if DEBUG debug("\n=========================< (RE)START DEBUG >=========================\n"); print_reset_reason(); #endif i2c_init(CONFIG_SYS_I2C_CLOCK); setup_system_time(); setup_fatfs(); printf_P(PSTR("\n" MCU_STRING "+Z8S180 Stamp Monitor - Version: " VERSION " \n\n")); setup_z180_serv(); main_loop(); }