📄 debug_serial.c
字号:
/* -*-C-*- * * $Revision: $ * $Author: $ * $Date: $ * * Copyright (c) 1996 Advanced RISC Machines Limited. * All Rights Reserved. * * Project: ANGEL * * Title: Serial device driver for Integrator board *//* * Provide a single serial device. Since we're only providing a single * device we don't need to worry about device id's and idents. But these * could be used to provide for two or more devices via the one driver. */#include "angel.h"#include "devconf.h"#include "serial.h"#include "evaluator.h" /* header for this file */#include "devdriv.h" /* device driver support */#include "params.h" /* parameter structures and utilities */#include "rxtx.h" /* rx/tx packet engines */#include "logging.h"#include "serlock.h" /* serialisation, etc. */#include "serring.h" /* interface to high-level driver */#include "c501uart.h" /* chip definition struct & register bit values *//* General purpose constants, macros, enums, typedefs */#define DEFBAUD 9600 /* default baud rate *//* * forward declarations of necessary functions */static void c501uart_ControlTx(const DeviceID devid);static void c501uart_ControlRx(const unsigned int devid);static DevError c501uart_Control(DeviceID devid, DeviceControl op, void *arg);static void c501uart_KickStartFn(DeviceID devid);extern void delayloop(int ms);static unsigned int baud_options[] ={ 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 230400};static ParameterList param_list[] = { { AP_BAUD_RATE, sizeof(baud_options) / sizeof(baud_options[0]), baud_options }};/* * The default parameter config for the device */static Parameter param_default[] = { { AP_BAUD_RATE, 9600 }};/* the state shared between the Int. handler and the deferred processor */static RingBuffer c501uart_rx_ring[C501UART_NUM_PORTS];static RingBuffer c501uart_tx_ring[C501UART_NUM_PORTS];#if (HAVE_ANGEL_C501UART)/* * the configuration needed by the TX and RX engines */#define SERIAL_FC_SET ((1 << serial_XON) | (1 << serial_XOFF))#define SERIAL_CTL_SET ((1 << serial_STX) | (1 << serial_ETX) |\ (1 << serial_ESC))#define SERIAL_ESC_SET (SERIAL_FC_SET | SERIAL_CTL_SET)static const struct re_config engine_config[C501UART_NUM_PORTS] ={ { serial_STX, serial_ETX, serial_ESC, /* self-explanatory? */ SERIAL_FC_SET, /* set of flow-control characters */ SERIAL_ESC_SET, /* set of characters to be escaped */ serpkt_flow_control, (void *)DI_C501UART_B,/* what to do with FC chars */ angel_DD_RxEng_BufferAlloc, (void *)DI_C501UART_B /* how to get a buffer */ }#if (C501UART_NUM_PORTS > 1) ,{ serial_STX, serial_ETX, serial_ESC, /* self-explanatory? */ SERIAL_FC_SET, /* set of flow-control characters */ SERIAL_ESC_SET, /* set of characters to be escaped */ serpkt_flow_control, (void *)DI_C501UART_A,/* what to do with FC chars */ angel_DD_RxEng_BufferAlloc, (void *)DI_C501UART_A /* how to get a buffer */ }#endif};/* the state of the rx engine */static struct re_state rx_engine_state[C501UART_NUM_PORTS];/* the state of the tx engine */static struct te_state tx_engine_state[C501UART_NUM_PORTS];/* packet for actual rx in progress */static struct data_packet rx_packet[C501UART_NUM_PORTS];/* the current write packet */static struct data_packet tx_packet[C501UART_NUM_PORTS];/* the above, collected */static RxTxState c501uart_rx_tx_state[C501UART_NUM_PORTS] ={ { &engine_config[C501UART_IDENT_B], &rx_engine_state[C501UART_IDENT_B], &tx_engine_state[C501UART_IDENT_B], &rx_packet[C501UART_IDENT_B], &tx_packet[C501UART_IDENT_B], 1 /* rx_flow */ }#if (C501UART_NUM_PORTS > 1) ,{ &engine_config[C501UART_IDENT_A], &rx_engine_state[C501UART_IDENT_A], &tx_engine_state[C501UART_IDENT_A], &rx_packet[C501UART_IDENT_A], &tx_packet[C501UART_IDENT_A], 1 /* rx_flow */ }#endif};#endif /* HAVE_ANGEL_C501UART */#if (HAVE_RAW_C501UART)static RawState c501uart_raw_state[C501UART_NUM_PORTS];#endif/* * The control functions and interface */static const SerialControl c501uart_Ctrl[C501UART_NUM_PORTS] ={ {#if (RAW_C501UART_B == 0) &c501uart_rx_tx_state[C501UART_IDENT_B], NULL, serpkt_int_tx_processing, serpkt_int_rx_processing,#else NULL, &c501uart_raw_state[C501UART_IDENT_B], serraw_int_tx_processing, serraw_int_rx_processing,#endif C501UART_IDENT_B, &c501uart_tx_ring[C501UART_IDENT_B], &c501uart_rx_ring[C501UART_IDENT_B], c501uart_ControlTx, c501uart_ControlRx, c501uart_Control, c501uart_KickStartFn }#if C501UART_NUM_PORTS > 1 ,{#if (RAW_C501UART_A == 0) &c501uart_rx_tx_state[C501UART_IDENT_A], NULL, &packet_state[C501UART_IDENT_A], serpkt_int_tx_processing, serpkt_int_rx_processing,#else NULL, &c501uart_raw_state[C501UART_IDENT_A], NULL, serraw_int_tx_processing, serraw_int_rx_processing,#endif C501UART_IDENT_A, &c501uart_tx_ring[C501UART_IDENT_A], &c501uart_rx_ring[C501UART_IDENT_A], c501uart_ControlTx, c501uart_ControlRx, c501uart_Control, c501uart_KickStartFn }#endif};/* Publically-accessible globals *//* * The device table entry for this device */const struct angel_DeviceEntry angel_C501UARTSerial[C501UART_NUM_PORTS] ={ {#if (RAW_C501UART_B == 0) DT_ANGEL, { serpkt_AsyncWrite, serpkt_RegisterRead }, serpkt_Control,#else DT_RAW, { /* nasty but necessary casts, as can only statically initialise * the first member of a union */ (angel_DeviceWriteFn) serraw_Write, (angel_DeviceRegisterReadFn)serraw_Read }, serraw_Control,#endif &c501uart_Ctrl[C501UART_IDENT_B], { sizeof(param_list) / sizeof(param_list[0]), param_list }, { sizeof(param_default) / sizeof(param_default[0]), param_default } }#if C501UART_NUM_PORTS > 1 ,{#if (RAW_C501UART_A == 0) DT_ANGEL, { serpkt_AsyncWrite, serpkt_RegisterRead }, serpkt_Control,#else DT_RAW, { /* nasty but necessary casts, as can only statically initialise * the first member of a union */ (angel_DeviceWriteFn) serraw_Write, (angel_DeviceRegisterReadFn)serraw_Read }, serraw_Control,#endif &c501uart_Ctrl[C501UART_IDENT_A], { sizeof(param_list) / sizeof(param_list[0]), param_list }, { sizeof(param_default) / sizeof(param_default[0]), param_default } }#endif};/* what address? */#define c501uart_Address(port) ((port == C501UART_IDENT_B) ? \ (C501UARTReg *)EVALUATOR_UART1_BASE : (C501UARTReg *)EVALUATOR_UART0_BASE)/* which ring buffer? */#define c501uart_TxRingBuf(port) (&c501uart_tx_ring[port])#define c501uart_RxRingBuf(port) (&c501uart_rx_ring[port]) /*---------- Begin register trace */#define TRACE_START_ADDR (0x40000)#define TRACE_STOP_ADDR (0x50000)__inline void traceRegs( unsigned a, unsigned b ){ unsigned tmp1, tmp2, tmp3; __asm { mov tmp1, #TRACE_STOP_ADDR ldr tmp2, [tmp1] cmp tmp2, tmp1 movge tmp2, #TRACE_START_ADDR cmp tmp2, #TRACE_START_ADDR movlt tmp2, #TRACE_START_ADDR str pc, [tmp2], #+4 str lr, [tmp2], #+4 str sp, [tmp2], #+4 mrs tmp3, CPSR str tmp3, [tmp2], #+4 str a, [tmp2], #+4 str b, [tmp2], #+4 str b, [tmp2], #+4 str b, [tmp2], #+4 str tmp2, [tmp1] }} /* ---------------- end register trace *//* * Function: c501uart_KickStartFn * Purpose: Kick-start tx by sending first character * * Params: * Input: devid device ID of the driver * * Returns: Nothing */static void c501uart_KickStartFn(DeviceID devid){ char c; const unsigned int port = SerCtrl(devid)->port; C501UARTReg *const serchip = c501uart_Address(port); IGNORE(devid);/* LogInfo(LOG_SERIAL, ("Kickstart\n")); */ c = ringBufGetChar( c501uart_TxRingBuf(port) ); while ( !TX_READY(c501uart_GetStatus(serchip)) ) { ; } /* Yes, you may have been told to kickstart while already transmiting */ c501uart_SerPutChar(serchip, c); traceRegs( c, 0);}/* * enable async transmission if not already enabled * NB caller should ensure protection against interrupt */static void c501uart_ControlTx(DeviceID devid){ unsigned tx_status = angel_DeviceStatus[devid] & SER_TX_MASK; const unsigned int port = SerCtrl(devid)->port; /* * We enable tx whenever we want to send a flow control char, * OR when we are sending a packet and we have not been XOFF'ed */ if ((tx_status & SER_TX_FLOW_CONTROL) || (tx_status == SER_TX_DATA)) { /* tx interrupt should be enabled */ if ((angel_DeviceStatus[devid] & SER_TX_IRQ_EN) == 0) { /* LogInfo(LOG_SERIAL, ("Enable TX Interrupt\n")); */ angel_DeviceStatus[devid] |= SER_TX_IRQ_EN; EnableInterruptNum( DEBUG_COMPORT_TX_INT ); traceRegs(tx_status, (unsigned)angel_DeviceStatus[devid]); } } else { /* tx interrupt should be disabled */ if (angel_DeviceStatus[devid] & SER_TX_IRQ_EN) { /* LogInfo(LOG_SERIAL, ("Disable TX Interrupt\n")); */ DisableInterruptNum( DEBUG_COMPORT_TX_INT ); angel_DeviceStatus[devid] &= ~SER_TX_IRQ_EN; traceRegs(tx_status, (unsigned)angel_DeviceStatus[devid]); } }}/* * control rx interrupt mask according to flow control and read interest * NB caller should ensure protection against interrupt */static void c501uart_ControlRx(DeviceID devid){ const unsigned int port = SerCtrl(devid)->port; if ( ((angel_DeviceStatus[devid] & SER_RX_DISABLED) == 0) && ((angel_DeviceStatus[devid] & DEV_READ_BUSY_MASK) != 0) ) { /* rx interrupt should be enabled */ if ((angel_DeviceStatus[devid] & SER_RX_IRQ_EN) == 0 ) { angel_DeviceStatus[devid] |= SER_RX_IRQ_EN; EnableInterruptNum( DEBUG_COMPORT_RX_INT ); traceRegs((unsigned)angel_DeviceStatus[devid], 0); } } else { if ( (angel_DeviceStatus[devid] & SER_RX_DISABLED) != 0 ) { DisableInterruptNum( DEBUG_COMPORT_RX_INT ); if ( (angel_DeviceStatus[devid] & SER_RX_IRQ_EN) != 0 ) { angel_DeviceStatus[devid] &= ~SER_RX_IRQ_EN; } traceRegs((unsigned)angel_DeviceStatus[devid], 0); } }}/* * wait for tx to drain completely */static void serial_tx_drain(DeviceID devid){ const unsigned int port = SerCtrl(devid)->port; C501UARTReg *const serchip = c501uart_Address(port); RingBuffer *ring = c501uart_TxRingBuf(port); int c = 0; if (ringBufNotEmpty(ring)) { /* Wait for message to move over to UART */ while ( (angel_DeviceStatus[devid] & SER_TX_EOD) != 0 ) continue; } /* Now wait for UART to drain */ while ((c501uart_GetStatus(serchip) & USRTxEmpty) == 0) c++; if (c > 0) LogInfo(LOG_SERIAL, ("serial_tx_drain: waited %d\n", c)); }/* * Initialisation control operation */static DevError c501uart_init(DeviceID devid){ DevError err; /* * do one-time start-up initialisation * (for this device, just a device reset) */ Angel_ExitToUSR(); /* because DeviceControl requires it */ err = angel_DeviceControl(devid, DC_RESET, NULL); Angel_EnterSVC(); return err;}/* * Receive Mode control operation */static DevError c501uart_recv_mode(DeviceID devid, DevRecvMode mode){ DevError ret_code = DE_OKAY; if (mode == DR_DISABLE) { if (!(angel_DeviceStatus[devid] & SER_RX_DISABLED)) { /* disable reception and schedule send of XOFF */ angel_DeviceStatus[devid] |= (SER_RX_DISABLED | SER_TX_FLOW_CONTROL); c501uart_ControlRx(devid); c501uart_ControlTx(devid); } } else if (mode == DR_ENABLE) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -