Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Async/DMA UART2 callback issues #1136

Open
rschoop opened this issue Aug 25, 2024 · 2 comments
Open

Async/DMA UART2 callback issues #1136

rschoop opened this issue Aug 25, 2024 · 2 comments
Assignees

Comments

@rschoop
Copy link

rschoop commented Aug 25, 2024

Hello , I have a custom board based on the MAX32650 . UART2 is connected to a FT230X chip and is working fine . In the examples , data is looped back from UART2 to UART1 . I modified the code to work only with UART2 and I am using a terminal program to receive from UART2_TX and send data to UART2_RX.

In the case for Async transmissions , the callbacks from UART2_TX write requests work fine. I receive the data on the terminal every time. But for read requests, blocking MXC_UART_Transaction and non-blocking MXC_UART_TransactionAsync do not work or the callbacks do not work to make READ_FLAG=0 ; When I use blocking MXC_UART_Read it works every time . See the code below .

For DMA transmissions I used the code from #1106 , I modified the code a bit to use only UART2 in my situation , so no loop back from UART2 to UART1 . Callbacks to make WRITE_FLAG and READ_FLAG zero does not work in the case of DMAAutoHandlers. For DMAManualHandlers the call back works only for write requests. For read requests it does not work . Please check the code below .

Please , can you have a look for me ?

/***** Includes *****/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "mxc_device.h"
#include "board.h"
#include "mxc_delay.h"
#include "uart.h"
#include "dma.h"
#include "nvic_table.h"

/***** Definitions *****/

#define UART_BAUD 115200
#define BUFF_SIZE 8

/***** Globals *****/

volatile int READ_FLAG;
volatile int WRITE_FLAG;

/***** Functions *****/


void UART2_Handler(void)
{
    MXC_UART_AsyncHandler(MXC_UART2);
}

/******************************************************************************/
void readCallback(mxc_uart_req_t *req, int error)
{
    READ_FLAG = error;
}

void writeCallback(mxc_uart_req_t *req, int error)
{
    WRITE_FLAG = error;
}


