关于z-stack串口的一些看法
用户需要使用cc2530串口的话,需要进行初始化,在SampleApp.c下我们需要调用的是MT_UartInit() 和MT_UartRegisterTaskID(task_id) 。剩下的就是在需要的时候HalUARTWrite()和 HalUARTRead()就行了。但是实际上串口涉及了很多东西,让我们从main函数开始看看到底做了什么。
ZMain.c: main()
hal_drivers.c: HalDriverInit (void)
hal_uart.c: HalUARTInit() //因为协议栈的串口用的是dma的方式,所以
是转到下面的函数
_hal_uart_dma.c: HalUARTInitDMA() //配置dma的参数
_______________________________________________________________________________
{
halDMADesc_t*ch; //halDMADesc_t 结构体参考hal_dma.h
P2DIR&= ~P2DIR_PRIPO; //usart0优先
P2DIR |= HAL_UART_PRIPO; //0x00
PERCFG&= ~HAL_UART_PERCFG_BIT; //串口所用的io口设在P0上
PxSEL |= HAL_UART_Px_RX_TX; //替换得到P0SEL = 0x0c 意思是设为外设功能
ADCCFG &= ~HAL_UART_Px_RX_TX; // Make sure ADC doesnt use this.
UxCSR= CSR_MODE; // Mode isUART Mode.
UxUCR = UCR_FLUSH; // Flush it.
ch= HAL_DMA_GET_DESC1234( HAL_DMA_CH_TX ); //ch 是halDMADesc_t结构体指针,HAL_DMA_GET_DESC1234()宏定义为(dmaCh1234+((a)-1)),相当于把4个连续地址的结构体地址给了指针
HAL_DMA_SET_DEST(ch, DMA_UDBUF ); //设置dma传送的目的地址
HAL_DMA_SET_VLEN(ch, HAL_DMA_VLEN_USE_LEN );
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 );
.......
}
返回main函数
———————————————————————————————————————
OSAL.C: osal_init_system()
osal_sampleapp.c: osalInitTasks( )
MT_TASK.c: MT_TaskInit(uint8task_id)
MT_UART.C: MT_UartInit(); //这里配置的是串口的参数,回调函数设 为MT_UartProcessZToolData()
hal_uart.c: HalUARTOpen(MT_UART_DEFAULT_PORT, &uartConfig) //上面的函数配置好了,这里就打开串口。MT_UART_DEFAULT_PORT定义为0x00,是串口0
_hal_uart_dma.c: HalUARTOpenDMA(config) //这里的config就是MT_UartInit()里面配置好的
———————————————————————————————————————
{
dmaCfg.uartCB= config->callBackFunc //把前面串口的回调函数赋值给dma配置结构体的回调函数,因为串口的发送接收都会触发dma事件,dma把串口寄存器的东西拿走之后需要调用回调函数,这里应该是为了概念明确才这么做的吧?
......
// Initialize that TX DMA is not pending
dmaCfg.txDMAPending = FALSE;
dmaCfg.txShdwValid = FALSE;
}
执行完了就一层层往上返回main函数
———————————————————————————————————————
——————————————————————————————————————
z-stack中,每一层要设置什么事件都是用osal_set_event(taskid,event)这个函数去做的,taskid就是各个层的任务id,进入该层的事件处理函数后用event来区分到底发生了什么事。
所以在这里,就调用了MT_ProcessEvent(uint8task_id, uint16 events),函数里面具体在干嘛没看懂。
顺着main函数往下运行来到osal_run_system()
hal_drivers.c Hal_ProcessPoll( )
hal_uart.c: HalUARTPoll( )
_hal_uart_dma.c: HalUARTPollDMA() //轮询dma的函数,放在了系统的循环中, 则说明osal是定期去查询串口数据的
———————————————————————————————————————
{
uint16 cnt = 0; //字符计数
uint8 evt = 0; //事件号
if (HAL_UART_DMA_NEW_RX_BYTE(dmaCfg.rxHead)) //这个宏是查找有没有新收到数据的
{
rxIdx_t tail = findTail();//有的话就找到数据的末端,实际上就是用整形数来表示
// If the DMA hastransferred in more Rx bytes, reset the Rx idle timer.
if (dmaCfg.rxTail != tail)//如果在这一次轮询之前又收到数据了则两者不相等
{