z-stack协议uart分析(DMA)

时间:2022-04-20 21:14:31

1、从ZMain里面的main函数开始分析

2、进入int main( void );

HalDriverInit();   //硬件相关初始化,有DMA初始化和UART初始化

3、进入HalDriverInit();

/* DMA */
#if (defined HAL_DMA) && (HAL_DMA == TRUE)   
// Must be called before the init call to any module that uses DMA.
HalDmaInit();
#endif

/* UART */
#if (defined HAL_UART) && (HAL_UART == TRUE)   // HAL_UART已经在IAR里面定义了HAL_UART=TRUE
HalUARTInit();
#endif

4、进入HalUARTInit();

#if HAL_UART_DMA     // HAL_UART_DMA已经在hal_board_cfg.h里面定义了HAL_UART_DMA     #define HAL_UART_DMA  1 
HalUARTInitDMA();
#endif

5、进入HalUARTInitDMA();配置引脚功能和DMA通道等

 /******************************************************************************
* @fn HalUARTInitDMA
*
* @brief Initialize the UART
*
* @param none
*
* @return none
*****************************************************************************/
static void HalUARTInitDMA(void)
{
halDMADesc_t *ch; P2DIR &= ~P2DIR_PRIPO;
P2DIR |= HAL_UART_PRIPO; #if (HAL_UART_DMA == 1)
PERCFG &= ~HAL_UART_PERCFG_BIT; // Set UART0 I/O to Alt. 1 location on P0.
#else
PERCFG |= HAL_UART_PERCFG_BIT; // Set UART1 I/O to Alt. 2 location on P1.
#endif
PxSEL |= UxRX_TX; // Enable Tx and Rx peripheral functions on pins.
ADCCFG &= ~UxRX_TX; // Make sure ADC doesnt use this.
UxCSR = CSR_MODE; // Mode is UART Mode.
UxUCR = UCR_FLUSH; // Flush it. // Setup Tx by DMA.
ch = HAL_DMA_GET_DESC1234( HAL_DMA_CH_TX ); // The start address of the destination.
HAL_DMA_SET_DEST( ch, DMA_UDBUF ); // Using the length field to determine how many bytes to transfer.
HAL_DMA_SET_VLEN( ch, HAL_DMA_VLEN_USE_LEN ); // One byte is transferred each time.
HAL_DMA_SET_WORD_SIZE( ch, HAL_DMA_WORDSIZE_BYTE ); // The bytes are transferred 1-by-1 on Tx Complete trigger.
HAL_DMA_SET_TRIG_MODE( ch, HAL_DMA_TMODE_SINGLE );
HAL_DMA_SET_TRIG_SRC( ch, DMATRIG_TX ); // The source address is incremented by 1 byte after each transfer.
HAL_DMA_SET_SRC_INC( ch, HAL_DMA_SRCINC_1 ); // The destination address is constant - the Tx Data Buffer.
HAL_DMA_SET_DST_INC( ch, HAL_DMA_DSTINC_0 ); // The DMA Tx done is serviced by ISR in order to maintain full thruput.
HAL_DMA_SET_IRQ( ch, HAL_DMA_IRQMASK_ENABLE ); // Xfer all 8 bits of a byte xfer.
HAL_DMA_SET_M8( ch, HAL_DMA_M8_USE_8_BITS ); // DMA has highest priority for memory access.
HAL_DMA_SET_PRIORITY( ch, HAL_DMA_PRI_HIGH ); // Setup Rx by DMA.
ch = HAL_DMA_GET_DESC1234( HAL_DMA_CH_RX ); // The start address of the source.
HAL_DMA_SET_SOURCE( ch, DMA_UDBUF ); // Using the length field to determine how many bytes to transfer.
HAL_DMA_SET_VLEN( ch, HAL_DMA_VLEN_USE_LEN ); /* The trick is to cfg DMA to xfer 2 bytes for every 1 byte of Rx.
* The byte after the Rx Data Buffer is the Baud Cfg Register,
* which always has a known value. So init Rx buffer to inverse of that
* known value. DMA word xfer will flip the bytes, so every valid Rx byte
* in the Rx buffer will be preceded by a DMA_PAD char equal to the
* Baud Cfg Register value.
*/
HAL_DMA_SET_WORD_SIZE( ch, HAL_DMA_WORDSIZE_WORD ); // The bytes are transferred 1-by-1 on Rx Complete trigger.
HAL_DMA_SET_TRIG_MODE( ch, HAL_DMA_TMODE_SINGLE_REPEATED );
HAL_DMA_SET_TRIG_SRC( ch, DMATRIG_RX ); // The source address is constant - the Rx Data Buffer.
HAL_DMA_SET_SRC_INC( ch, HAL_DMA_SRCINC_0 ); // The destination address is incremented by 1 word after each transfer.
HAL_DMA_SET_DST_INC( ch, HAL_DMA_DSTINC_1 );
HAL_DMA_SET_DEST( ch, dmaCfg.rxBuf );
HAL_DMA_SET_LEN( ch, HAL_UART_DMA_RX_MAX ); // The DMA is to be polled and shall not issue an IRQ upon completion.
HAL_DMA_SET_IRQ( ch, HAL_DMA_IRQMASK_DISABLE ); // Xfer all 8 bits of a byte xfer.
HAL_DMA_SET_M8( ch, HAL_DMA_M8_USE_8_BITS ); // DMA has highest priority for memory access.
HAL_DMA_SET_PRIORITY( ch, HAL_DMA_PRI_HIGH );
}