/******************************************************************************/
int main(void)
{
    int error, i, fail = 0;
    uint8_t TxData[BUFF_SIZE];
    uint8_t RxData[BUFF_SIZE];

    printf("\n\n**************** UART Example ******************\n");

    printf("\nUART Baud \t: %d Hz\n", UART_BAUD);
    printf("Test Length \t: %d bytes\n\n", BUFF_SIZE);

    // Initialize the data buffers
    for (i = 0; i < BUFF_SIZE; i++) {
        TxData[i] = i + 0x30;
    }
    memset(RxData, 0x0, BUFF_SIZE);

    NVIC_ClearPendingIRQ(UART2_IRQn);
	NVIC_DisableIRQ(UART2_IRQn);
	MXC_NVIC_SetVector(UART2_IRQn, UART2_Handler);
	NVIC_EnableIRQ(UART2_IRQn);

    // Initialize the UART
    error = MXC_UART_Init(MXC_UART2, UART_BAUD);
    if (error < E_NO_ERROR) {
        printf("-->Error initializing UART: %d\n", error);
        printf("-->Example Failed\n");
        return error;
    }

    MXC_GPIO_SetVSSEL ( MXC_GPIO1 , MXC_GPIO_VSSEL_VDDIOH , MXC_GPIO_PIN_9 ) ;
    MXC_GPIO_SetVSSEL ( MXC_GPIO1 , MXC_GPIO_VSSEL_VDDIOH , MXC_GPIO_PIN_10 ) ;

    printf("-->UART Initialized\n\n");

    // Setup the asynchronous request
    mxc_uart_req_t read_req;
    read_req.uart = MXC_UART1;
    read_req.rxData = RxData;
    read_req.rxLen = BUFF_SIZE;
    read_req.txLen = 0;
    read_req.callback = readCallback;

    mxc_uart_req_t write_req;
    write_req.uart = MXC_UART2;
    write_req.txData = TxData;
    write_req.txLen = BUFF_SIZE;
    write_req.rxLen = 0;
    write_req.callback = writeCallback;

    READ_FLAG = 1;
    WRITE_FLAG = 1;


    error = MXC_UART_TransactionAsync(&write_req);

	if (error != E_NO_ERROR) {
		printf("-->Error starting sync write: %d\n", error);
		printf("-->Example Failed\n");
		return error;
	}

	printf("waiting for write flag\n") ;
	while (WRITE_FLAG) {}
	printf("write flag received\n") ;



	/*printf("waiting for read data\n") ;

	error = MXC_UART_Transaction(&read_req);

	if (error != E_NO_ERROR) {
		printf("-->Error starting async read: %d\n", error);
		printf("-->Example Failed\n");
		return error;
	}

	printf("waiting for read flag\n") ;
	while (READ_FLAG) {}*/



    /*error = MXC_UART_TransactionAsync(&read_req);

    if (error != E_NO_ERROR) {
        printf("-->Error starting async read: %d\n", error);
        printf("-->Example Failed\n");
        return error;
    }

    printf("waiting for read flag\n") ;
    while (READ_FLAG) {}*/



	printf("waiting for read data\n") ;

	i = 8 ;
	error = MXC_UART_Read ( MXC_UART2 , RxData , &i );

	if (error < E_NO_ERROR) {
		printf("-->Error initializing UART: %d\n", error);
		printf("-->Example Failed\n");
		return error;
	}



    if ((error = memcmp(RxData, TxData, BUFF_SIZE)) != 0) {
        printf("-->Error verifying Data: %d\n", error);
        fail++;
    } else {
        printf("-->Data verified\n");
    }

    if (fail != 0) {
        printf("\n-->Example Failed\n");
        return E_FAIL;
    }

    printf("\n-->Example Succeeded\n");
    return E_NO_ERROR;
}

/******************************************************************************
 *
 * Copyright (C) 2024 Analog Devices, Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ******************************************************************************/

/**
 * @file    main.c
 * @brief   Main for UART example.
 * @details This example sends data from one UART to another. For this example
 *          you must connect a jumper across RX(P2.14) of UART1 and TX(P1.10) of UART2.
 *			UART_BAUD and the BUFF_SIZE can be changed in this example.
 */


/***** Includes *****/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "mxc_device.h"
//#include "pb.h"
#include "board.h"
#include "mxc_delay.h"
#include "uart.h"
#include "dma.h"
#include "nvic_table.h"
//#include "led.h"

/***** Definitions *****/
//#define AUTOHANDLERS

#define UART_BAUD 115200
#define BUFF_SIZE 8

#define RX_UART MXC_UART2
#define TX_UART MXC_UART2

/***** Globals *****/
volatile int READ_FLAG;
volatile int WRITE_FLAG;
volatile int buttonPressed;
static mxc_uart_req_t read_req;
static mxc_uart_req_t write_req;

/***** Functions *****/
#ifndef AUTOHANDLERS
void DMA_RX_Handler(void)
{
    MXC_DMA_Handler();
}

void DMA_TX_Handler(void)
{
    MXC_DMA_Handler();
}
#endif

void readCallback(mxc_uart_req_t *req, int error)
{
    READ_FLAG = error;
}

void writeCallback(mxc_uart_req_t *req, int error)
{
    WRITE_FLAG = error;
}

void buttonHandler(void)
{
    buttonPressed = 1;
}

