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

fix(PeriphDrivers): Fix UART DMA Transactions and Enable Full Duplex #763

Merged
merged 28 commits into from
Nov 30, 2023
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
b6d919d
Fix DMA channel leak in UART RevA
Jake-Carter Oct 9, 2023
b9393ea
Add MXC_DMA_CH_GET_IRQ for ME14
Jake-Carter Oct 9, 2023
34276b4
Checkpoint: auto interrupt handlers (not totally compatible with old …
Jake-Carter Oct 9, 2023
77ecaef
UART_RevA: Add APIs for setting DMA handlers, expose to ME14
Jake-Carter Oct 10, 2023
e2a9134
clang-format
Jake-Carter Oct 10, 2023
bd4e60f
Implement autohandlers for UART Rev B
Jake-Carter Oct 16, 2023
fade8a5
Add function prototypes for all micros
Jake-Carter Oct 20, 2023
1a336ea
Add RevB passthroughs
Jake-Carter Oct 20, 2023
2d325eb
Add stdbool to all uart.h
Jake-Carter Oct 20, 2023
07eef60
Add RevA passthroughs
Jake-Carter Oct 20, 2023
2d5ec93
Fix req clobbering and callbacks for RevA
Jake-Carter Oct 20, 2023
a03f22b
Fix req clobbering and callbacks for RevB
Jake-Carter Oct 20, 2023
2cd7d4f
Fix build error
Jake-Carter Oct 20, 2023
d9e9441
clang-format
Jake-Carter Oct 20, 2023
fe51c36
Add newline at end of file
Jake-Carter Oct 23, 2023
dc04d78
Fix -1 assigned to uint8_t
Jake-Carter Oct 23, 2023
2ea9524
clang-format bot reformatting.
EricB-ADI Oct 24, 2023
aba737e
Remove UART FIFO clears in me21 file
Jake-Carter Oct 25, 2023
831c893
Address Lorne review notes
Jake-Carter Nov 13, 2023
8086917
Only acquire channel if we don't have one already
Jake-Carter Nov 13, 2023
ad19c87
Update UART example projects
Jake-Carter Nov 14, 2023
34db845
Use MXC_ASSERT instead of runtime checks
Jake-Carter Nov 29, 2023
81837cc
Disable MXC_ASSERT for bootloader examples
Jake-Carter Nov 29, 2023
c24e810
Merge remote-tracking branch 'remotes/upstream/main' into fix/gh-761
Jake-Carter Nov 29, 2023
566f057
Fix variable mismatch, swap for more asserts
Jake-Carter Nov 30, 2023
b332e72
Disable MXC_ASSERT for SCPA_OTP_Dump
Jake-Carter Nov 30, 2023
63fca53
clang-format
Jake-Carter Nov 30, 2023
85020c8
PURGE THE ASSERTS
Jake-Carter Nov 30, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Libraries/CMSIS/Device/Maxim/MAX32665/Include/max32665.h
Original file line number Diff line number Diff line change
Expand Up @@ -499,6 +499,10 @@ typedef enum {
((i) == 7) ? DMA15_IRQn : \
0))

#define MXC_DMA_CH_GET_IRQ(i) \
(((i) > (MXC_DMA_CH_OFFSET - 1)) ? MXC_DMA1_CH_GET_IRQ(i % MXC_DMA_CH_OFFSET) : \
MXC_DMA0_CH_GET_IRQ(i))

/* Create alias for MXC_DMA0 for backwards compatibility with code that was
written for parts that only had one DMA instance. */
#define MXC_DMA MXC_DMA0
Expand Down
6 changes: 6 additions & 0 deletions Libraries/PeriphDrivers/Include/MAX32665/uart.h
Original file line number Diff line number Diff line change
Expand Up @@ -700,6 +700,12 @@ uint32_t MXC_UART_GetAsyncTXCount(mxc_uart_req_t *req);
*/
uint32_t MXC_UART_GetAsyncRXCount(mxc_uart_req_t *req);

int MXC_UART_SetAutoDMAHandlers(mxc_uart_regs_t *uart, bool enable);
Jake-Carter marked this conversation as resolved.
Show resolved Hide resolved
int MXC_UART_SetTXDMAChannel(mxc_uart_regs_t *uart, unsigned int channel);
int MXC_UART_GetTXDMAChannel(mxc_uart_regs_t *uart);
int MXC_UART_SetRXDMAChannel(mxc_uart_regs_t *uart, unsigned int channel);
int MXC_UART_GetRXDMAChannel(mxc_uart_regs_t *uart);

/**@} end of group uart */

#ifdef __cplusplus
Expand Down
21 changes: 21 additions & 0 deletions Libraries/PeriphDrivers/Source/UART/uart_me14.c
Original file line number Diff line number Diff line change
Expand Up @@ -446,3 +446,24 @@ uint32_t MXC_UART_GetAsyncRXCount(mxc_uart_req_t *req)
{
return req->rxCnt;
}

int MXC_UART_SetAutoDMAHandlers(mxc_uart_regs_t *uart, bool enable)
{
return MXC_UART_RevA_SetAutoDMAHandlers((mxc_uart_reva_regs_t *)uart, enable);
}
int MXC_UART_SetTXDMAChannel(mxc_uart_regs_t *uart, unsigned int channel)
{
return MXC_UART_RevA_SetTXDMAChannel((mxc_uart_reva_regs_t *)uart, channel);
}
int MXC_UART_GetTXDMAChannel(mxc_uart_regs_t *uart)
{
return MXC_UART_RevA_GetTXDMAChannel((mxc_uart_reva_regs_t *)uart);
}
int MXC_UART_SetRXDMAChannel(mxc_uart_regs_t *uart, unsigned int channel)
{
return MXC_UART_RevA_SetRXDMAChannel((mxc_uart_reva_regs_t *)uart, channel);
}
int MXC_UART_GetRXDMAChannel(mxc_uart_regs_t *uart)
{
return MXC_UART_RevA_GetRXDMAChannel((mxc_uart_reva_regs_t *)uart);
}
161 changes: 146 additions & 15 deletions Libraries/PeriphDrivers/Source/UART/uart_reva.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@
#include "uart.h"
#include "uart_reva.h"
#include "dma.h"
#ifdef __arm__
#include "nvic_table.h"
#endif

/* **** Definitions **** */
#define MXC_UART_REVA_ERRINT_EN \
Expand All @@ -56,6 +59,7 @@ typedef struct {
mxc_uart_reva_req_t *req;
int channelTx;
int channelRx;
bool auto_dma_handlers;
} uart_reva_req_state_t;

uart_reva_req_state_t states[MXC_UART_INSTANCES];
Expand Down Expand Up @@ -98,6 +102,14 @@ int MXC_UART_RevA_Init(mxc_uart_reva_regs_t *uart, unsigned int baud)

MXC_UART_SetFrequency((mxc_uart_regs_t *)uart, baud);

// Initialize state struct
lorne-maxim marked this conversation as resolved.
Show resolved Hide resolved
for (int i = 0; i < MXC_UART_INSTANCES; i++) {
states[i].channelRx = -1;
states[i].channelTx = -1;
states[i].req = NULL;
states[i].auto_dma_handlers = false;
}

return E_NO_ERROR;
}

Expand Down Expand Up @@ -548,6 +560,49 @@ unsigned int MXC_UART_RevA_ReadRXFIFO(mxc_uart_reva_regs_t *uart, unsigned char
return read;
}

#if MXC_DMA_INSTANCES > 1

void MXC_UART_RevA_DMA0_Handler(void)
{
MXC_DMA_Handler(MXC_DMA0);
}

void MXC_UART_RevA_DMA1_Handler(void)
{
MXC_DMA_Handler(MXC_DMA1);
}

#endif

/* "Auto" handlers just need to call MXC_DMA_Handler with the correct
DMA instance.
*/
void MXC_UART_RevA_DMA_SetupAutoHandlers(mxc_dma_regs_t *dma_instance, unsigned int channel)
{
#ifdef __arm__
NVIC_EnableIRQ(MXC_DMA_CH_GET_IRQ(channel));

#if MXC_DMA_INSTANCES > 1
/* (JC): This is not the cleanest or most scalable way to do this,
but I tried defining default handler's in the system file.
Some complications make this the most attractive short-term
option. We could handle multiple DMA instances better in the DMA API (See the mismatch between the size of "dma_resource" array and the number of channels per instance, to start)*/
if (dma_instance == MXC_DMA0) {
MXC_NVIC_SetVector(MXC_DMA_CH_GET_IRQ(channel), MXC_UART_RevA_DMA0_Handler);
} else if (dma_instance == MXC_DMA1) {
MXC_NVIC_SetVector(MXC_DMA_CH_GET_IRQ(channel), MXC_UART_RevA_DMA1_Handler);
}
#else
// Only one DMA instance, we can point direct to MXC_DMA_Handler
MXC_NVIC_SetVector(MXC_UART_RevA_DMA0_Handler, MXC_DMA_Handler);
Jake-Carter marked this conversation as resolved.
Show resolved Hide resolved
#endif // MXC_DMA_INSTANCES > 1

#else
// TODO(JC): RISC-V

#endif // __arm__
}

int MXC_UART_RevA_ReadRXFIFODMA(mxc_uart_reva_regs_t *uart, mxc_dma_regs_t *dma,
unsigned char *bytes, unsigned int len,
mxc_uart_dma_complete_cb_t callback, mxc_dma_config_t config)
Expand All @@ -565,11 +620,24 @@ int MXC_UART_RevA_ReadRXFIFODMA(mxc_uart_reva_regs_t *uart, mxc_dma_regs_t *dma,
return E_NULL_PTR;
}

if (states[uart_num].auto_dma_handlers) {
/* Acquire channel */
#if TARGET_NUM == 32665
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd like to avoid part specific code in the _revX.c files. Can this condition be based on MXC_DMA_INSTANCES instead?

channel = MXC_DMA_AcquireChannel(dma);
channel = MXC_DMA_AcquireChannel(dma);
Jake-Carter marked this conversation as resolved.
Show resolved Hide resolved
#else
channel = MXC_DMA_AcquireChannel();
channel = MXC_DMA_AcquireChannel();
#endif
MXC_UART_RevA_SetRXDMAChannel(uart, channel);
/* (JC) Since we're automatically acquiring a channel here, we need the ISR for that channel to call MXC_DMA_Handler. */
MXC_UART_RevA_DMA_SetupAutoHandlers(dma, channel);
} else {
/* Rely on application-defined handlers. */
if (states[uart_num].channelRx < 0)
return E_BAD_STATE;
channel = states[uart_num].channelRx;
}

// states[uart_num].channelRx = channel;

config.ch = channel;

Expand All @@ -583,7 +651,6 @@ int MXC_UART_RevA_ReadRXFIFODMA(mxc_uart_reva_regs_t *uart, mxc_dma_regs_t *dma,
srcdst.dest = bytes;
srcdst.len = len;

states[uart_num].channelRx = channel;
MXC_DMA_ConfigChannel(config, srcdst);
MXC_DMA_SetCallback(channel, MXC_UART_DMACallback);
Jake-Carter marked this conversation as resolved.
Show resolved Hide resolved
MXC_DMA_EnableInt(channel);
Expand Down Expand Up @@ -617,12 +684,63 @@ unsigned int MXC_UART_RevA_WriteTXFIFO(mxc_uart_reva_regs_t *uart, unsigned char
return written;
}

int MXC_UART_RevA_SetAutoDMAHandlers(mxc_uart_reva_regs_t *uart, bool enable)
{
int n = MXC_UART_GET_IDX((mxc_uart_regs_t *)uart);
if (n < 0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These checks could be asserts. They are not really time critical, though, so I'll leave the final decision to you.

return E_BAD_PARAM;

states[n].auto_dma_handlers = enable;

return E_NO_ERROR;
}

int MXC_UART_RevA_SetTXDMAChannel(mxc_uart_reva_regs_t *uart, unsigned int channel)
{
int n = MXC_UART_GET_IDX((mxc_uart_regs_t *)uart);
if (n < 0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here is another place where ASSERT may be better. I see other places (not just in the code this PR touches) that could be ASSERTs also. IMO, anything that checks to see if a valid UART instance was passed in is better as an ASSERT.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lorne-maxim I ended up purging the asserts except for once in the Init functions. The compiler should catch those cases as type-cast mismatch, so I think the checks for a valid UART instance in every function were overkill anyways...

It reduces our kid size pretty significantly, which is nice

return E_BAD_PARAM;

states[n].channelTx = channel;

return E_NO_ERROR;
}

int MXC_UART_RevA_GetTXDMAChannel(mxc_uart_reva_regs_t *uart)
{
int n = MXC_UART_GET_IDX((mxc_uart_regs_t *)uart);
if (n < 0)
return E_BAD_PARAM;

return states[n].channelTx;
}

int MXC_UART_RevA_SetRXDMAChannel(mxc_uart_reva_regs_t *uart, unsigned int channel)
{
int n = MXC_UART_GET_IDX((mxc_uart_regs_t *)uart);
if (n < 0)
return E_BAD_PARAM;

states[n].channelRx = channel;

return E_NO_ERROR;
}

int MXC_UART_RevA_GetRXDMAChannel(mxc_uart_reva_regs_t *uart)
{
int n = MXC_UART_GET_IDX((mxc_uart_regs_t *)uart);
if (n < 0)
return E_BAD_PARAM;

return states[n].channelRx;
}

unsigned int MXC_UART_RevA_WriteTXFIFODMA(mxc_uart_reva_regs_t *uart, mxc_dma_regs_t *dma,
unsigned char *bytes, unsigned int len,
mxc_uart_dma_complete_cb_t callback,
mxc_dma_config_t config)
{
uint8_t channel;
uint8_t channel = -1;
Jake-Carter marked this conversation as resolved.
Show resolved Hide resolved
mxc_dma_srcdst_t srcdst;

int uart_num = MXC_UART_GET_IDX((mxc_uart_regs_t *)uart);
Expand All @@ -635,11 +753,22 @@ unsigned int MXC_UART_RevA_WriteTXFIFODMA(mxc_uart_reva_regs_t *uart, mxc_dma_re
return E_NULL_PTR;
}

if (states[uart_num].auto_dma_handlers) {
/* Acquire channel */
Jake-Carter marked this conversation as resolved.
Show resolved Hide resolved
#if TARGET_NUM == 32665
channel = MXC_DMA_AcquireChannel(dma);
channel = MXC_DMA_AcquireChannel(dma);
#else
channel = MXC_DMA_AcquireChannel();
channel = MXC_DMA_AcquireChannel();
#endif
MXC_UART_RevA_SetTXDMAChannel(uart, channel); // Set state variable
/* (JC) Since we're automatically acquiring a channel here, we need the ISR for that channel to call MXC_DMA_Handler.*/
MXC_UART_RevA_DMA_SetupAutoHandlers(dma, channel);
} else {
/* Rely on application-defined handlers (from SetTXDMAChannel) */
if (states[uart_num].channelTx < 0)
return E_BAD_STATE;
channel = MXC_UART_RevA_GetTXDMAChannel(uart);
}

config.ch = channel;

Expand All @@ -653,7 +782,6 @@ unsigned int MXC_UART_RevA_WriteTXFIFODMA(mxc_uart_reva_regs_t *uart, mxc_dma_re
srcdst.source = bytes;
srcdst.len = len;

states[uart_num].channelTx = channel;
MXC_DMA_ConfigChannel(config, srcdst);
MXC_DMA_SetCallback(channel, MXC_UART_DMACallback);
MXC_DMA_EnableInt(channel);
Expand Down Expand Up @@ -942,6 +1070,8 @@ int MXC_UART_RevA_TransactionDMA(mxc_uart_reva_req_t *req, mxc_dma_regs_t *dma)
}
}

states[uart_num].req = req; // Callback lookups are dependent saved state info

MXC_UART_DisableInt((mxc_uart_regs_t *)(req->uart), 0xFFFFFFFF);
MXC_UART_ClearFlags((mxc_uart_regs_t *)(req->uart), 0xFFFFFFFF);

Expand Down Expand Up @@ -996,21 +1126,22 @@ void MXC_UART_RevA_DMACallback(int ch, int error)
mxc_uart_reva_req_t *temp_req;

for (int i = 0; i < MXC_UART_INSTANCES; i++) {
if (states[i].channelTx == ch) {
if (states[i].channelTx == ch || states[i].channelRx == ch) {
//save the request
temp_req = states[i].req;
// Callback if not NULL
if (temp_req->callback != NULL) {
temp_req->callback((mxc_uart_req_t *)temp_req, E_NO_ERROR);
}
break;
} else if (states[i].channelRx == ch) {
//save the request
temp_req = states[i].req;
// Callback if not NULL
if (temp_req->callback != NULL) {
temp_req->callback((mxc_uart_req_t *)temp_req, E_NO_ERROR);

if (states[i].auto_dma_handlers) {
MXC_DMA_ReleaseChannel(ch);
if (ch == states[i].channelRx)
states[i].channelRx = -1;
else
states[i].channelTx = -1;
}

break;
}
}
Expand Down
6 changes: 6 additions & 0 deletions Libraries/PeriphDrivers/Source/UART/uart_reva.h
Original file line number Diff line number Diff line change
Expand Up @@ -112,4 +112,10 @@ int MXC_UART_RevA_TxAsyncCallback(mxc_uart_reva_regs_t *uart, int retVal);
int MXC_UART_RevA_RxAsyncCallback(mxc_uart_reva_regs_t *uart, int retVal);
void MXC_UART_RevA_DMACallback(int ch, int error);

int MXC_UART_RevA_SetAutoDMAHandlers(mxc_uart_reva_regs_t *uart, bool enable);
int MXC_UART_RevA_SetTXDMAChannel(mxc_uart_reva_regs_t *uart, unsigned int channel);
int MXC_UART_RevA_GetTXDMAChannel(mxc_uart_reva_regs_t *uart);
int MXC_UART_RevA_SetRXDMAChannel(mxc_uart_reva_regs_t *uart, unsigned int channel);
int MXC_UART_RevA_GetRXDMAChannel(mxc_uart_reva_regs_t *uart);

#endif // LIBRARIES_PERIPHDRIVERS_SOURCE_UART_UART_REVA_H_