您的位置:首页 > 其它

z-stack协议uart分析(DMA)

2016-03-30 15:19 99 查看
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 = 216;
}
else
{
UxBAUD = 59;
}

switch (config->baudRate)
{
case HAL_UART_BR_9600:
UxGCR = 8;
dmaCfg.txTick = 35; // (32768Hz / (9600bps / 10 bits))
// 10 bits include start and stop bits.
break;
case HAL_UART_BR_19200:
UxGCR = 9;
dmaCfg.txTick = 18;
break;
case HAL_UART_BR_38400:
UxGCR = 10;
dmaCfg.txTick = 9;
break;
case HAL_UART_BR_57600:
UxGCR = 10;
dmaCfg.txTick = 6;
break;
default:
// HAL_UART_BR_115200
UxGCR = 11;
dmaCfg.txTick = 3;
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[0] = *(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*2);

UxCSR |= CSR_RE;
UxDBUF = 0;  // Prime the DMA-ISR pump.

// Initialize that TX DMA is not pending
dmaCfg.txDMAPending = FALSE;
dmaCfg.txShdwValid = FALSE;
}


9、至此就可以正常使用该串口了,但是具体如何调用呢,有如下函数
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: