CSR8675 uses UART transceiver function of serial port

Keywords: REST

CSR8675 uses UART transceiver function of serial port

There are two ways for CSR8675 to realize UART function, one is managed connection, the other is direct connection.

Managed connection: do not operate Stream directly, create Source and Sink through VM layer to realize data transmission, which is processed by the library, so it is convenient to realize.
Direct connection: directly operate the Stream. The source is a storage area. Data transmission is realized by operating the memory. The processing data transmission efficiency is higher.

For now, we will introduce the managed connection, and then update the direct connection when you have time.

1. Use RAW transmission

Under project properties, change the Transport property to RAW.

2. Open debug macro

Add debug macro to sink debug. H

3. Edit serial port code to realize loopback function

Four functions are mainly implemented

  1. Message processing function
  2. Serial initialization function
  3. Serial receiving function
  4. Serial port sending function

<sink_uart.h>

#ifndef __UART_H_
#define __UART_H_

void UARTStreamMessageHandler (Task pTask, MessageId pId, Message pMessage);
void uart_data_stream_rx_data(Source src);
void uart_data_stream_tx_data(const uint8 *data, uint16 length);
void uart_data_stream_init(void);

#endif /* __UART_H_ */ 

<sink_uart.c>

#include <stream.h>
#include <sink.h>
#include <source.h>
#include <string.h>
#include <panic.h>
#include <message.h>
#include <app/uart/uart_if.h>
#include <stdio.h>
#include <string.h>
#include "uart.h"
#include "sink_debug.h"

#ifdef DEBUG_UART
#define UART_DEBUG(x) DEBUG(x)
#else
#define UART_DEBUG(x) 
#endif

typedef struct
{
    TaskData task;
    Sink uart_sink;
    Source uart_source;
}UARTStreamTaskData;

UARTStreamTaskData theUARTStreamTask;

void uart_data_stream_init(void)
{
    /* Assign task message handler */
    theUARTStreamTask.task.handler = UARTStreamMessageHandler;
    /* Configure uart settings */
    StreamUartConfigure(VM_UART_RATE_38K4, VM_UART_STOP_ONE, VM_UART_PARITY_NONE);
    /* Get the sink for the uart */
    theUARTStreamTask.uart_sink = StreamUartSink();
    if(theUARTStreamTask.uart_sink != 0)
        PanicNull(theUARTStreamTask.uart_sink);
    /* Get the source for the uart */
    theUARTStreamTask.uart_source = StreamUartSource();
    if(theUARTStreamTask.uart_source != 0)
        PanicNull(theUARTStreamTask.uart_source);
    /* Register uart source with task */
    MessageSinkTask(StreamSinkFromSource(theUARTStreamTask.uart_source),&theUARTStreamTask.task);
}

void uart_data_stream_tx_data(const uint8 *data, uint16 length)
{
    uint16 offset = 0;
    uint8 *dest = NULL;
    /* Claim space in the sink, getting the offset to it */
    offset = SinkClaim(theUARTStreamTask.uart_sink, length);
    if(offset == 0xFFFF) Panic();
    /* Map the sink into memory space */
    dest = SinkMap(theUARTStreamTask.uart_sink);
    PanicNull(dest);
    /* Copy data into the claimed space */
    memcpy(dest+offset, data, length);
    /* Flush the data out to the uart */
    PanicZero(SinkFlush(theUARTStreamTask.uart_sink, length));
}

void uart_data_stream_rx_data(Source src)
{
    uint16 length = 0;
    const uint8 *data = NULL;
    /* Get the number of bytes in the specified source before the next packet boundary */
    if(!(length = SourceBoundary(src)))
        return;
    /* Maps the specified source into the address map */
    data = SourceMap(src);
    PanicNull((void*)data);
    /* Transmit the received data */
    uart_data_stream_tx_data(data, length);
    
    UART_DEBUG(("UART: Rx: length = %d\n",length));
    /* Discards the specified amount of bytes from the front of the specified source */
    SourceDrop(src, length);
}

void UARTStreamMessageHandler (Task pTask, MessageId pId, Message pMessage)
{
    switch (pId)
    {
        case MESSAGE_MORE_DATA:
            uart_data_stream_rx_data(((MessageMoreData *)pMessage)->source);
        break;

        default:
        break;
    }
} 

4. Call function to realize loopback

Modify PSKey
01EA UART_BITRATE changed to 38400

01c2 UART? Config? Usr changed to 0880

In the main function, call the serial port initialization function before MessageLoop().

Press F5 to download to the development board.
Connect the serial port, open the serial port tool, and check the serial port number in the device manager of the computer. The baud rate is set to 38400, the data bit is 8, the stop bit is 1, and the parity bit is none.

However, there is a small problem. After sending 10 data and printing the data length in the receiving function, you will find that you have entered the receiving function twice, received one byte for the first time, and received all the remaining bytes for the second time.

The operation is verified several times, and a rule is found that the first time a byte is always received, and then the length of the rest of the data received will change randomly. The reason may be that the underlying library is realized by flow. Here, asynchronous serial port is used, there is no hardware flow control, and the serial port buffer space of CSR8675 itself is not large, which will lead to data truncation when receiving.
Therefore, in the process of using asynchronous serial port, it is necessary to add splicing processing to the received data according to the actual situation, and at the same time, add custom protocol, increase information such as frame head, frame tail, data length, data verification, etc., so as to ensure that the received content is correct.

Posted by tyrol_gangster on Sun, 27 Oct 2019 21:38:36 -0700