#ifdef AUTOHANDLERS
int exampleDMAAutoHandlers(void)
{
    int error = 0;

    // Auto DMA handlers will automatically initialize DMA, acquire & assign channels,
    // and guarantee that each transaction's callback function is executed when
    // the transaction is complete.
    MXC_UART_SetAutoDMAHandlers(RX_UART, true);
    MXC_UART_SetAutoDMAHandlers(TX_UART, true);

    // "READ_FLAG" is set in the read transaction's callback.  It will be set to 0 when
    // the read request completes successfully.  We use it to wait for the DMA transaction
    // to complete, since the DMA APIs are asynchronous (non-blocking)
    READ_FLAG = 1;
    WRITE_FLAG = 1;

    /*error = MXC_UART_TransactionDMA(&read_req);
    if (error) {
        printf("-->Error starting DMA read: %d\n", error);
        printf("-->Example Failed\n");
        return error;
    }*/

    error = MXC_UART_TransactionDMA(&write_req);
    if (error) {
        printf("-->Error starting DMA write: %d\n", error);
        printf("-->Example Failed\n");
        return error;
    }


    //printf("waiting for read flag\n") ;
    //while (READ_FLAG) {}


    printf("waiting for write flag\n") ;
    while (WRITE_FLAG) {}

    printf("-->Transaction completed\n");
    return READ_FLAG;
}
#else
int exampleDMAManualHandlers(void)
{
    int error = 0;

    // Manally initialize DMA
    MXC_DMA_Init();

    // Manually acquire a channel for the read request and assign it to the drivers.
    int rx_channel = MXC_DMA_AcquireChannel();
    if (rx_channel >= 0) {
        printf("Acquired DMA channel %i for RX transaction\n", rx_channel);
    } else {
        printf("Failed to acquire RX DMA channel with error %i\n", rx_channel);
        return rx_channel;
    }
    MXC_UART_SetRXDMAChannel(RX_UART, rx_channel);

    // Additionally, assign the NVIC IRQ to a function that calls "MXC_DMA_Handler()".
    // This is required for any assigned callbacks to work.
    NVIC_EnableIRQ(MXC_DMA_CH_GET_IRQ(rx_channel));
    MXC_NVIC_SetVector(MXC_DMA_CH_GET_IRQ(rx_channel), DMA_RX_Handler);

    // Do the same for the write request.
    int tx_channel = MXC_DMA_AcquireChannel();
    if (tx_channel >= 0) {
        printf("Acquired DMA channel %i for RX transaction\n", tx_channel);
    } else {
        printf("Failed to acquire RX DMA channel with error %i\n", tx_channel);
        return tx_channel;
    }
    MXC_UART_SetTXDMAChannel(TX_UART, tx_channel);
    NVIC_EnableIRQ(MXC_DMA_CH_GET_IRQ(tx_channel));
    MXC_NVIC_SetVector(MXC_DMA_CH_GET_IRQ(tx_channel), DMA_TX_Handler);

    // Initialize flags.  We will use these to monitor when the read/write requests
    // have completed, since the DMA APIs are asynchronous.
    WRITE_FLAG = 1;
    READ_FLAG = 1;

    /*error = MXC_UART_TransactionDMA(&read_req);
    if (error) {
        printf("-->Error starting DMA read: %d\n", error);
        printf("-->Example Failed\n");
        return error;
    }*/

    error = MXC_UART_TransactionDMA(&write_req);
    if (error) {
        printf("-->Error starting DMA write: %d\n", error);
        printf("-->Example Failed\n");
        return error;
    }

    printf("waiting for write flag\n") ;
    while (WRITE_FLAG) {}

    //printf("waiting for read flag\n") ;
    //while (READ_FLAG) {}


    printf("-->Transaction completed\n");
    return WRITE_FLAG;
}
#endif // AUTOHANDLERS

