#include "d51_util.h" static volatile uint32_t w; // Display unsigned 32-bit number by port toggling DBG_1 (to view on a scope) // Read as follows: 1230 = | | | | | | || (note zero is fast double toggle) #define DBG_PAUSE 5 void dbg_print(uint32_t x) { int8_t t; uint32_t n; uint32_t p, p2; if (x < 10) t = 0; else if (x < 100) t = 1; else if (x < 1000) t = 2; else if (x < 10000) t = 3; else if (x < 100000) t = 4; else if (x < 1000000) t = 5; else if (x < 10000000) t = 6; else if (x < 100000000) t = 7; else if (x < 1000000000) t = 8; else t = 9; while (t >= 0) { p2 = t; p = 1; while (p2--) p *= 10; n = x / p; x -= n * p; if (!n) { DBG_1_ON; DBG_1_OFF; DBG_1_ON; DBG_1_OFF; n--; } else { while (n > 0) { DBG_1_ON; DBG_1_OFF; n--; } } t--; } for (w = DBG_PAUSE; w; w--) ; // Long pause after number is complete } // Display unsigned 32-bit number through debug led // Read as follows: 1230 = [*] [* *] [* * *] [**] (note zero is fast double flash) #define DLED_ONTIME 1000000 #define DLED_PAUSE 1500000 void dled_print(uint32_t x, uint8_t long_pause) { int8_t t; uint32_t n; uint32_t p, p2; if (x < 10) t = 0; else if (x < 100) t = 1; else if (x < 1000) t = 2; else if (x < 10000) t = 3; else if (x < 100000) t = 4; else if (x < 1000000) t = 5; else if (x < 10000000) t = 6; else if (x < 100000000) t = 7; else if (x < 1000000000) t = 8; else t = 9; while (t >= 0) { p2 = t; p = 1; while (p2--) p *= 10; n = x / p; x -= n * p; if (!n) { DBG_LED_ON; for (w = DLED_ONTIME / 4; w; w--) ; DBG_LED_OFF; for (w = DLED_ONTIME / 4; w; w--) ; DBG_LED_ON; for (w = DLED_ONTIME / 4; w; w--) ; DBG_LED_OFF; for (w = DLED_ONTIME / 4; w; w--) ; n--; } else { while (n > 0) { DBG_LED_ON; for (w = DLED_ONTIME; w; w--) ; DBG_LED_OFF; for (w = DLED_ONTIME / 2; w; w--) ; n--; } } for (w = DLED_PAUSE; w; w--) ; t--; } if (long_pause) { for (w = DLED_PAUSE * 4; w; w--) ; } } #ifdef DEBUG_BOOT_TRACING_ENABLE volatile uint32_t debug_code; // These macros are for compile time substitution # define DEBUG_BOOT_TRACING_EXTINTn (DEBUG_BOOT_TRACING_PIN % _U_(0x10)) # define DEBUG_BOOT_TRACING_EXTINTb (_U_(0x1) << DEBUG_BOOT_TRACING_EXTINTn) # define DEBUG_BOOT_TRACING_CONFIG_INDn (DEBUG_BOOT_TRACING_EXTINTn / _U_(0x8)) # define DEBUG_BOOT_TRACING_CONFIG_SENSEn (DEBUG_BOOT_TRACING_EXTINTn % _U_(0x8)) # define DEBUG_BOOT_TRACING_CONFIG_SENSEb (DEBUG_BOOT_TRACING_CONFIG_SENSEn * _U_(0x4)) # define DEBUG_BOOT_TRACING_IRQn (EIC_0_IRQn + DEBUG_BOOT_TRACING_EXTINTn) // These macros perform PORT+PIN definition translation to IRQn in the preprocessor # define PORTPIN_TO_IRQn_EXPAND(def) def # define PORTPIN_TO_IRQn_DEF(def) PORTPIN_TO_IRQn_EXPAND(def) # if DEBUG_BOOT_TRACING_PIN < 10 # define PORTPIN_TO_IRQn_TODEF(port, pin) PORTPIN_TO_IRQn_DEF(PIN_##port##0##pin##A_EIC_EXTINT_NUM) # else # define PORTPIN_TO_IRQn_TODEF(port, pin) PORTPIN_TO_IRQn_DEF(PIN_##port##pin##A_EIC_EXTINT_NUM) # endif # define PORTPIN_TO_IRQn(port, pin) PORTPIN_TO_IRQn_TODEF(port, pin) // These macros perform function name output in the preprocessor # define DEBUG_BOOT_TRACING_HANDLER_CONCAT(irq) void EIC_##irq##_Handler(void) # define DEBUG_BOOT_TRACING_HANDLER(irq) DEBUG_BOOT_TRACING_HANDLER_CONCAT(irq) // To generate the function name of the IRQ handler catching boot tracing, // certain macros must be undefined, so save their current values to macro stack # pragma push_macro("PA") # pragma push_macro("PB") # pragma push_macro("_L_") // Undefine / redefine pushed macros # undef PA # undef PB # undef _L_ # define _L_(x) x // Perform the work and output // Ex: PORT PB, PIN 31 = void EIC_15_Handler(void) DEBUG_BOOT_TRACING_HANDLER(PORTPIN_TO_IRQn(DEBUG_BOOT_TRACING_PORT, DEBUG_BOOT_TRACING_PIN)) // Restore macros # pragma pop_macro("PA") # pragma pop_macro("PB") # pragma pop_macro("_L_") { // This is only for non-functional keyboard troubleshooting and should be disabled after boot // Intention is to lock up the keyboard here with repeating debug led code while (1) { dled_print(debug_code, 1); } } void debug_code_init(void) { DBGC(DC_UNSET); // Configure Ports for EIC PORT->Group[DEBUG_BOOT_TRACING_PORT].DIRCLR.reg = 1 << DEBUG_BOOT_TRACING_PIN; // Input PORT->Group[DEBUG_BOOT_TRACING_PORT].OUTSET.reg = 1 << DEBUG_BOOT_TRACING_PIN; // High PORT->Group[DEBUG_BOOT_TRACING_PORT].PINCFG[DEBUG_BOOT_TRACING_PIN].bit.INEN = 1; // Input Enable PORT->Group[DEBUG_BOOT_TRACING_PORT].PINCFG[DEBUG_BOOT_TRACING_PIN].bit.PULLEN = 1; // Pull Enable PORT->Group[DEBUG_BOOT_TRACING_PORT].PINCFG[DEBUG_BOOT_TRACING_PIN].bit.PMUXEN = 1; // Mux Enable PORT->Group[DEBUG_BOOT_TRACING_PORT].PMUX[DEBUG_BOOT_TRACING_PIN / 2].bit.PMUXO = 0; // Mux A // Enable CLK_EIC_APB MCLK->APBAMASK.bit.EIC_ = 1; // Configure EIC EIC->CTRLA.bit.SWRST = 1; while (EIC->SYNCBUSY.bit.SWRST) { } EIC->ASYNCH.reg = DEBUG_BOOT_TRACING_EXTINTb; EIC->INTENSET.reg = DEBUG_BOOT_TRACING_EXTINTb; EIC->CONFIG[DEBUG_BOOT_TRACING_CONFIG_INDn].reg |= (EIC_CONFIG_SENSE0_FALL_Val << DEBUG_BOOT_TRACING_CONFIG_SENSEb); EIC->CTRLA.bit.ENABLE = 1; while (EIC->SYNCBUSY.bit.ENABLE) { } // Enable EIC IRQ NVIC_EnableIRQ(DEBUG_BOOT_TRACING_IRQn); } void debug_code_disable(void) { // Disable EIC IRQ NVIC_DisableIRQ(DEBUG_BOOT_TRACING_IRQn); // Disable EIC EIC->CTRLA.bit.ENABLE = 0; while (EIC->SYNCBUSY.bit.ENABLE) { } // Default port configuration PORT->Group[DEBUG_BOOT_TRACING_PORT].DIRCLR.reg = 1 << DEBUG_BOOT_TRACING_PIN; // Input PORT->Group[DEBUG_BOOT_TRACING_PORT].OUTCLR.reg = 1 << DEBUG_BOOT_TRACING_PIN; // Low PORT->Group[DEBUG_BOOT_TRACING_PORT].PINCFG[DEBUG_BOOT_TRACING_PIN].bit.INEN = 0; // Input Disable PORT->Group[DEBUG_BOOT_TRACING_PORT].PINCFG[DEBUG_BOOT_TRACING_PIN].bit.PULLEN = 0; // Pull Disable PORT->Group[DEBUG_BOOT_TRACING_PORT].PINCFG[DEBUG_BOOT_TRACING_PIN].bit.PMUXEN = 0; // Mux Disable PORT->Group[DEBUG_BOOT_TRACING_PORT].PMUX[DEBUG_BOOT_TRACING_PIN / 2].bit.PMUXO = 0; // Mux A // Disable CLK_EIC_APB MCLK->APBAMASK.bit.EIC_ = 0; } #else void debug_code_init(void) {} void debug_code_disable(void) {} #endif // DEBUG_BOOT_TRACING_ENABLE