// Use this function to disable serial interrupts whenever reply // characters are expected from GDB. The reason we want to control // whether the target can be interrupted or not is simply that GDB on // the host will be sending acknowledge characters/commands while the // stub is running - if serial interrupts were still active, the // characters would never reach the (polling) getDebugChar. static void interruptible(int state) { static int __interrupts_suspended = 0; if (state) { __interrupts_suspended--; if (0 >= __interrupts_suspended) { __interrupts_suspended = 0; #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT // this _check_ should go away { hal_virtual_comm_table_t* __chan; __chan = CYGACC_CALL_IF_DEBUG_PROCS(); CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_IRQ_ENABLE); } #else if (__interruptible_control) __interruptible_control(1); #endif } } else { __interrupts_suspended++; if (1 == __interrupts_suspended) #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT // this _check_ should go away { hal_virtual_comm_table_t* __chan; __chan = CYGACC_CALL_IF_DEBUG_PROCS(); CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_IRQ_DISABLE); } #else if (__interruptible_control) __interruptible_control(0); #endif } }
static int set_debug_comm(int __comm_id) { static int __selected_id = CYGNUM_CALL_IF_SET_COMM_ID_EMPTY; hal_virtual_comm_table_t* __chan; int interrupt_state = 0; int res = 1, update = 0; CYGARC_HAL_SAVE_GP(); CYG_ASSERT(__comm_id >= CYGNUM_CALL_IF_SET_COMM_ID_MANGLER && __comm_id < CYGNUM_HAL_VIRTUAL_VECTOR_NUM_CHANNELS, "Invalid channel"); switch (__comm_id) { case CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT: if (__selected_id > 0) res = __selected_id-1; else if (__selected_id == 0) res = CYGNUM_CALL_IF_SET_COMM_ID_MANGLER; else res = __selected_id; break; case CYGNUM_CALL_IF_SET_COMM_ID_EMPTY: CYGACC_CALL_IF_DEBUG_PROCS_SET(0); __selected_id = __comm_id; break; case CYGNUM_CALL_IF_SET_COMM_ID_MANGLER: __comm_id = 0; update = 1; break; default: __comm_id++; // skip mangler entry update = 1; break; } if (update) { // Find the interrupt state of the channel. __chan = CYGACC_CALL_IF_DEBUG_PROCS(); if (__chan) interrupt_state = CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_IRQ_DISABLE); __selected_id = __comm_id; CYGACC_CALL_IF_DEBUG_PROCS_SET(comm_channels[__comm_id]); // Set interrupt state on the new channel. __chan = CYGACC_CALL_IF_DEBUG_PROCS(); if (interrupt_state) CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_IRQ_ENABLE); else CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_IRQ_DISABLE); } CYGARC_HAL_RESTORE_GP(); return res; }
void mon_set_read_char_timeout(int ms) { hal_virtual_comm_table_t *__chan; #ifdef CYGPKG_REDBOOT_ANY_CONSOLE if (!console_selected) { int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT); int i; // Set timeout to minimum on each channel; total amounts to desired value _mon_timeout = ms; ms = 1; for (i = 0; i < CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS; i++) { CYGACC_CALL_IF_SET_CONSOLE_COMM(i); if ((__chan = CYGACC_CALL_IF_CONSOLE_PROCS()) != 0) { CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_SET_TIMEOUT, ms); } } CYGACC_CALL_IF_SET_CONSOLE_COMM(cur); } else #endif { if ((__chan = CYGACC_CALL_IF_CONSOLE_PROCS()) != 0) { CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_SET_TIMEOUT, ms); } if ((__chan = CYGACC_CALL_IF_DEBUG_PROCS()) != 0) { CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_SET_TIMEOUT, ms); } } }
void hal_if_diag_write_char(char c) { hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_CONSOLE_PROCS(); if (__chan) CYGACC_COMM_IF_PUTC(*__chan, c); else { __chan = CYGACC_CALL_IF_DEBUG_PROCS(); // FIXME: What should be done if assertions are not enabled? // This is a bad bad situation - we have no means for diag // output; we want to hit a breakpoint to alert the developer // or something like that. CYG_ASSERT(__chan, "No valid channel set"); CYGACC_COMM_IF_PUTC(*__chan, c); } // Check interrupt flag if (CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG()) { CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG_SET(0); cyg_hal_user_break(0); } }
void mon_write_char(unsigned char c) { hal_virtual_comm_table_t *__chan; #ifdef CYGPKG_REDBOOT_ANY_CONSOLE if (!console_selected) { int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT); int i; // Send output to all channels for (i = 0; i < CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS; i++) { CYGACC_CALL_IF_SET_CONSOLE_COMM(i); __chan = CYGACC_CALL_IF_CONSOLE_PROCS(); CYGACC_COMM_IF_PUTC(*__chan, c); } CYGACC_CALL_IF_SET_CONSOLE_COMM(cur); } else #endif { __chan = CYGACC_CALL_IF_CONSOLE_PROCS(); if (__chan) CYGACC_COMM_IF_PUTC(*__chan, c); else { __chan = CYGACC_CALL_IF_DEBUG_PROCS(); CYGACC_COMM_IF_PUTC(*__chan, c); } } }
void hal_ctrlc_isr_init(void) { // A ROM monitor never enables the interrupt itself. This is left // to the (RAM) application. #ifndef CYGSEM_HAL_ROM_MONITOR hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS(); #if 1 // Prevents crash on older stubs int v_m; // Allow only ctrl-c interrupt enabling when version in table is // below legal max and above the necessary service, and _not_ // the value we set it to below. v_m = CYGACC_CALL_IF_VERSION() & CYGNUM_CALL_IF_TABLE_VERSION_CALL_MASK; if (v_m >= CYGNUM_CALL_IF_TABLE_VERSION_CALL_MAX || v_m < CYGNUM_CALL_IF_SET_DEBUG_COMM || v_m == CYGNUM_CALL_IF_TABLE_VERSION_CALL_HACK) return; // Now trash that value - otherwise downloading an image with // builtin stubs on a board with older stubs (which will cause the // version to be set to VERSION_CALL) may cause all subsequent // runs to (wrongly) fall through to the below code. If there is // a new stub on the board, it will reinitialize the version field // on reset. Yes, this is a gross hack! CYGACC_CALL_IF_VERSION_SET(CYGNUM_CALL_IF_TABLE_VERSION_CALL_HACK); #endif // We can only enable interrupts on a valid debug channel. if (__chan) CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_IRQ_ENABLE); #endif }
// Flush output channel void hal_flush_output(void) { #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT __call_if_debug_procs_t __debug_procs = CYGACC_CALL_IF_DEBUG_PROCS(); CYGACC_COMM_IF_CONTROL(*__debug_procs, __COMMCTL_FLUSH_OUTPUT); #endif }
static inline void __flush(void) { hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_CONSOLE_PROCS(); if (__chan == NULL) __chan = CYGACC_CALL_IF_DEBUG_PROCS(); CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_FLUSH_OUTPUT); }
static inline void __putc(char c) { hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_CONSOLE_PROCS(); if (__chan) CYGACC_COMM_IF_PUTC(*__chan, c); else { __chan = CYGACC_CALL_IF_DEBUG_PROCS(); CYGACC_COMM_IF_PUTC(*__chan, c); } }
static void cyg_hal_diag_mangler_null_putc(void* __ch_data, cyg_uint8 c) { hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS(); CYGARC_HAL_SAVE_GP(); CYGACC_COMM_IF_PUTC(*__chan, c); CYGARC_HAL_RESTORE_GP(); }
// Set the baud rate for the current serial port. void __set_baud_rate (int baud) { #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT __call_if_debug_procs_t __debug_procs = CYGACC_CALL_IF_DEBUG_PROCS(); CYGACC_COMM_IF_CONTROL(*__debug_procs, __COMMCTL_SETBAUD, baud); #elif defined(CYGPKG_CYGMON) // FIXME! #else HAL_STUB_PLATFORM_SET_BAUD_RATE(baud); #endif }
// Read one character from the current serial port. int getDebugChar (void) { #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT __call_if_debug_procs_t __debug_procs = CYGACC_CALL_IF_DEBUG_PROCS(); return CYGACC_COMM_IF_GETC(*__debug_procs); #elif defined(CYGPKG_CYGMON) return ecos_bsp_console_getc(); #else return HAL_STUB_PLATFORM_GET_CHAR(); #endif }
// Write C to the current serial port. void putDebugChar (int c) { #ifdef CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT __call_if_debug_procs_t __debug_procs = CYGACC_CALL_IF_DEBUG_PROCS(); CYGACC_COMM_IF_PUTC(*__debug_procs, c); #elif defined(CYGPKG_CYGMON) ecos_bsp_console_putc(c); #else HAL_STUB_PLATFORM_PUT_CHAR(c); #endif }
static void mon_read_char(unsigned char *c) { hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_CONSOLE_PROCS(); if (__chan) *c = CYGACC_COMM_IF_GETC(*__chan); else { __chan = CYGACC_CALL_IF_DEBUG_PROCS(); *c = CYGACC_COMM_IF_GETC(*__chan); } }
static inline char __getc(void) { char c; hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_CONSOLE_PROCS(); if (__chan) c = CYGACC_COMM_IF_GETC(*__chan); else { __chan = CYGACC_CALL_IF_DEBUG_PROCS(); c = CYGACC_COMM_IF_GETC(*__chan); } return c; }
// This gets called via the virtual vector console comms entry and // just forwards IO to the debug comms entries. // This differs from setting the console channel to the same as the // debug channel in that console output will go to the debug channel // even if the debug channel is changed. static cyg_uint8 cyg_hal_diag_mangler_null_getc(void* __ch_data) { cyg_uint8 __ch; hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS(); CYGARC_HAL_SAVE_GP(); __ch = CYGACC_COMM_IF_GETC(*__chan); CYGARC_HAL_RESTORE_GP(); return __ch; }
char xgetchar(void) { char ch; hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_CONSOLE_PROCS(); if (__chan) ch = CYGACC_COMM_IF_GETC(*__chan); else { __chan = CYGACC_CALL_IF_DEBUG_PROCS(); ch = CYGACC_COMM_IF_GETC(*__chan); } return ch; }
cyg_uint32 hal_ctrlc_isr(CYG_ADDRWORD vector, CYG_ADDRWORD data) { hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS(); int isr_ret = 0, ctrlc = 0; if (__chan) { isr_ret = CYGACC_COMM_IF_DBG_ISR(*__chan, &ctrlc, vector, data); if (ctrlc) cyg_hal_user_break( (CYG_ADDRWORD *)hal_saved_interrupt_state ); } return isr_ret; }
bool mon_read_char_with_timeout(unsigned char *c) { bool res = false; hal_virtual_comm_table_t *__chan; #ifdef CYGPKG_REDBOOT_ANY_CONSOLE if (!console_selected) { int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT); int i, j, tot; // Try input from all channels tot = 0; while (tot < _mon_timeout) { for (i = 0; i < CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS; i++, tot++) { CYGACC_CALL_IF_SET_CONSOLE_COMM(i); __chan = CYGACC_CALL_IF_CONSOLE_PROCS(); res = CYGACC_COMM_IF_GETC_TIMEOUT(*__chan, c); if (res) { // Input available on this channel, make it be the console if (*c != '\0') { // Don't chose this unless real data have arrived console_selected = true; CYGACC_CALL_IF_SET_DEBUG_COMM(i); // Disable interrupts on all channels but this one for (j = 0; j < CYGNUM_HAL_VIRTUAL_VECTOR_COMM_CHANNELS; j++) { if (i != j) { CYGACC_CALL_IF_SET_CONSOLE_COMM(j); __chan = CYGACC_CALL_IF_CONSOLE_PROCS(); CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_IRQ_DISABLE); } } CYGACC_CALL_IF_SET_CONSOLE_COMM(i); return res; } } } } CYGACC_CALL_IF_SET_CONSOLE_COMM(cur); } else #endif { __chan = CYGACC_CALL_IF_CONSOLE_PROCS(); if (__chan) res = CYGACC_COMM_IF_GETC_TIMEOUT(*__chan, c); else { __chan = CYGACC_CALL_IF_DEBUG_PROCS(); res = CYGACC_COMM_IF_GETC_TIMEOUT(*__chan, c); } } return res; }
cyg_uint32 hal_default_isr(CYG_ADDRWORD vector, CYG_ADDRWORD data) { cyg_uint32 result; #if (defined(CYGDBG_HAL_DEBUG_GDB_CTRLC_SUPPORT) \ || defined(CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT)) && \ (defined(CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT) || \ defined(CYGHWR_HAL_GDB_PORT_VECTOR) && \ defined(HAL_CTRLC_ISR)) #ifndef CYGIMP_HAL_COMMON_INTERRUPTS_CHAIN #if CYGSEM_HAL_VIRTUAL_VECTOR_SUPPORT int gdb_vector = -1; // This check only to avoid crash on older stubs in case of unhandled // interrupts. It is a bit messy, but required in a transition period. #ifndef CYGSEM_HAL_ROM_MONITOR if (CYGNUM_CALL_IF_TABLE_VERSION_CALL_HACK == (CYGACC_CALL_IF_VERSION() & CYGNUM_CALL_IF_TABLE_VERSION_CALL_MASK)) #endif { hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS(); if (__chan) gdb_vector = CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_DBG_ISR_VECTOR); } if( CYGHWR_HAL_GDB_PORT_VECTORS_MATCH(vector, gdb_vector) ) #else // Old code using hardwired channels. This should go away eventually. if( vector == CYGHWR_HAL_GDB_PORT_VECTOR ) #endif #endif { result = HAL_CTRLC_ISR( vector, data ); if( 0 != result ) return result; } #endif result = hal_arch_default_isr (vector, data); if( 0 != result) return result; CYG_TRACE2(true, "Interrupt: %d, Data: 0x%08x", vector, data); CYG_FAIL("Spurious Interrupt!!!"); return 0; }
void hal_if_diag_read_char(char *c) { hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_CONSOLE_PROCS(); if (__chan) *c = CYGACC_COMM_IF_GETC(*__chan); else { __chan = CYGACC_CALL_IF_DEBUG_PROCS(); // FIXME: What should be done if assertions are not enabled? // This is a bad bad situation - we have no means for diag // output; we want to hit a breakpoint to alert the developer // or something like that. CYG_ASSERT(__chan, "No valid channel set"); *c = CYGACC_COMM_IF_GETC(*__chan); } }
cyg_bool hal_ctrlc_check(CYG_ADDRWORD vector, CYG_ADDRWORD data) { hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS(); int gdb_vector = vector-1; int isr_ret, ctrlc = 0; // This check only to avoid crash on older stubs in case of unhandled // interrupts. It is a bit messy, but required in a transition period. if (__chan && (CYGNUM_CALL_IF_TABLE_VERSION_CALL_HACK == (CYGACC_CALL_IF_VERSION() & CYGNUM_CALL_IF_TABLE_VERSION_CALL_MASK))){ gdb_vector = CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_DBG_ISR_VECTOR); } if (vector == gdb_vector) { isr_ret = CYGACC_COMM_IF_DBG_ISR(*__chan, &ctrlc, vector, data); if (ctrlc) { cyg_hal_user_break( (CYG_ADDRWORD *)hal_saved_interrupt_state ); return true; } } return false; }
static void cyg_hal_diag_mangler_gdb_flush(void* __ch_data) { CYG_INTERRUPT_STATE old; hal_virtual_comm_table_t* __chan = CYGACC_CALL_IF_DEBUG_PROCS(); #if CYGNUM_HAL_DEBUG_GDB_PROTOCOL_RETRIES != 0 int tries = CYGNUM_HAL_DEBUG_GDB_PROTOCOL_RETRIES; #endif // Nothing to do if mangler buffer is empty. if (__mangler_pos == 0) return; // Disable interrupts. This prevents GDB trying to interrupt us // while we are in the middle of sending a packet. The serial // receive interrupt will be seen when we re-enable interrupts // later. #if defined(CYG_HAL_STARTUP_ROM) \ || !defined(CYG_HAL_GDB_ENTER_CRITICAL_IO_REGION) HAL_DISABLE_INTERRUPTS(old); #else CYG_HAL_GDB_ENTER_CRITICAL_IO_REGION(old); #endif #if CYGNUM_HAL_DEBUG_GDB_PROTOCOL_RETRIES != 0 // Only wait 500ms for data to arrive - avoid "stuck" connections CYGACC_COMM_IF_CONTROL(*__chan, __COMMCTL_SET_TIMEOUT, CYGNUM_HAL_DEBUG_GDB_PROTOCOL_TIMEOUT); #endif while(1) { static const char hex[] = "0123456789ABCDEF"; cyg_uint8 csum = 0; char c1; int i; CYGACC_COMM_IF_PUTC(*__chan, '$'); CYGACC_COMM_IF_PUTC(*__chan, 'O'); csum += 'O'; for( i = 0; i < __mangler_pos; i++ ) { char ch = __mangler_line[i]; char h = hex[(ch>>4)&0xF]; char l = hex[ch&0xF]; CYGACC_COMM_IF_PUTC(*__chan, h); CYGACC_COMM_IF_PUTC(*__chan, l); csum += h; csum += l; } CYGACC_COMM_IF_PUTC(*__chan, '#'); CYGACC_COMM_IF_PUTC(*__chan, hex[(csum>>4)&0xF]); CYGACC_COMM_IF_PUTC(*__chan, hex[csum&0xF]); nak: #if CYGNUM_HAL_DEBUG_GDB_PROTOCOL_RETRIES != 0 if (CYGACC_COMM_IF_GETC_TIMEOUT(*__chan, &c1) == 0) { c1 = '-'; if (tries && (--tries == 0)) c1 = '+'; } #else c1 = CYGACC_COMM_IF_GETC(*__chan); #endif if( c1 == '+' ) break; if( cyg_hal_is_break( &c1 , 1 ) ) { // Caller's responsibility to react on this. CYGACC_CALL_IF_CONSOLE_INTERRUPT_FLAG_SET(1); break; } if( c1 != '-' ) goto nak; } __mangler_pos = 0; // And re-enable interrupts #if defined(CYG_HAL_STARTUP_ROM) \ || !defined(CYG_HAL_GDB_ENTER_CRITICAL_IO_REGION) HAL_RESTORE_INTERRUPTS(old); #else CYG_HAL_GDB_LEAVE_CRITICAL_IO_REGION(old); #endif }