/* */ #include "common.h" #include #include #include #include #include "config.h" #include "debug.h" #include "z80-if.h" #include "i2c.h" #include "con-utils.h" #include "serial.h" #include "timer.h" #include "cli.h" #include "env.h" #define udelay(n) _delay_us(n) static uint8_t mcusr; /*--------------------------------------------------------------------------*/ #if DEBUG __attribute__ ((naked)) __attribute__ ((section (".init3"))) void preset_ram (void) { for (uint8_t *p = RAMSTART; p <= (uint8_t *) RAMEND; p++) *p = 0xdd; } 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 static void setup_avr(void) { /* save and clear reset reason(s) */ /* TODO: move to init section? */ mcusr = MCUSR; MCUSR = 0; /* WD */ /* CPU */ /* Disable JTAG Interface regardless of the JTAGEN fuse setting. */ MCUCR = _BV(JTD); MCUCR = _BV(JTD); /* disable unused periphels */ PRR0 = _BV(PRTIM2) | _BV(PRTIM0) | _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 */ OCR1A = F_CPU / 8 / 1000 - 1; // Timer1: 1000Hz interval (OC1A) TCCR1B = 0b00001010; TIMSK1 = _BV(OCIE1A); // Enable TC1.oca interrupt } static int reset_reason_is_power_on(void) { return (mcusr & _BV(PORF)) != 0; } /*--------------------------------------------------------------------------*/ /* Stored value of bootdelay, used by autoboot_command() */ static int stored_bootdelay; /*************************************************************************** * Watch for 'delay' seconds for autoboot stop. * returns: 0 - no key, allow autoboot * 1 - got key, abort */ static int abortboot(int bootdelay) { int abort = 0; uint32_t ts; if (bootdelay >= 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(); /* 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("bootdelay", 10, CONFIG_BOOTDELAY); debug("### main_loop entered: bootdelay=%d\n\n", bootdelay); _delay_ms(20); s = getenv("bootcmd"); stored_bootdelay = bootdelay; return s; } static void autoboot_command(const char *s) { debug("### main_loop: bootcmd=\"%s\"\n", s ? s : PSTR("")); _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) { setup_avr(); z80_setup_bus(); env_init(); if (reset_reason_is_power_on()) _delay_ms(CONFIG_PWRON_DELAY); serial_setup(getenv_ulong("baudrate", 10, CONFIG_BAUDRATE)); sei(); #if DEBUG debug("\n=========================< (RE)START DEBUG >=========================\n"); print_reset_reason(); #endif #if DEBUG unsigned long i_speed = getenv_ulong("i2c_clock", 10, CONFIG_SYS_I2C_CLOCK); debug("### Setting I2C clock Frequency to %lu Hz.\n", i_speed); i2c_init(i_speed); #else i2c_init(CONFIG_SYS_I2C_CLOCK); #endif printf_P(PSTR("\n(ATMEGA1281+HD64180)_stamp Tester\n")); main_loop(); }