6、紧接着需要配置串口

uartConfig.configured = TRUE; // 2x30 don't care - see uart driver.
uartConfig.baudRate = SERIAL_APP_BAUD;
uartConfig.flowControl = FALSE;
uartConfig.flowControlThreshold = SERIAL_APP_THRESH; // 2x30 don't care - see uart driver.
uartConfig.rx.maxBufSize = SERIAL_APP_RX_SZ; // 2x30 don't care - see uart driver.
uartConfig.tx.maxBufSize = SERIAL_APP_TX_SZ; // 2x30 don't care - see uart driver.
uartConfig.idleTimeout = SERIAL_APP_IDLE; // 2x30 don't care - see uart driver.
uartConfig.intEnable = TRUE; // 2x30 don't care - see uart driver.
uartConfig.callBackFunc = SerialApp_CallBack;
HalUARTOpen (UART0, &uartConfig);

7、进入HalUARTOpen (UART0, &uartConfig);

#if (HAL_UART_DMA == 1)
if (port == HAL_UART_PORT_0) HalUARTOpenDMA(config);
#endif

8、进入HalUARTOpenDMA(config);

 /******************************************************************************
* @fn HalUARTOpenDMA
*
* @brief Open a port according tp the configuration specified by parameter.
*
* @param config - contains configuration information
*
* @return none
*****************************************************************************/
static void HalUARTOpenDMA(halUARTCfg_t *config)
{
dmaCfg.uartCB = config->callBackFunc;
// Only supporting subset of baudrate for code size - other is possible.
HAL_UART_ASSERT((config->baudRate == HAL_UART_BR_9600) ||
(config->baudRate == HAL_UART_BR_19200) ||
(config->baudRate == HAL_UART_BR_38400) ||
(config->baudRate == HAL_UART_BR_57600) ||
(config->baudRate == HAL_UART_BR_115200)); if (config->baudRate == HAL_UART_BR_57600 ||
config->baudRate == HAL_UART_BR_115200)
{
UxBAUD = ;
}
else
{
UxBAUD = ;
} switch (config->baudRate)
{
case HAL_UART_BR_9600:
UxGCR = ;
dmaCfg.txTick = ; // (32768Hz / (9600bps / 10 bits))
// 10 bits include start and stop bits.
break;
case HAL_UART_BR_19200:
UxGCR = ;
dmaCfg.txTick = ;
break;
case HAL_UART_BR_38400:
UxGCR = ;
dmaCfg.txTick = ;
break;
case HAL_UART_BR_57600:
UxGCR = ;
dmaCfg.txTick = ;
break;
default:
// HAL_UART_BR_115200
UxGCR = ;
dmaCfg.txTick = ;
break;
} // 8 bits/char; no parity; 1 stop bit; stop bit hi.
if (config->flowControl)
{
UxUCR = UCR_FLOW | UCR_STOP;
PxSEL |= HAL_UART_Px_CTS;
// DMA Rx is always on (self-resetting). So flow must be controlled by the S/W polling the Rx
// buffer level. Start by allowing flow.
PxOUT &= ~HAL_UART_Px_RTS;
PxDIR |= HAL_UART_Px_RTS;
}
else
{
UxUCR = UCR_STOP;
} dmaCfg.rxBuf[] = *(volatile uint8 *)DMA_UDBUF; // Clear the DMA Rx trigger.
HAL_DMA_CLEAR_IRQ(HAL_DMA_CH_RX);
HAL_DMA_ARM_CH(HAL_DMA_CH_RX);
osal_memset(dmaCfg.rxBuf, (DMA_PAD ^ 0xFF), HAL_UART_DMA_RX_MAX*); UxCSR |= CSR_RE;
UxDBUF = ; // Prime the DMA-ISR pump. // Initialize that TX DMA is not pending
dmaCfg.txDMAPending = FALSE;
dmaCfg.txShdwValid = FALSE;
}

9、至此就可以正常使用该串口了,但是具体如何调用呢,有如下函数