/******************************************************************************/
int main(void)
{
    int error, i, fail = 0;
    uint8_t TxData[BUFF_SIZE];
    uint8_t RxData[BUFF_SIZE];

    printf("\n\n**************** UART Example ******************\n");
    printf("This example sends data from one UART to another\n");
    printf("\nConnect RX(P2.14) of UART1 and TX(P1.10) of UART2.\n\n");
    printf("To indicate a successful UART transfer, LED1 will illuminate.\n");
    printf("\nPush SW2 to continue\n");

    /*buttonPressed = 0;
    PB_RegisterCallback(0, (pb_callback)buttonHandler);
    while (!buttonPressed) {}*/

    printf("\nUART Baud \t: %d Hz\n", UART_BAUD);
    printf("Test Length \t: %d bytes\n\n", BUFF_SIZE);

    // Initialize the data buffers
    for (i = 0; i < BUFF_SIZE; i++) {
        TxData[i] = i+0x30;
    }
    memset(RxData, 0x0, BUFF_SIZE);

    // Initialize the UART
    error = MXC_UART_Init(TX_UART, UART_BAUD);
    if (error < E_NO_ERROR) {
        printf("-->Error initializing UART: %d\n", error);
        printf("-->Example Failed\n");
        return error;
    }

    /*error = MXC_UART_Init(RX_UART, UART_BAUD);
    if (error < E_NO_ERROR) {
        printf("-->Error initializing UART: %d\n", error);
        printf("-->Example Failed\n");
        return error;
    }*/


    MXC_GPIO_SetVSSEL ( MXC_GPIO1 , MXC_GPIO_VSSEL_VDDIOH , MXC_GPIO_PIN_9 ) ;
    MXC_GPIO_SetVSSEL ( MXC_GPIO1 , MXC_GPIO_VSSEL_VDDIOH , MXC_GPIO_PIN_10 ) ;


    // Setup request structs describing the transactions.
    // Request structs are placed in the global scope so they
    // don't go out of context.  This can happen when a req struct
    // is declared inside a function and the function completes.
    // The memory would be freed, invalidating the UART driver's
    // pointers to it.
    read_req.uart = RX_UART;
    read_req.rxData = RxData;
    read_req.rxLen = BUFF_SIZE;
    read_req.txLen = 0;
    read_req.callback = readCallback;

    write_req.uart = TX_UART;
    write_req.txData = TxData;
    write_req.txLen = BUFF_SIZE;
    write_req.rxLen = 0;
    write_req.callback = writeCallback;

    printf("-->UART Initialized\n\n");

#ifdef AUTOHANDLERS
    error = exampleDMAAutoHandlers();
#else
    error = exampleDMAManualHandlers();
#endif

    if (READ_FLAG != E_NO_ERROR) {
        printf("-->Error with read callback; %d\n", READ_FLAG);
        fail++;
    }

    if ((error = memcmp(RxData, TxData, BUFF_SIZE)) != 0) {
        printf("-->Error verifying Data: %d\n", error);
        fail++;
    } else {
        printf("-->Data verified\n");
    }

    if (fail != 0) {
        printf("\n-->Example Failed\n");
        //LED_On(0); // indicates FAIL
        return E_FAIL;
    }

    //LED_On(1); // indicates SUCCESS
    printf("\n-->Example Succeeded\n");
    return E_NO_ERROR;
}







@Jake-Carter
Copy link
Contributor

@rschoop For the async case I see in your request struct you still have UART1 for the read request. Set it to UART2 and you should at least get the callbacks.

// Setup the asynchronous request
    mxc_uart_req_t read_req;
    read_req.uart = MXC_UART1; // <-----
    read_req.rxData = RxData;
    read_req.rxLen = BUFF_SIZE;
    read_req.txLen = 0;
    read_req.callback = readCallback;

For the DMA case - I worked through this on my side and found it working for both manual and auto handlers. I see you've commented out the read_req DMA transaction and modified the example to wait on the WRITE_FLAG, so a read request is never launched at all.

Here's an updated project for your use-case. Note I used CONSOLE_UART. You'll want to update this to UART2.
UART_DMA_Echo_Example_MAX32650.zip

There's an echo.py script in there for reference.

Also be careful if your printfs are going to the same UART instance and being echoed back by your python script. (printfs go to CONSOLE_UART defined in board.h).
If that is the case, then be sure to clear the RX FIFO before you launch the transactions. I added this in the attached example.

