Hi, I'm new to the platform and have been developing a few tasks for almost a month on the S32K116 EVB, but I'm having trouble with the UART driver. I'm trying to set an UART communication but I can send but I can't receive. I have been trying to follow the platform examples but I get the same issue with the examples: the EVB sends without a problem but doesn't receive a thing.
Thank you beforehand for your comments.
Solved! Go to Solution.
Hello Daniel. Thank you for your reply!
I used the platform driver example (attached below). I wil try to update and look for that project example, since I don't have UART project examples. just driver examples.
I'm checking communication using a logic analyzer and also debugging to test if my receiving buffer is being populated or not. So far, my results have been: If I send a message before trying to receive something, my receiving buffer is filled with as many zeroes as the amount of bytes I sent in the message before trying to receive. If I don't send a message before trying to receive then I don't even receive zeroes.
This is the receive part in main.c
while (1)
{
/* Receive and store data byte by byte until new line character is received,
* or the buffer becomes full (256 characters received)
*/
LPUART_DRV_ReceiveData(INST_LPUART1, buffer, 1U);
/* Wait for transfer to be completed */
while(LPUART_DRV_GetReceiveStatus(INST_LPUART1, &bytesRemaining) == STATUS_BUSY);
/* Check the status */
status = LPUART_DRV_GetReceiveStatus(INST_LPUART1, &bytesRemaining);
if (status != STATUS_SUCCESS)
{
/* If an error occurred, send the error message and exit the loop */
LPUART_DRV_SendDataBlocking(INST_LPUART1, (uint8_t *)errorMsg, strlen(errorMsg), TIMEOUT);
break;
}
/* Append string terminator to the received data */
bufferIdx++;
buffer[bufferIdx] = 0U;
/* If the received string is "Hello Board", send back "Hello World" */
if(strcmp((char *)buffer, "Hello Board\n") == 0)
{
strcpy((char *)buffer, "Hello World\n");
}
/* Send the received data back */
LPUART_DRV_SendDataBlocking(INST_LPUART1, buffer, bufferIdx, TIMEOUT);
/* Reset the buffer index to start a new reception */
bufferIdx = 0U;
}
/*** Don't write any code pass this line, or it will be deleted during code generation. ***/
/*** RTOS startup code. Macro PEX_RTOS_START is defined by the RTOS component. DON'T MODIFY THIS CODE!!! ***/
#ifdef PEX_RTOS_START
PEX_RTOS_START(); /* Startup of the selected RTOS. Macro is defined by the RTOS component. */
#endif
/*** End of RTOS startup code. ***/
/*** Processor Expert end of main routine. DON'T MODIFY THIS CODE!!! ***/
for(;;) {
if(exit_code != 0) {
break;
}
}
Here is the receive data function:
status_t LPUART_DRV_ReceiveData(uint32_t instance,
uint8_t * rxBuff,
uint32_t rxSize)
{
DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
DEV_ASSERT(rxBuff != NULL);
status_t retVal = STATUS_SUCCESS;
lpuart_state_t * lpuartState = (lpuart_state_t *)s_lpuartStatePtr[instance];
/* Indicates this is a non-blocking transaction. */
lpuartState->isRxBlocking = false;
DEV_ASSERT((lpuartState->transferType == LPUART_USING_INTERRUPTS) ||
(lpuartState->transferType == LPUART_USING_DMA));
if (lpuartState->transferType == LPUART_USING_INTERRUPTS)
{
/* Start the reception process using interrupts */
retVal = LPUART_DRV_StartReceiveDataUsingInt(instance, rxBuff, rxSize);
}
#if FEATURE_LPUART_HAS_DMA_ENABLE
else
{
/* Start the reception process using DMA */
retVal = LPUART_DRV_StartReceiveDataUsingDma(instance, rxBuff, rxSize);
}
#endif
return retVal;
}
Here is the receive data using interruptions:
static status_t LPUART_DRV_StartReceiveDataUsingInt(uint32_t instance,
uint8_t * rxBuff,
uint32_t rxSize)
{
DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
DEV_ASSERT(rxBuff != NULL);
lpuart_state_t * lpuartState = (lpuart_state_t *)s_lpuartStatePtr[instance];
LPUART_Type * base = s_lpuartBase[instance];
/* Check it's not busy receiving data from a previous function call */
if (lpuartState->isRxBusy)
{
return STATUS_BUSY;
}
/* Check the validity of the parameters */
DEV_ASSERT(rxSize > 0U);
DEV_ASSERT((lpuartState->bitCountPerChar == LPUART_8_BITS_PER_CHAR) ||
((rxSize & 1U) == 0U));
/* Initialize the module driver state struct to indicate transfer in progress
* and with the buffer and byte count data. */
lpuartState->isRxBusy = true;
lpuartState->rxBuff = rxBuff;
lpuartState->rxSize = rxSize;
lpuartState->receiveStatus = STATUS_BUSY;
/* Enable the receiver */
LPUART_SetReceiverCmd(base, true);
/* Enable error interrupts */
LPUART_SetErrorInterrupts(base, true);
/* Enable receive data full interrupt */
LPUART_SetIntMode(base, LPUART_INT_RX_DATA_REG_FULL, true);
return STATUS_SUCCESS;
}
Finally, those are used to receive here, in the interrup handler:
static void LPUART_DRV_RxIrqHandler(uint32_t instance)
{
lpuart_state_t * lpuartState = (lpuart_state_t *)s_lpuartStatePtr[instance];
/* Get data and put in receive buffer */
LPUART_DRV_GetData(instance);
/* Update the internal state */
if (lpuartState->bitCountPerChar == LPUART_8_BITS_PER_CHAR)
{
++lpuartState->rxBuff;
--lpuartState->rxSize;
}
else
{
lpuartState->rxBuff = &lpuartState->rxBuff[2];
lpuartState->rxSize -= 2U;
}
/* Check if this was the last byte in the current buffer */
if (lpuartState->rxSize == 0U)
{
/* Invoke callback if there is one (callback may reset the rx buffer for continuous reception) */
if (lpuartState->rxCallback != NULL)
{
lpuartState->rxCallback(lpuartState, UART_EVENT_RX_FULL, lpuartState->rxCallbackParam);
}
}
/* Finish reception if this was the last byte received */
if (lpuartState->rxSize == 0U)
{
/* Complete transfer (disable rx logic) */
LPUART_DRV_CompleteReceiveDataUsingInt(instance);
/* Invoke callback if there is one */
if (lpuartState->rxCallback != NULL)
{
lpuartState->rxCallback(lpuartState, UART_EVENT_END_TRANSFER, lpuartState->rxCallbackParam);
}
}
}
The GetData function accesses the register in which the receive data should be allocated. I'm sorry if I pasted too much code.
Update: I downloaded S32DS v2.2 and checked that example. It still isn't working. Do I have to change something to make it work?
Update 2: Somehow the debugger is interferring with instance LPUART0, so I wasn't able to receive through PORTB0 but I was able to receive through USB instead. Thank you for your help!
Thank you,
Regards, Jose.
Hello Jose,
Have you tried the simple S32K116_Project_LPUART example from S32DS v2.2:
Do you monitor the RX pin with an oscilloscope / logic analyzer?
Can you share a test code?
Thank you,
Regards,
Daniel
Hello Daniel. Thank you for your reply!
I used the platform driver example (attached below). I wil try to update and look for that project example, since I don't have UART project examples. just driver examples.
I'm checking communication using a logic analyzer and also debugging to test if my receiving buffer is being populated or not. So far, my results have been: If I send a message before trying to receive something, my receiving buffer is filled with as many zeroes as the amount of bytes I sent in the message before trying to receive. If I don't send a message before trying to receive then I don't even receive zeroes.
This is the receive part in main.c
while (1)
{
/* Receive and store data byte by byte until new line character is received,
* or the buffer becomes full (256 characters received)
*/
LPUART_DRV_ReceiveData(INST_LPUART1, buffer, 1U);
/* Wait for transfer to be completed */
while(LPUART_DRV_GetReceiveStatus(INST_LPUART1, &bytesRemaining) == STATUS_BUSY);
/* Check the status */
status = LPUART_DRV_GetReceiveStatus(INST_LPUART1, &bytesRemaining);
if (status != STATUS_SUCCESS)
{
/* If an error occurred, send the error message and exit the loop */
LPUART_DRV_SendDataBlocking(INST_LPUART1, (uint8_t *)errorMsg, strlen(errorMsg), TIMEOUT);
break;
}
/* Append string terminator to the received data */
bufferIdx++;
buffer[bufferIdx] = 0U;
/* If the received string is "Hello Board", send back "Hello World" */
if(strcmp((char *)buffer, "Hello Board\n") == 0)
{
strcpy((char *)buffer, "Hello World\n");
}
/* Send the received data back */
LPUART_DRV_SendDataBlocking(INST_LPUART1, buffer, bufferIdx, TIMEOUT);
/* Reset the buffer index to start a new reception */
bufferIdx = 0U;
}
/*** Don't write any code pass this line, or it will be deleted during code generation. ***/
/*** RTOS startup code. Macro PEX_RTOS_START is defined by the RTOS component. DON'T MODIFY THIS CODE!!! ***/
#ifdef PEX_RTOS_START
PEX_RTOS_START(); /* Startup of the selected RTOS. Macro is defined by the RTOS component. */
#endif
/*** End of RTOS startup code. ***/
/*** Processor Expert end of main routine. DON'T MODIFY THIS CODE!!! ***/
for(;;) {
if(exit_code != 0) {
break;
}
}
Here is the receive data function:
status_t LPUART_DRV_ReceiveData(uint32_t instance,
uint8_t * rxBuff,
uint32_t rxSize)
{
DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
DEV_ASSERT(rxBuff != NULL);
status_t retVal = STATUS_SUCCESS;
lpuart_state_t * lpuartState = (lpuart_state_t *)s_lpuartStatePtr[instance];
/* Indicates this is a non-blocking transaction. */
lpuartState->isRxBlocking = false;
DEV_ASSERT((lpuartState->transferType == LPUART_USING_INTERRUPTS) ||
(lpuartState->transferType == LPUART_USING_DMA));
if (lpuartState->transferType == LPUART_USING_INTERRUPTS)
{
/* Start the reception process using interrupts */
retVal = LPUART_DRV_StartReceiveDataUsingInt(instance, rxBuff, rxSize);
}
#if FEATURE_LPUART_HAS_DMA_ENABLE
else
{
/* Start the reception process using DMA */
retVal = LPUART_DRV_StartReceiveDataUsingDma(instance, rxBuff, rxSize);
}
#endif
return retVal;
}
Here is the receive data using interruptions:
static status_t LPUART_DRV_StartReceiveDataUsingInt(uint32_t instance,
uint8_t * rxBuff,
uint32_t rxSize)
{
DEV_ASSERT(instance < LPUART_INSTANCE_COUNT);
DEV_ASSERT(rxBuff != NULL);
lpuart_state_t * lpuartState = (lpuart_state_t *)s_lpuartStatePtr[instance];
LPUART_Type * base = s_lpuartBase[instance];
/* Check it's not busy receiving data from a previous function call */
if (lpuartState->isRxBusy)
{
return STATUS_BUSY;
}
/* Check the validity of the parameters */
DEV_ASSERT(rxSize > 0U);
DEV_ASSERT((lpuartState->bitCountPerChar == LPUART_8_BITS_PER_CHAR) ||
((rxSize & 1U) == 0U));
/* Initialize the module driver state struct to indicate transfer in progress
* and with the buffer and byte count data. */
lpuartState->isRxBusy = true;
lpuartState->rxBuff = rxBuff;
lpuartState->rxSize = rxSize;
lpuartState->receiveStatus = STATUS_BUSY;
/* Enable the receiver */
LPUART_SetReceiverCmd(base, true);
/* Enable error interrupts */
LPUART_SetErrorInterrupts(base, true);
/* Enable receive data full interrupt */
LPUART_SetIntMode(base, LPUART_INT_RX_DATA_REG_FULL, true);
return STATUS_SUCCESS;
}
Finally, those are used to receive here, in the interrup handler:
static void LPUART_DRV_RxIrqHandler(uint32_t instance)
{
lpuart_state_t * lpuartState = (lpuart_state_t *)s_lpuartStatePtr[instance];
/* Get data and put in receive buffer */
LPUART_DRV_GetData(instance);
/* Update the internal state */
if (lpuartState->bitCountPerChar == LPUART_8_BITS_PER_CHAR)
{
++lpuartState->rxBuff;
--lpuartState->rxSize;
}
else
{
lpuartState->rxBuff = &lpuartState->rxBuff[2];
lpuartState->rxSize -= 2U;
}
/* Check if this was the last byte in the current buffer */
if (lpuartState->rxSize == 0U)
{
/* Invoke callback if there is one (callback may reset the rx buffer for continuous reception) */
if (lpuartState->rxCallback != NULL)
{
lpuartState->rxCallback(lpuartState, UART_EVENT_RX_FULL, lpuartState->rxCallbackParam);
}
}
/* Finish reception if this was the last byte received */
if (lpuartState->rxSize == 0U)
{
/* Complete transfer (disable rx logic) */
LPUART_DRV_CompleteReceiveDataUsingInt(instance);
/* Invoke callback if there is one */
if (lpuartState->rxCallback != NULL)
{
lpuartState->rxCallback(lpuartState, UART_EVENT_END_TRANSFER, lpuartState->rxCallbackParam);
}
}
}
The GetData function accesses the register in which the receive data should be allocated. I'm sorry if I pasted too much code.
Update: I downloaded S32DS v2.2 and checked that example. It still isn't working. Do I have to change something to make it work?
Update 2: Somehow the debugger is interferring with instance LPUART0, so I wasn't able to receive through PORTB0 but I was able to receive through USB instead. Thank you for your help!
Thank you,
Regards, Jose.
Hello Jose,
So I understand that it works for you through the Virtual serial port.
The PTB0/PTB1 pins are routed to the OpenSDA programmer.
But you don't have to use the pins
Regards,
Daniel