2021-02-28 10:43 PM
Hello Folks,
I am working on one project, in which we are using STM32L010C6T6 Controller connected with the Quectel LPWA module.
Basically, all we are doing is to turn it on the LPWA module, connect with a cloud and send the data and receive the data from our mobile application using UART Communication.
It turns on and connected with the cloud for 10 min. and move into sleep mode. Again after 30 sec, it wakes up again and starts the cycle again.
Every time, when it connects with the cloud through MQTT, I send battery data from my device via UART.
But after putting our device in run mode for more than 30 hours to 40 hours, it moves into hard fault function.
I tried to track the problem one time when it was on debug mode. And found out there was a problem with the UART Transmission handler. It is going in the wrong condition and gives me a hard fault error.
HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, uint8_t *pData, uint16_t Size)
{
/* Check that a Tx process is not already ongoing */
if (huart->gState == HAL_UART_STATE_READY)
{
if ((pData == NULL) || (Size == 0U))
{
return HAL_ERROR;
}
/* In case of 9bits/No Parity transfer, pData buffer provided as input parameter
should be aligned on a u16 frontier, as data to be filled into TDR will be
handled through a u16 cast. */
if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
{
if ((((uint32_t)pData) & 1) != 0)
{
return HAL_ERROR;
}
}
/* Process Locked */
__HAL_LOCK(huart);
huart->pTxBuffPtr = pData;
huart->TxXferSize = Size;
huart->TxXferCount = Size;
huart->TxISR = NULL;
huart->ErrorCode = HAL_UART_ERROR_NONE;
huart->gState = HAL_UART_STATE_BUSY_TX;
/* Set the Tx ISR function pointer according to the data word length */
if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
{
huart->TxISR = UART_TxISR_16BIT;
}
else
{
huart->TxISR = UART_TxISR_8BIT;
}
/* Process Unlocked */
__HAL_UNLOCK(huart);
/* Enable the Transmit Data Register Empty interrupt */
SET_BIT(huart->Instance->CR1, USART_CR1_TXEIE);
return HAL_OK;
}
else
{
return HAL_BUSY;
}
}
Please check bold lines, this is where it was gone wrong with the same data which I send every in10 min. But gives me an error after around 2 days.
Check the below function, This is how my data is sending and receiving after it. I have a string of around 64bytes in uint8_t data type.
void bg95_tx(uint8_t *command, uint16_t cmd_len)
{
HAL_UART_Transmit_IT(&huart2, command, cmd_len);
HAL_UART_Receive_IT(&huart2, &rx_data, 1);
}
I think it should go in else condition of below in handler call. And it is going everytime.
/* Set the Tx ISR function pointer according to the data word length */
if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
{
huart->TxISR = UART_TxISR_16BIT;
}
else
{
huart->TxISR = UART_TxISR_8BIT;
}
But sometimes at the time of the hard fault, it was gone in if condition and moves into hard default function.
Can you please elaorate, why it is going in wrong condition, and what is meaning of,
if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
Please help me to solve this hard fault problem, what is the possibility for hard fault and how can i solve it.
What can I add in the hard fault function to make it restart again. Already using restart function from startup file, but it still not resetting itself.
Kindly please help as soon as possible. And let me know if you need more information.
Code level is LEVEL 0, and 27kb is code size.
Thanks and regards,
Reena Patel
2021-03-01 07:03 AM
So you are NOT using 9-bit data, correct? Then if the UART code goes into the "16bit data" condition, it probably means that your huart->Init structure has been changed or corrupted. Set a breakpoint on that line and see see what the structure contains. Then the hard work of finding what caused the change. Usually stray pointers.
2021-03-01 09:29 AM
Use a effective Hard Fault handler that can output useful diagnostics at the site of the fault. I've published several to the forum on multiple occasions.
The CM0 is going to be highly sensitive to buffer alignment, make sure you're not doing 16 or 32-bit reads on unaligned addresses.
ie uint16_t foo = *((uint16_t *)pData); // ie casting an 8-bit, or unaligned pointer, to a pointer that actually needs to be aligned for the architecture in play.
NVIC_SystemReset() or equivalent should work to reset the processor, provided you AREN'T driving NRST with a HIGH signal with a push-pull driver.