📄 hal_diag.c
字号:
init_serial_channel(&channels[1]);
// Setup procs in the vector table
// Set channel 0
CYGACC_CALL_IF_SET_CONSOLE_COMM(0);
comm = CYGACC_CALL_IF_CONSOLE_PROCS();
CYGACC_COMM_IF_CH_DATA_SET(*comm, &channels[0]);
CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write);
CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_read);
CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_putc);
CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_serial_getc);
CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_serial_control);
CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_serial_isr);
CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_serial_getc_timeout);
// Set channel 1
CYGACC_CALL_IF_SET_CONSOLE_COMM(1);
comm = CYGACC_CALL_IF_CONSOLE_PROCS();
CYGACC_COMM_IF_CH_DATA_SET(*comm, &channels[1]);
CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_serial_write);
CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_serial_read);
CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_serial_putc);
CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_serial_getc);
CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_serial_control);
CYGACC_COMM_IF_DBG_ISR_SET(*comm, cyg_hal_plf_serial_isr);
CYGACC_COMM_IF_GETC_TIMEOUT_SET(*comm, cyg_hal_plf_serial_getc_timeout);
// Restore original console
CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
}
//=============================================================================
// LCD driver
//=============================================================================
// The LCD driver is only used by the new vector code. Cannot be used
// by the old compatibility cruft.
// FEMA 162B 16 character x 2 line LCD
// base addresses and register offsets *
#define MBD_BASE 0
#define LCD_BASE (MBD_BASE + 0xEB00007)
#define LCD_DATA 0x00 // read/write lcd data
#define LCD_STAT 0x08 // read lcd busy status
#define LCD_CMD 0x08 // write lcd command
// status register bit definitions
#define LCD_STAT_BUSY 0x80 // 1 = display busy
#define LCD_STAT_ADD 0x7F // bits 0-6 return current display address
// command register definitions
#define LCD_CMD_RST 0x01 // clear entire display and reset display address
#define LCD_CMD_HOME 0x02 // reset display address and reset any shifting
#define LCD_CMD_ECL 0x04 // move cursor left one position on next data write
#define LCD_CMD_ESL 0x05 // shift display left one position on next data write
#define LCD_CMD_ECR 0x06 // move cursor right one position on next data write
#define LCD_CMD_ESR 0x07 // shift display right one position on next data write
#define LCD_CMD_DOFF 0x08 // display off, cursor off, blinking off
#define LCD_CMD_BL 0x09 // blink character at current cursor position
#define LCD_CMD_CUR 0x0A // enable cursor on
#define LCD_CMD_DON 0x0C // turn display on
#define LCD_CMD_CL 0x10 // move cursor left one position
#define LCD_CMD_SL 0x14 // shift display left one position
#define LCD_CMD_CR 0x18 // move cursor right one position
#define LCD_CMD_SR 0x1C // shift display right one position
#define LCD_CMD_MODE 0x38 // sets 8 bits, 2 lines, 5x7 characters
#define LCD_CMD_ACG 0x40 // bits 0-5 sets the character generator address
#define LCD_CMD_ADD 0x80 // bits 0-6 sets the display data address to line 1 +
// LCD status values
#define LCD_OK 0x00
#define LCD_ERR 0x01
#define LCD_LINE0 0x00
#define LCD_LINE1 0x40
#define LCD_LINE_LENGTH 16
static char lcd_line0[LCD_LINE_LENGTH+1];
static char lcd_line1[LCD_LINE_LENGTH+1];
static char *lcd_line[2] = { lcd_line0, lcd_line1 };
static int lcd_curline = 0;
static int lcd_linepos = 0;
static void lcd_dis(int add, char *s, cyg_uint8* base);
static void
init_lcd_channel(cyg_uint8* base)
{
cyg_uint8 stat;
int i;
// wait for not busy
// Note: It seems that the LCD isn't quite ready to process commands
// when it clears the BUSY flag. Reading the status address an extra
// time seems to give it enough breathing room.
do { HAL_READ_UINT8(base+LCD_STAT, stat); } while (stat & LCD_STAT_BUSY);
HAL_READ_UINT8(base+LCD_STAT, stat);
// configure the lcd for 8 bits/char, 2 lines
// and 5x7 dot matrix
HAL_WRITE_UINT8(base+LCD_CMD, LCD_CMD_MODE);
// wait for not busy
do { HAL_READ_UINT8(base+LCD_STAT, stat); } while (stat & LCD_STAT_BUSY);
HAL_READ_UINT8(base+LCD_STAT, stat);
// turn the LCD display on
HAL_WRITE_UINT8(base+LCD_CMD, LCD_CMD_DON);
lcd_curline = 0;
lcd_linepos = 0;
for( i = 0; i < LCD_LINE_LENGTH; i++ )
lcd_line[0][i] = lcd_line[1][i] = ' ';
lcd_line[0][LCD_LINE_LENGTH] = lcd_line[1][LCD_LINE_LENGTH] = 0;
lcd_dis(LCD_LINE0, lcd_line[0], base);
lcd_dis(LCD_LINE1, lcd_line[1], base);
}
// this routine writes the string to the LCD
// display after setting the address to add
static void
lcd_dis(int add, char *s, cyg_uint8* base)
{
cyg_uint8 stat;
int i;
// wait for not busy (see Note in hal_diag_init above)
do { HAL_READ_UINT8(base+LCD_STAT, stat); } while (stat & LCD_STAT_BUSY);
HAL_READ_UINT8(base+LCD_STAT, stat);
// write the address
HAL_WRITE_UINT8(base+LCD_CMD, (LCD_CMD_ADD + add));
// write the string out to the display stopping when we reach 0
for (i = 0; *s != '\0'; i++)
{
// wait for not busy
do { HAL_READ_UINT8(base+LCD_STAT, stat); } while (stat & LCD_STAT_BUSY);
HAL_READ_UINT8(base+LCD_STAT, stat);
// write the data
HAL_WRITE_UINT8(base+LCD_DATA, *s++);
}
}
void
cyg_hal_plf_lcd_putc(void* __ch_data, cyg_uint8 c)
{
cyg_uint8* base = (cyg_uint8*)__ch_data;
unsigned long __state;
int i;
CYGARC_HAL_SAVE_GP();
// ignore CR
if( c == '\r' ) return;
HAL_DISABLE_INTERRUPTS(__state);
if( c == '\n' )
{
lcd_dis(LCD_LINE0, &lcd_line[lcd_curline^1][0], base);
lcd_dis(LCD_LINE1, &lcd_line[lcd_curline][0], base);
// Do a line feed
lcd_curline ^= 1;
lcd_linepos = 0;
for( i = 0; i < LCD_LINE_LENGTH; i++ )
lcd_line[lcd_curline][i] = ' ';
HAL_RESTORE_INTERRUPTS(__state);
return;
}
// Only allow to be output if there is room on the LCD line
if( lcd_linepos < LCD_LINE_LENGTH )
lcd_line[lcd_curline][lcd_linepos++] = c;
HAL_RESTORE_INTERRUPTS(__state);
}
cyg_uint8
cyg_hal_plf_lcd_getc(void* __ch_data)
{
return 0;
}
static void
cyg_hal_plf_lcd_write(void* __ch_data, const cyg_uint8* __buf,
cyg_uint32 __len)
{
CYGARC_HAL_SAVE_GP();
while(__len-- > 0)
cyg_hal_plf_lcd_putc(__ch_data, *__buf++);
CYGARC_HAL_RESTORE_GP();
}
static void
cyg_hal_plf_lcd_read(void* __ch_data, cyg_uint8* __buf, cyg_uint32 __len)
{
CYGARC_HAL_SAVE_GP();
while(__len-- > 0)
*__buf++ = cyg_hal_plf_lcd_getc(__ch_data);
CYGARC_HAL_RESTORE_GP();
}
static int
cyg_hal_plf_lcd_control(void *__ch_data, __comm_control_cmd_t __func, ...)
{
// Do nothing (yet).
return 0;
}
static void
cyg_hal_plf_lcd_init(void)
{
hal_virtual_comm_table_t* comm;
int cur = CYGACC_CALL_IF_SET_CONSOLE_COMM(CYGNUM_CALL_IF_SET_COMM_ID_QUERY_CURRENT);
// Init channel
init_lcd_channel((cyg_uint8*)LCD_BASE);
// Setup procs in the vector table
// Set channel 2
CYGACC_CALL_IF_SET_CONSOLE_COMM(2);
comm = CYGACC_CALL_IF_CONSOLE_PROCS();
CYGACC_COMM_IF_CH_DATA_SET(*comm, LCD_BASE);
CYGACC_COMM_IF_WRITE_SET(*comm, cyg_hal_plf_lcd_write);
CYGACC_COMM_IF_READ_SET(*comm, cyg_hal_plf_lcd_read);
CYGACC_COMM_IF_PUTC_SET(*comm, cyg_hal_plf_lcd_putc);
CYGACC_COMM_IF_GETC_SET(*comm, cyg_hal_plf_lcd_getc);
CYGACC_COMM_IF_CONTROL_SET(*comm, cyg_hal_plf_lcd_control);
// Restore original console
CYGACC_CALL_IF_SET_CONSOLE_COMM(cur);
}
//=============================================================================
// Compatibility with older stubs
//=============================================================================
#ifndef CYGSEM_HAL_VIRTUAL_VECTOR_DIAG
#if defined(CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS)
#include <cyg/hal/hal_stub.h> // CYG_HAL_GDB_ENTER_CRITICAL_IO_REGION
#endif
//-----------------------------------------------------------------------------
// Assumption: all diagnostic output must be GDB packetized unless
// this is a configuration for a stand-alone ROM system.
#if defined(CYG_HAL_STARTUP_ROM) && !defined(CYGSEM_HAL_ROM_MONITOR)
# define HAL_DIAG_USES_HARDWARE
#endif
#if (CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL == 0)
# define __BASE ((cyg_uint8*)CYG_DEV_SERIAL_BASE_A)
#elif (CYGNUM_HAL_VIRTUAL_VECTOR_CONSOLE_CHANNEL == 1)
# define __BASE ((cyg_uint8*)CYG_DEV_SERIAL_BASE_B)
#else
# error "Cannot use LCD"
#endif
static channel_data_t channel = { __BASE, 0, 0};
#ifdef HAL_DIAG_USES_HARDWARE
void hal_diag_init(void)
{
init_serial_channel(&channel);
}
void hal_diag_write_char(char __c)
{
cyg_hal_plf_serial_putc(&channel, __c);
}
void hal_diag_read_char(char *c)
{
*c = cyg_hal_plf_serial_getc(&channel);
}
#else // ifdef HAL_DIAG_USES_HARDWARE
// Initialize diag port
void
hal_diag_init(void)
{
// Init devices
init_serial_channel(&channel);
}
void
hal_diag_write_char_serial( char c )
{
unsigned long __state;
HAL_DISABLE_INTERRUPTS(__state);
cyg_hal_plf_serial_putc(&channel, c);
HAL_RESTORE_INTERRUPTS(__state);
}
void
hal_diag_read_char(char *c)
{
*c = cyg_hal_plf_serial_getc(&channel);
}
void
hal_diag_write_char(char c)
{
static char line[100];
static int pos = 0;
// No need to send CRs
if( c == '\r' ) return;
line[pos++] = c;
if( c == '\n' || pos == sizeof(line) )
{
CYG_INTERRUPT_STATE old;
// 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.
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
CYG_HAL_GDB_ENTER_CRITICAL_IO_REGION(old);
#else
HAL_DISABLE_INTERRUPTS(old);
#endif
while(1)
{
char c1;
static char hex[] = "0123456789ABCDEF";
cyg_uint8 csum = 0;
int i;
hal_diag_write_char_serial('$');
hal_diag_write_char_serial('O');
csum += 'O';
for( i = 0; i < pos; i++ )
{
char ch = line[i];
char h = hex[(ch>>4)&0xF];
char l = hex[ch&0xF];
hal_diag_write_char_serial(h);
hal_diag_write_char_serial(l);
csum += h;
csum += l;
}
hal_diag_write_char_serial('#');
hal_diag_write_char_serial(hex[(csum>>4)&0xF]);
hal_diag_write_char_serial(hex[csum&0xF]);
// Wait for the ACK character '+' from GDB here and handle
// receiving a ^C instead.
hal_diag_read_char(&c1);
if( c1 == '+' )
break; // a good acknowledge
#ifdef CYGDBG_HAL_DEBUG_GDB_BREAK_SUPPORT
if( 3 == c1 ) {
// Ctrl-C: breakpoint.
cyg_hal_gdb_interrupt(
(target_register_t)__builtin_return_address(0));
break;
}
#endif
// otherwise, loop round again
}
pos = 0;
// And re-enable interrupts
#ifdef CYGDBG_HAL_DEBUG_GDB_INCLUDE_STUBS
CYG_HAL_GDB_LEAVE_CRITICAL_IO_REGION(old);
#else
HAL_RESTORE_INTERRUPTS(old);
#endif
}
}
#endif // ifdef HAL_DIAG_USES_HARDWARE
#endif // CYGSEM_HAL_VIRTUAL_VECTOR_DIAG
//-----------------------------------------------------------------------------
// End of hal_diag.c
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -