Z-stack problem of the serial structure uartcfg_t nonsense
typedef struct
{
Uint8 *rxbuf;//Receive Cache
Uint8 rxhead;//Head
Uint8 rxtail;//Tail
Uint8 rxmax;//Receive Maximum length
Uint8 rxcnt;//Count
Uint8 rxtick;//Time
Uint8 rxhigh;//High
Uint8 *txbuf;
#if hal_uart_big_tx_buf
UInt16 Txhead;
UInt16 Txtail;
UInt16 Txmax;
UInt16 txcnt;
#else
Uint8 Txhead;
Uint8 Txtail;
Uint8 Txmax;
Uint8 txcnt;
#endif
Uint8 Txtick;
Uint8 flag;//Flag bit
haluartcback_t RXCB;
} uartcfg_t;
A friend asked me the above question, to tell the truth, I was the first time to see this thing, get hands than my friend still confused, the friend at least also know what function, just not clear the specific meaning and function of each parameter. In order to solve this problem, I have been looking for masters, the end result is not very clear, because ordinary people just use, which tube so many of these specific details? No way, I only have to solve their own, I hope that my efforts can give you a little revelation!
First of all, the application of this structure, it is directly oriented to the application layer of the serial port, that is, contact with customers or a relatively close structure, usually in the serial port to receive data and send data when used. And the serial port has two kinds of ways, one is the common serial port, one is the DMA way. Here I only analyze this structure for the normal serial port.
Let's start by looking at where this structure is used.
static void Polldma (uartcfg_t *cfg)
static void Pollisr (uartcfg_t *cfg)
These two functions directly use the structure as a parameter, it should be said to be the most closely related, is our focus on the analysis of the object, but here do not look at the DMA, because this I am very layman----------haha!!!!!
UInt16 Haluartread (uint8 port, uint8 *buf, UInt16 len)
Uint8 Haluartopen (uint8 port, haluartcfg_t *config)
void Haluartclose (uint8 port)
void Haluartpoll (void)
UInt16 Hal_uart_rxbuflen (uint8 port)
UInt16 Haluartwrite (uint8 port, uint8 *buf, UInt16 len)
These functions all define the variables of this structure in use, so we also need to focus on them.
It can be seen that this structure and the application of the serial port, that is, the data received and sent, and the serial port of the initialization of the lamp does not matter. So this excludes any possibility of serial port initialization.
We're going to have a relationship. Two definitions of global variables:
#if hal_uart_0_enable
Static uartcfg_t *cfg0;
#endif
#if hal_uart_1_enable
Static uartcfg_t *cfg1;
#endif
Can be seen, serial 0 corresponding variable cfg0, serial 1 corresponding variable CFG1. The change in these two variables gives us a major focus, because as long as we understand the process of change and how we use it, we can basically find out the meaning of each parameter.
In order to clarify the meaning of each parameter, so one by one to analyze. This is the inverse problem-solving method, the positive thinking is the first to read each function to see the understanding, nature will know. But where do I get that ability and kung fu? So lazy to start from behind!!!
1. uint8 *rxbuf;//Receive Cache
This parameter I think there is no need to explain too much, is the serial port to receive the cache. Intuitive understanding is the serial port to receive the data, the most obvious place to reflect this meaning is the serial receiver function:
Cfg->rxbuf = Osal_mem_alloc (cfg->rxmax+1);
Here is the statement in the open serial function that allocates storage space for the receive cache.
Osal_mem_free (CFG->RXBUF);
This function is to close the serial function, that is, to free up storage space.
Hal_isr_function (HALUART0RXISR, Urx0_vector)
{
Cfg0->rxbuf[cfg0->rxhead] = u0dbuf;
if (Cfg0->rxhead = = Cfg0->rxmax)
{
Cfg0->rxhead = 0;
}
Else
{
cfg0->rxhead++;
}
}
This is the serial port 0 interrupt function: where cfg0->rxbuf[cfg0->rxhead] = U0dbuf, it is obvious that the data in the U0DBUF transferred to the storage area.
There are two questions that can be seen from this function:
Rxhead is used as a serial receive count, while Rxmax represents the maximum received data length.
2, Uint8 Rxhead
The literal understanding is the receiving head, but the above already mentions the function that appears to have the serial port to receive the count. Then let's see what it means.
Cfg->rxhead = Cfg->rxtail = 0;
This assignment in the open string is initialized to 0.
In fact, from the above interrupt function has been the function of this parameter embodies the incisively and vividly:
Is that the serial port receives the data, and this parameter always points to a location like a parameter being stored in the rxbuf. Because the hardware serial buffer u0dbuf can only hold one byte, if not in time to transfer this received, then will be overwritten by the next byte, so the Rxhead variable points to the address of the store, of course, is based on the definition of rxbuf storage space. Equivalent to an array assignment, there must be a variable that points to the next assigned parameter of the array, although the final value of the variable also reflects the size of the assigned array to some extent. So Rxhead played a similar role here, and if (Cfg0->rxhead = = Cfg0->rxmax) This sentence also illustrates clearly, once the count reached the maximum number of received defined, that is, the RXBUF storage space is full, Then you can not continue to store, or the location of the store is unknown, and it is possible to cause other variables in the program damage, then this time if the serial port has data to do? Then you need to empty the rxbuf to receive, otherwise you will lose the data.
3, Uint8 Rxtail;
This variable is closely related to the empty rxbuf mentioned above.
while ((Cfg->rxtail! = cfg->rxhead) && (CNT < len))
{
*buf++ = cfg->rxbuf[cfg->rxtail];
if (Cfg->rxtail = = Cfg->rxmax)
{
Cfg->rxtail = 0;
}
Else
{
cfg->rxtail++;
}
cnt++;
}
Here is called in the UInt16 haluartread (uint8 port, uint8 *buf, UInt16 len) function, actually read the data of the Rxbuf space, and then RXBUF can continue to receive the serial data. You can see *buf++ = Cfg->rxbuf[cfg->rxtail] This is the transfer of data, and the number of transfers is counted as rxtail. Once the count reaches Rxmax, the count is 0 because Rxmax defines the maximum amount of data for rxbuf.
One thing to emphasize here: the difference between Rxtail and Rxhead.
The first thing I saw in this two variables is that the Rxhead is the head of the serial data string, and the Rxtail is the tail (end) of the serial data string, because this understanding conforms to our usual habit of writing serial communication protocol, symbolizing. But look carefully only, although also is the concept of head and tail, but should not so understand.
Rxtail and Rxhead should be for rxbuf. Rxhead is the count of data to Rxbuf, and Rxtail is the count of data taken from RXBUF. I hope this must be noticed. So we are not difficult to understand: Rxhead is in the serial reception interrupt when the emphasis is used, and rxtail is used in the Haluartread function. It is also important to note that Haluartread is not reading UXBUF data, but reading the data in Rxbuf.
In fact, think carefully, these two parameters are still related to the head and tail of the serial port. The first name begins, the serial port receives the data to begin to store the data the point, the tail also is the end, is the serial port data takes away uses as the point of his use. Rxhead=0, marking the serial port to receive data new starting point, a new beginning, and Rxtail=0, mark the serial port received all the data taken away for his use,------end. It embodies the whole process of serial port data from receiving to being used.
4, Uint8 rxmax;//receive the maximum length
This I think there is no need to explain more, here only to see how big it is, because the amount of the assignment is very hidden, I find a long time to do not bear the conscientious!!!
First, in the open serial port function, there are:
Cfg->rxmax = config->rx.maxbufsize;
Second, in the Void Spimgr_init () function, there are:
UartConfig.rx.maxBufSize = Spi_mgr_default_max_rx_buff;
At times there are the following definitions:
#define Spi_mgr_default_max_rx_buff Spi_rx_buff_max
Finally found the final thing:
#define SPI_RX_BUFF_MAX 128
Or hide is very hidden is, hehe!!!! About this 128 I was doing an experiment, in the serial interface of the experiment is also the definition of 128. More will be thrown away! The next time I have a chance to say.
5, Uint8 rxcnt;
static void Pollisr (uartcfg_t *cfg)
{
Uint8 cnt = uart_rx_avail (CFG);
if (! ( Cfg->flag & UART_CFG_RXF))
{
If anything received, reset the Rx idle timer.
if (cfg->rxcnt! = CNT)
{
Cfg->rxtick = Hal_uart_rx_idle;
cfg->rxcnt = CNT;
}
/* It is necessary-stop Rx flow in advance of a full Rx buffer because
* bytes can keep coming while sending h/w FIFO flushes.
*/
if (cfg->rxcnt >= (cfg->rxmax-safe_rx_min))
{
Rx_stop_flow (CFG);
}
}
}
This is the most typical use of this function.
The first sentence of care Not if (cfg->rxcnt! = CNT) is related to the CNT variable at the outset, and even more so is in the inside directly cfg->rxcnt = CNT, so it has to be related to CNT.
Uint8 cnt = uart_rx_avail (CFG); the first sentence of this function, and:
#define UART_RX_AVAIL (CFG) \
((Cfg->rxhead >= cfg->rxtail)? (cfg->rxhead-cfg->rxtail): \
(Cfg->rxmax-cfg->rxtail + cfg->rxhead +1))
My understanding is that Uart_rx_avail is indicating how much useful data is left in the serial buffer rxbuf, that is, data that has not been taken away. First of all, from the literal understanding of avail as "utility" meaning, then the extension of the available, then the meaning is "useful" "free", hehe! It's really interesting to understand, huh?
From the back of the judgment statement, Cfg->rxhead-cfg->rxtail, because of the above explanation, understand this is very easy, some data-the number of data has been taken away, then the province still have how many useful data volume.
and Cfg->rxmax-cfg->rxtail + cfg->rxhead +1 understand need to turn a bend, because at this time cfg->rxhead > Cfg->rxtail, then under what circumstances to meet this condition, In only one case, Rxhead is already in the second round of receiving counts, while Rxtail is still in the previous round. Cfg->rxmax-cfg->rxtail, that is, the first round to fill the RXBUF data to take Cfg->rxtail, then the first round of the remaining data, then in the + Cfg->rxhead This, is added cfg- >rxhead the second round of data received, as for the following +1 of the understanding of Cfg->rxbuf = Osal_mem_alloc (cfg->rxmax+1), allocating storage space would have been more divided than Rxmax. ------------------------------Here I still have doubts, who have a deep understanding of welcome communication!
And if (cfg->rxcnt >= (cfg->rxmax-safe_rx_min)) Here understanding is more subtle, indicating that the receive cache space is full, so the following is Rx_stop_flow (CFG);
#define Rx_stop_flow (CFG) {\
if (! ( Cfg->flag & uart_cfg_u1f)) \
{ \
Rx0_flow_off; \
} \
else \
{ \
Rx1_flow_off; \
} \
if (Cfg->flag & UART_CFG_DMA) \
{ \
Cfg->rxtick = dma_rx_dly; \
} \
Cfg->flag |= uart_cfg_rxf; \
}
It can be seen that the receiver is stopped by the hardware flow control, and the set bit Cfg->flag is UART_CFG_RXF.
As for Cfg->rxmax-safe_rx_min's understanding is the subtlety of the place.
#define SAFE_RX_MIN 48
Defines the maximum number of bytes of data that can be received at each serial port operation processing interval. Because this space must be reserved enough, otherwise during the non-processing interval may overwrite the previous data, the understanding of this is now more difficult, I would like to go through the following narrative will be enlightened.
6, Uint8 rxtick;//time
Cfg->rxtick = Hal_uart_rx_idle;
#define HAL_UART_RX_IDLE (6 * rx_msecs_to_ticks)
#define Rx_msecs_to_ticks 33
So cfg->rxtick=198, that is, almost 200ms to deal with this function once POLLISR.
Here I can argue that the above mentioned # define Safe_rx_min 48
Because the CC2430 serial baud rate is 38400bps, one byte requires an event of approximately: 4.16ms, then 198/4.16 equals 47.6, about 48. So that's why the above 48 is defined. Because Cfg->rxtick defines how often the serial buffer is processed, and in order to ensure that the serial buffers are not overwritten by new data, it is necessary to ensure that more than 48 bytes of storage space is idle during this interval.
As for this time specifically related to the use of sleep timer, this I am not clear.
7, Uint8 Rxhigh;
Cfg->rxhigh = config->rx.maxbufsize-config->flowcontrolthreshold;
Defines the size of the Rxhigh.
else if (Cfg->rxhigh && (cfg->rxhead >= Cfg->rxhigh))
{
EVT = Hal_uart_rx_about_full;
}
It is pointed out that the usage of Rxhigh is to trigger the Hal_uart_rx_about_full event once the received data exceeds Rxhigh.
Uartconfig.flowcontrolthreshold = Spi_mgr_default_threshold;
#define Spi_mgr_default_threshold Spi_threshold
#define Spi_threshold 48
Finally we can see the cfg->rxhigh=128-48=80.
This means that the Hal_uart_rx_about_full event is triggered whenever the received data exceeds 80. So let's see what this event is for:
if (Event & Hal_uart_rx_full | Hal_uart_rx_about_full | Hal_uart_rx_timeout))
{
while (Hal_uart_rxbuflen (Spi_mgr_default_port))
{
Haluartread (Spi_mgr_default_port, &ch, 1);
.....................................................................................................
Basically, call Haluartread to read the data of the serial-port mixed-storage area.
Its basic meaning is a read the upper limit of the serial cache data, as long as the data within the RXBUF to reach this amount should be read. My understanding of the above several events is:
Hal_uart_rx_full:rxbuf full
Hal_uart_rx_about_full:rxbuf full, that is, almost full.
Hal_uart_rx_timeout:rx Receive event overflow.
8, about the TX-related variables Here is not a say, and Rx almost mean.
9, Uint8 Flag;
The sign of the serial port, identifies the different states of the serial port operation, including the cache full, empty and so on. This does not describe, because I feel good understanding, just specific more trouble, meaning know can ha.
10, haluartcback_t RXCB;
This is the serial call callback function, also do not say.
Basically the meaning of these parameters to say, understand the meaning of the program to better match the corresponding function.
As for the right, but also ask you a lot of criticism, I just from the local analysis, and try to put these meanings, a bit even the suspicion of the suspect!!!
But my friend began to think that this structure is related to the Zstack and PC serial communication protocol, here I can say, this is not related to the communication protocol. It should be said that there is no direct relationship.
and Zstack and PC serial communication is through the Z-tool tool, about this I briefly mention:
The protocols for Zstack and Z-tool communication are:
For a detailed description of this, see: Serial Port interface_f8w-2003-0001_.pdf
and Z-tool tool detailed description see: swra119.pdf
This is the end of this, is too tired, from what do not know, to now I have a whole day, tired of panic!
Final statement: The above description represents only personal understanding and does not represent official regulations.
If there are any mistakes, please also criticize!!!!
Yyytech in Chengdu
2008-8-9 17:43
"Turn" reprint zstack serial User Guide