MXC_Delay(MXC_DELAY_MSEC(50)); // Small delay to allow any echos to complete from python script.
                               // Otherwise previous echos may hit after this and fill up the FIFO again
MXC_UART_ClearRXFIFO(RX_UART);
error = MXC_UART_TransactionDMA(&read_req);
// ...

Hope this helps.

@Jake-Carter Jake-Carter self-assigned this Aug 28, 2024
@rschoop
Copy link
Author

rschoop commented Sep 1, 2024

Hi Jake-Carter ,

Thank you very much, it helped for sure . But still some issues with UART2 DMA echo .

For the async , it was my mistake with UART1 on the read request . I changed it to UART2 and the callbacks works now . Also another mistake I saw was assuming that the blocking MXC_UART_Transaction function has a callback . Now for the async I have a echo that runs on UART2 with no problem. First wait for a read and then echo it back on UART2 .

The echo DMA and the python script works perfect for me on the console or UART0 . But when change the UART0 to UART2 , the read flag does not work . Same behavior I had with my echo DMA program .

I did not explain my dma program well. The program you see it is only for the write transaction . I can receive the transmitted data and write flag is received . But when I comment out the write transaction and the wait for write flag and use only the read transaction and wait only for the read flag it does not work . So actually my previous dma code is not a echo application .

This week I am going to write a register level dma uart echo example on UART2 . The thing is the uart2 echo works well on async . I would like to have uart2 echo on dma .

I just changed the following in the sent dma echo example using the python script :

#define RX_UART MXC_UART2
#define TX_UART MXC_UART2

Add the following:

MXC_GPIO_SetVSSEL ( MXC_GPIO1 , MXC_GPIO_VSSEL_VDDIOH , MXC_GPIO_PIN_9 ) ;
MXC_GPIO_SetVSSEL ( MXC_GPIO1 , MXC_GPIO_VSSEL_VDDIOH , MXC_GPIO_PIN_10 ) ;

Manual DMA:

MXC_Delay(MXC_DELAY_MSEC(50));
MXC_UART_ClearRXFIFO(TX_UART);
MXC_UART_ClearRXFIFO(RX_UART);

printf("-->start manual dma echo\n");

error = MXC_UART_TransactionDMA(&read_req);
if (error) {
    printf("-->Error starting DMA read: %d\n", error);
    printf("-->Example Failed\n");
    return error;
}

error = MXC_UART_TransactionDMA(&write_req);
if (error) {
    printf("-->Error starting DMA write: %d\n", error);
    printf("-->Example Failed\n");
    return error;
}

while (WRITE_FLAG) {}
printf("-->write flag received\n");
while (READ_FLAG) {}
printf("-->read flag received\n");

printf("-->Transaction completed\n");
return WRITE_FLAG;

Results:

= RESTART: C:\Users\rschoop\Downloads\UART_DMA_Echo_Example_MAX32650\echo.py
Opened COM4
b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f !"#$%&\'()*+,-./01'
b'23456789:;<=>?'
b'\x00\x01\x02\x03\x04\x05\x06\x07\x08\t\n\x0b\x0c\r\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f '
b'!"#$%&\'()*+,-./0123456789:;<=>?'

on my console you can see it does not receive the read flag:

**************** UART Example ******************
UART Echo back example

UART Baud : 115200 Hz
Test Length : 64 bytes

-->UART Initialized

Acquired DMA channel 0 for RX transaction
Acquired DMA channel 1 for RX transaction
-->start manual dma echo
-->write flag received

Full code:

/******************************************************************************
 *
 * Copyright (C) 2024 Analog Devices, Inc. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 ******************************************************************************/

/**
 * @file    main.c
 * @brief   Main for UART example.
 * @details This example sends data from one UART to another. For this example
 *          you must connect a jumper across RX(P2.14) of UART1 and TX(P1.10) of UART2.
 *			UART_BAUD and the BUFF_SIZE can be changed in this example.
 */


/***** Includes *****/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include "mxc_device.h"
#include "board.h"
#include "mxc_delay.h"
#include "uart.h"
#include "dma.h"
#include "nvic_table.h"
#include "mxc_errors.h"

/***** Definitions *****/
//#define AUTOHANDLERS

#define UART_BAUD 115200
#define BUFF_SIZE 64

#define RX_UART MXC_UART2
#define TX_UART MXC_UART2

/***** Globals *****/
volatile int READ_FLAG;
volatile int WRITE_FLAG;
volatile int buttonPressed;
static mxc_uart_req_t read_req;
static mxc_uart_req_t write_req;

/***** Functions *****/
#ifndef AUTOHANDLERS
void DMA_RX_Handler(void)
{
    MXC_DMA_Handler();
}

void DMA_TX_Handler(void)
{
    MXC_DMA_Handler();
}
#endif

void readCallback(mxc_uart_req_t *req, int error)
{
    READ_FLAG = error;
}

void writeCallback(mxc_uart_req_t *req, int error)
{
    WRITE_FLAG = error;
}

void buttonHandler(void)
{
    buttonPressed = 1;
}

#ifdef AUTOHANDLERS
int exampleDMAAutoHandlers(void)
{
    int error = 0;

    // Auto DMA handlers will automatically initialize DMA, acquire & assign channels,
    // and guarantee that each transaction's callback function is executed when
    // the transaction is complete.
    MXC_UART_SetAutoDMAHandlers(RX_UART, true);
    MXC_UART_SetAutoDMAHandlers(TX_UART, true);

    // "READ_FLAG" is set in the read transaction's callback.  It will be set to 0 when
    // the read request completes successfully.  We use it to wait for the DMA transaction
    // to complete, since the DMA APIs are asynchronous (non-blocking)
    READ_FLAG = 1;

    MXC_Delay(MXC_DELAY_MSEC(50));
    MXC_UART_ClearRXFIFO(TX_UART);
    MXC_UART_ClearRXFIFO(RX_UART);

    error = MXC_UART_TransactionDMA(&read_req);
    if (error) {
        printf("-->Error starting DMA read: %d\n", error);
        printf("-->Example Failed\n");
        return error;
    }

    error = MXC_UART_TransactionDMA(&write_req);
    if (error) {
        printf("-->Error starting DMA write: %d\n", error);
        printf("-->Example Failed\n");
        return error;
    }

    while (READ_FLAG) {}

    printf("-->Transaction completed\n");
    return READ_FLAG;
}
#else
int exampleDMAManualHandlers(void)
{
    int error = 0;

    // Manally initialize DMA
    MXC_DMA_Init();

    // Manually acquire a channel for the read request and assign it to the drivers.
    int rx_channel = MXC_DMA_AcquireChannel();
    if (rx_channel >= 0) {
        printf("Acquired DMA channel %i for RX transaction\n", rx_channel);
    } else {
        printf("Failed to acquire RX DMA channel with error %i\n", rx_channel);
        return rx_channel;
    }
    MXC_UART_SetRXDMAChannel(RX_UART, rx_channel);

    // Additionally, assign the NVIC IRQ to a function that calls "MXC_DMA_Handler()".
    // This is required for any assigned callbacks to work.
    NVIC_EnableIRQ(MXC_DMA_CH_GET_IRQ(rx_channel));
    MXC_NVIC_SetVector(MXC_DMA_CH_GET_IRQ(rx_channel), DMA_RX_Handler);

    // Do the same for the write request.
    int tx_channel = MXC_DMA_AcquireChannel();
    if (tx_channel >= 0) {
        printf("Acquired DMA channel %i for RX transaction\n", tx_channel);
    } else {
        printf("Failed to acquire RX DMA channel with error %i\n", tx_channel);
        return tx_channel;
    }
    MXC_UART_SetTXDMAChannel(TX_UART, tx_channel);
    NVIC_EnableIRQ(MXC_DMA_CH_GET_IRQ(tx_channel));
    MXC_NVIC_SetVector(MXC_DMA_CH_GET_IRQ(tx_channel), DMA_TX_Handler);

    // Initialize flags.  We will use these to monitor when the read/write requests
    // have completed, since the DMA APIs are asynchronous.
    WRITE_FLAG = 1;
    READ_FLAG = 1;

    MXC_Delay(MXC_DELAY_MSEC(50));
    MXC_UART_ClearRXFIFO(TX_UART);
    MXC_UART_ClearRXFIFO(RX_UART);
    
    printf("-->start manual dma echo\n");

    error = MXC_UART_TransactionDMA(&read_req);
    if (error) {
        printf("-->Error starting DMA read: %d\n", error);
        printf("-->Example Failed\n");
        return error;
    }

    error = MXC_UART_TransactionDMA(&write_req);
    if (error) {
        printf("-->Error starting DMA write: %d\n", error);
        printf("-->Example Failed\n");
        return error;
    }

    while (WRITE_FLAG) {}
    printf("-->write flag received\n");
    while (READ_FLAG) {}
    printf("-->read flag received\n");

    printf("-->Transaction completed\n");
    return WRITE_FLAG;
}
#endif // AUTOHANDLERS

/******************************************************************************/
int main(void)
{
    int error, i, fail = 0;
    uint8_t TxData[BUFF_SIZE];
    uint8_t RxData[BUFF_SIZE];

    printf("\n\n**************** UART Example ******************\n");
    printf("UART Echo back example\n");

    printf("\nUART Baud \t: %d Hz\n", UART_BAUD);
    printf("Test Length \t: %d bytes\n\n", BUFF_SIZE);

    // Initialize the data buffers
    for (i = 0; i < BUFF_SIZE; i++) {
        TxData[i] = i;
    }
    memset(RxData, 0x0, BUFF_SIZE);

    // Initialize the UART
    error = MXC_UART_Init(TX_UART, UART_BAUD);
    if (error < E_NO_ERROR) {
        printf("-->Error initializing UART: %d\n", error);
        printf("-->Example Failed\n");
        return error;
    }
    
    MXC_GPIO_SetVSSEL ( MXC_GPIO1 , MXC_GPIO_VSSEL_VDDIOH , MXC_GPIO_PIN_9 ) ;
    MXC_GPIO_SetVSSEL ( MXC_GPIO1 , MXC_GPIO_VSSEL_VDDIOH , MXC_GPIO_PIN_10 ) ;

    // Setup request structs describing the transactions.
    // Request structs are placed in the global scope so they
    // don't go out of context.  This can happen when a req struct
    // is declared inside a function and the function completes.
    // The memory would be freed, invalidating the UART driver's
    // pointers to it.
    read_req.uart = RX_UART;
    read_req.rxData = RxData;
    read_req.rxLen = BUFF_SIZE;
    read_req.txLen = 0;
    read_req.callback = readCallback;

    write_req.uart = TX_UART;
    write_req.txData = TxData;
    write_req.txLen = BUFF_SIZE;
    write_req.rxLen = 0;
    write_req.callback = writeCallback;

    printf("-->UART Initialized\n\n");

#ifdef AUTOHANDLERS
    error = exampleDMAAutoHandlers();
#else
    error = exampleDMAManualHandlers();
#endif

    if (READ_FLAG != E_NO_ERROR) {
        printf("-->Error with read callback; %d\n", READ_FLAG);
        fail++;
    }

    for (unsigned int i = 0; i < BUFF_SIZE; i++) {
        if (TxData[i] != RxData[i]) {
            printf("---> Verify error at index %u, expected %i but got %i\n", i, TxData[i], RxData[i]);
            fail++;
        }
    }

    if (fail != 0) {
        printf("\n-->Example Failed\n");
        return E_FAIL;
    }

    printf("\n-->Example Succeeded\n");
    return E_NO_ERROR;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants