📄 hal_uart.c
字号:
#if HAL_UART_0_ENABLE
if ( port == HAL_UART_PORT_0 )
{
// Only supporting 38400 or 115200 for code size - other is possible.
U0BAUD = (config->baudRate == HAL_UART_BR_38400) ? 59 : 216;
U0GCR = (config->baudRate == HAL_UART_BR_38400) ? 10 : 11;
U0CSR |= CSR_RE;
#if HAL_UART_DMA == 1
cfg->flag = UART_CFG_DMA;
HAL_UART_ASSERT( (config->rx.maxBufSize <= 128) );
HAL_UART_ASSERT( (config->rx.maxBufSize > SAFE_RX_MIN) );
cfg->rxBuf = osal_mem_alloc( cfg->rxMax*2 );
osal_memset( cfg->rxBuf, ~DMA_PAD, cfg->rxMax*2 );
DMA_RX( cfg );
#else
cfg->flag = 0;
HAL_UART_ASSERT( (config->rx.maxBufSize < 256) );
cfg->rxBuf = osal_mem_alloc( cfg->rxMax+1 );
URX0IE = 1;
IEN2 |= UTX0IE;
#endif
// 8 bits/char; no parity; 1 stop bit; stop bit hi.
if ( config->flowControl )
{
cfg->flag |= UART_CFG_FLW;
U0UCR = UCR_FLOW | UCR_STOP;
// Must rely on H/W for RTS (i.e. Tx stops when receiver negates CTS.)
P0SEL |= HAL_UART_0_P0_RTS;
// Cannot use H/W for CTS as DMA does not clear the Rx bytes properly.
P0DIR |= HAL_UART_0_P0_CTS;
RX0_FLOW_ON;
}
else
{
U0UCR = UCR_STOP;
}
}
#endif
#if HAL_UART_1_ENABLE
if ( port == HAL_UART_PORT_1 )
{
// Only supporting 38400 or 115200 for code size - other is possible.
U1BAUD = (config->baudRate == HAL_UART_BR_38400) ? 59 : 216;
U1GCR = (config->baudRate == HAL_UART_BR_38400) ? 10 : 11;
U1CSR |= CSR_RE;
#if HAL_UART_DMA == 2
cfg->flag = (UART_CFG_U1F | UART_CFG_DMA);
HAL_UART_ASSERT( (config->rx.maxBufSize <= 128) );
HAL_UART_ASSERT( (config->rx.maxBufSize > SAFE_RX_MIN) );
cfg->rxBuf = osal_mem_alloc( cfg->rxMax*2 );
osal_memset( cfg->rxBuf, ~DMA_PAD, cfg->rxMax*2 );
DMA_RX( cfg );
#else
cfg->flag = UART_CFG_U1F;
HAL_UART_ASSERT( (config->rx.maxBufSize < 256) );
cfg->rxBuf = osal_mem_alloc( cfg->rxMax+1 );
URX1IE = 1;
IEN2 |= UTX1IE;
#endif
// 8 bits/char; no parity; 1 stop bit; stop bit hi.
if ( config->flowControl )
{
cfg->flag |= UART_CFG_FLW;
U1UCR = UCR_FLOW | UCR_STOP;
// Must rely on H/W for RTS (i.e. Tx stops when receiver negates CTS.)
P1SEL |= HAL_UART_1_P1_RTS;
// Cannot use H/W for CTS as DMA does not clear the Rx bytes properly.
P1DIR |= HAL_UART_1_P1_CTS;
RX1_FLOW_ON;
}
else
{
U1UCR = UCR_STOP;
}
}
#endif
return HAL_UART_SUCCESS;
}
/******************************************************************************
* @fn HalUARTClose
*
* @brief Close the UART
*
* @param port - UART port
*
* @return none
*****************************************************************************/
void HalUARTClose( uint8 port )
{
#if HAL_UART_CLOSE
uartCfg_t *cfg;
#if HAL_UART_0_ENABLE
if ( port == HAL_UART_PORT_0 )
{
U0CSR &= ~CSR_RE;
#if HAL_UART_DMA == 1
HAL_DMA_ABORT_CH( HAL_DMA_CH_RX );
HAL_DMA_ABORT_CH( HAL_DMA_CH_TX );
#else
URX0IE = 0;
#endif
cfg = cfg0;
cfg0 = NULL;
}
#endif
#if HAL_UART_1_ENABLE
if ( port == HAL_UART_PORT_1 )
{
U1CSR &= ~CSR_RE;
#if HAL_UART_DMA == 2
HAL_DMA_ABORT_CH( HAL_DMA_CH_RX );
HAL_DMA_ABORT_CH( HAL_DMA_CH_TX );
#else
URX1IE = 0;
#endif
cfg = cfg1;
cfg1 = NULL;
}
#endif
if ( cfg )
{
if ( cfg->rxBuf )
{
osal_mem_free( cfg->rxBuf );
}
if ( cfg->txBuf )
{
osal_mem_free( cfg->txBuf );
}
osal_mem_free( cfg );
}
#endif
}
/******************************************************************************
* @fn HalUARTPoll
*
* @brief Poll the UART.
*
* @param none
*
* @return none
*****************************************************************************/
void HalUARTPoll( void )
{
#if ( HAL_UART_0_ENABLE | HAL_UART_1_ENABLE )
static uint8 tickShdw;
uartCfg_t *cfg;
uint8 tick;
#if HAL_UART_0_ENABLE
if ( cfg0 )
{
cfg = cfg0;
}
#endif
#if HAL_UART_1_ENABLE
if ( cfg1 )
{
cfg = cfg1;
}
#endif
// Use the LSB of the sleep timer (ST0 must be read first anyway).
tick = ST0 - tickShdw;
tickShdw = ST0;
do
{
if ( cfg->txTick > tick )
{
cfg->txTick -= tick;
}
else
{
cfg->txTick = 0;
}
if ( cfg->rxTick > tick )
{
cfg->rxTick -= tick;
}
else
{
cfg->rxTick = 0;
}
#if HAL_UART_ISR
#if HAL_UART_DMA
if ( cfg->flag & UART_CFG_DMA )
{
pollDMA( cfg );
}
else
#endif
{
pollISR( cfg );
}
#elif HAL_UART_DMA
pollDMA( cfg );
#endif
/* The following logic makes continuous callbacks on any eligible flag
* until the condition corresponding to the flag is rectified.
* So even if new data is not received, continuous callbacks are made.
*/
if ( cfg->rxHead != cfg->rxTail )
{
uint8 evt;
if ( cfg->rxHead >= (cfg->rxMax - SAFE_RX_MIN) )
{
evt = HAL_UART_RX_FULL;
}
else if ( cfg->rxHigh && (cfg->rxHead >= cfg->rxHigh) )
{
evt = HAL_UART_RX_ABOUT_FULL;
}
else if ( cfg->rxTick == 0 )
{
evt = HAL_UART_RX_TIMEOUT;
}
else
{
evt = 0;
}
if ( evt && cfg->rxCB )
{
cfg->rxCB( ((cfg->flag & UART_CFG_U1F)!=0), evt );
}
}
#if HAL_UART_0_ENABLE
if ( cfg == cfg0 )
{
#if HAL_UART_1_ENABLE
if ( cfg1 )
{
cfg = cfg1;
}
else
#endif
break;
}
else
#endif
break;
} while ( TRUE );
#else
return;
#endif
}
/**************************************************************************************************
* @fn Hal_UART_RxBufLen()
*
* @brief Calculate Rx Buffer length - the number of bytes in the buffer.
*
* @param port - UART port
*
* @return length of current Rx Buffer
**************************************************************************************************/
uint16 Hal_UART_RxBufLen( uint8 port )
{
uartCfg_t *cfg = NULL;
#if HAL_UART_0_ENABLE
if ( port == HAL_UART_PORT_0 )
{
cfg = cfg0;
}
#endif
#if HAL_UART_1_ENABLE
if ( port == HAL_UART_PORT_1 )
{
cfg = cfg1;
}
#endif
HAL_UART_ASSERT( cfg );
return UART_RX_AVAIL( cfg );
}
/*****************************************************************************
* @fn HalUARTRead
*
* @brief Read a buffer from the UART
*
* @param port - USART module designation
* buf - valid data buffer at least 'len' bytes in size
* len - max length number of bytes to copy to 'buf'
*
* @return length of buffer that was read
*****************************************************************************/
uint16 HalUARTRead( uint8 port, uint8 *buf, uint16 len )
{
uartCfg_t *cfg = NULL;
uint8 cnt = 0;
#if HAL_UART_0_ENABLE
if ( port == HAL_UART_PORT_0 )
{
cfg = cfg0;
}
#endif
#if HAL_UART_1_ENABLE
if ( port == HAL_UART_PORT_1 )
{
cfg = cfg1;
}
#endif
HAL_UART_ASSERT( cfg );
while ( (cfg->rxTail != cfg->rxHead) && (cnt < len) )
{
*buf++ = cfg->rxBuf[cfg->rxTail];
if ( cfg->rxTail == cfg->rxMax )
{
cfg->rxTail = 0;
}
else
{
cfg->rxTail++;
}
cnt++;
}
#if HAL_UART_DMA
#if HAL_UART_ISR
if ( cfg->flag & UART_CFG_DMA )
#endif
{
/* If there is no flow control on a DMA-driven UART, the Rx Head & Tail
* pointers must be reset to zero after every read in order to preserve the
* full length of the Rx buffer. This implies that every Read must read all
* of the Rx bytes available, or the pointers will not be reset and the
* next incoming packet may not fit in the Rx buffer space remaining - thus
* the end portion of the incoming packet that does not fit would be lost.
*/
if ( !(cfg->flag & UART_CFG_FLW) )
{
// This is a trick to trigger the DMA abort and restart logic in pollDMA.
cfg->flag |= UART_CFG_RXF;
}
}
#endif
#if HAL_UART_ISR
#if HAL_UART_DMA
if ( !(cfg->flag & UART_CFG_DMA) )
#endif
{
cfg->rxCnt = UART_RX_AVAIL( cfg );
if ( cfg->flag & UART_CFG_RXF )
{
if ( cfg->rxCnt < (cfg->rxMax - SAFE_RX_MIN) )
{
RX_STRT_FLOW( cfg );
}
}
}
#endif
return cnt;
}
/******************************************************************************
* @fn HalUARTWrite
*
* @brief Write a buffer to the UART.
*
* @param port - UART port
* pBuffer - pointer to the buffer that will be written, not freed
* length - length of
*
* @return length of the buffer that was sent
*****************************************************************************/
uint16 HalUARTWrite( uint8 port, uint8 *buf, uint16 len )
{
uartCfg_t *cfg = NULL;
uint8 cnt;
#if HAL_UART_0_ENABLE
if ( port == HAL_UART_PORT_0 )
{
cfg = cfg0;
}
#endif
#if HAL_UART_1_ENABLE
if ( port == HAL_UART_PORT_1 )
{
cfg = cfg1;
}
#endif
HAL_UART_ASSERT( cfg );
if ( cfg->txHead == cfg->txTail )
{
#if HAL_UART_DMA
// When pointers are equal, reset to zero to get max len w/out wrapping.
cfg->txHead = cfg->txTail = 0;
#endif
#if HAL_UART_ISR
#if HAL_UART_DMA
if ( !(cfg->flag & UART_CFG_DMA) )
#endif
{
cfg->flag &= ~UART_CFG_TXF;
}
#endif
}
// Accept "all-or-none" on write request.
if ( TX_AVAIL( cfg ) < len )
{
return 0;
}
for ( cnt = len; cnt; cnt-- )
{
cfg->txBuf[ cfg->txHead ] = *buf++;
if ( cfg->txHead == cfg->txMax )
{
cfg->txHead = 0;
}
else
{
cfg->txHead++;
}
}
#if HAL_UART_ISR
#if HAL_UART_DMA
if ( !(cfg->flag & UART_CFG_DMA) )
#endif
{
if ( !(cfg->flag & UART_CFG_TXF) && len )
{
cfg->flag |= UART_CFG_TXF;
if ( !(cfg->flag & UART_CFG_U1F) )
{
U0DBUF = cfg->txBuf[cfg->txTail];
}
else
{
U1DBUF = cfg->txBuf[cfg->txTail];
}
}
}
#endif
return len;
}
#if HAL_UART_ISR
/***************************************************************************************************
* @fn halUart0RxIsr
*
* @brief UART0 Receive Interrupt
*
* @param None
*
* @return None
***************************************************************************************************/
#if HAL_UART_0_ENABLE
HAL_ISR_FUNCTION( halUart0RxIsr, URX0_VECTOR )
{
cfg0->rxBuf[cfg0->rxHead] = U0DBUF;
if ( cfg0->rxHead == cfg0->rxMax )
{
cfg0->rxHead = 0;
}
else
{
cfg0->rxHead++;
}
}
#endif
/***************************************************************************************************
* @fn halUart1RxIsr
*
* @brief UART1 Receive Interrupt
*
* @param None
*
* @return None
***************************************************************************************************/
#if HAL_UART_1_ENABLE
HAL_ISR_FUNCTION( halUart1RxIsr, URX1_VECTOR )
{
cfg1->rxBuf[cfg1->rxHead] = U1DBUF;
if ( cfg1->rxHead == cfg1->rxMax )
{
cfg1->rxHead = 0;
}
else
{
cfg1->rxHead++;
}
}
#endif
/***************************************************************************************************
* @fn halUart0TxIsr
*
* @brief UART0 Transmit Interrupt
*
* @param None
*
* @return None
***************************************************************************************************/
#if HAL_UART_0_ENABLE
HAL_ISR_FUNCTION( halUart0TxIsr, UTX0_VECTOR )
{
UTX0IF = 0;
if ( cfg0->txTail == cfg0->txMax )
{
cfg0->txTail = 0;
}
else
{
cfg0->txTail++;
}
if ( cfg0->txTail != cfg0->txHead )
{
U0DBUF = cfg0->txBuf[cfg0->txTail];
}
}
#endif
/***************************************************************************************************
* @fn halUart1TxIsr
*
* @brief UART1 Transmit Interrupt
*
* @param None
*
* @return None
***************************************************************************************************/
#if HAL_UART_1_ENABLE
HAL_ISR_FUNCTION( halUart1TxIsr, UTX1_VECTOR )
{
UTX1IF = 0;
U1CSR &= ~CSR_TX_BYTE; // Rev-D does not require, older does.
if ( cfg1->txTail == cfg1->txMax )
{
cfg1->txTail = 0;
}
else
{
cfg1->txTail++;
}
if ( cfg1->txTail != cfg1->txHead )
{
U1DBUF = cfg1->txBuf[cfg1->txTail];
}
}
#endif
#endif
/******************************************************************************
******************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -