I have two functions; EEPROM_SPI_WriteBuffer(TxBuffer, (uint32_t)0x00, (uint16_t)32); for writing a buffer data to a 24bit adress and EEPROM_SPI_ReadBuffer(RxBuffer, (uint32_t)0x00, (uint16_t)32); for reading that data from that adress.
My issue is that "write" function takes too long to complete if "read" function is called after that function.
Here is the RTOS task:
void StartDefaultTask(void const * argument)
{
/* USER CODE BEGIN 5 */
EEPROM_SPI_INIT(&hspi2);
EEPROM_SPI_WriteBuffer(TxBuffer, (uint32_t)0x00, (uint16_t)32);
osDelay(1000);
/* Infinite loop */
for(;;)
{
EEPROM_SPI_ReadBuffer(RxBuffer, (uint32_t)0x00, (uint16_t)32);
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
osDelay(1000);
}
I can read the data if comment out the write function and write data if I comment out the read function everytime before I run the code.
I am using firebull's code Here
Anyone had any similar problems with this or could tell me where to look?
Related
I am new here, but have often benefited from questions and their results.
Now I have a problem that I can not solve for days. It is about a STM32L431RCT6 with FreeRTOS. There are 3 tasks running on it. Two of them are dedicated to processing CanOpenNode (1 to send data, 1 to receive). One is a custom controller. The code works as it is, but when I enable the CRC unit (MX_CRC_Init()) the problem appears. With the CRC unit enabled, only the task to receive the data from Canopen is executed. The other tasks are set to "Ready". What I notice is that the osDelay() used in the receive task seems to be ignored. It doesn't seem to matter if I use osDelay(1) or osDelay(10000).
void start_CO_rec_Thread(void *argument)
{
/* USER CODE BEGIN start_CO_TI_Thread */
/* Infinite loop */
for(;;)
{
canopen_app_interrupt();
osDelay(1);
}
osThreadTerminate(NULL);
/* USER CODE END start_CO_TI_Thread */
}
Something else is added. If I remove functions and variables in the task by starting an own controller, the processing of the tasks works again. Now I have concluded that the tasks need more stack memory. But this is also not the solution of the puzzle...
Working Code:
void Start_Controller(void *argument)
{
Sensor = new DS18B20(htim6);
Regler = new Smithpredictor(Sensor);
// osTimerStart(LifetimerHandle, 1000);
for(;;)
{
if (global_state==4)
actual_Temperatur = Regler->run(target_Temperature);
osDelay(MBC_intervall_s*1000);
}
osThreadTerminate(NULL);
}
Not Working Code:
void Start_Controller(void *argument)
{
Sensor = new DS18B20(htim6);
Regler = new Smithpredictor(Sensor);
osTimerStart(LifetimerHandle, 1000);
for(;;)
{
if (global_state==4)
actual_Temperatur = Regler->run(target_Temperature);
osDelay(MBC_intervall_s*1000);
}
osThreadTerminate(NULL);
}
I hope someone has an idea how to proceed or can help me. Even if it is just another way to further identify the problem. Maybe I have also committed some stupidity, I am unfortunately not a computer scientist.
I'm using UART RX callback code from here https://www.programmersought.com/article/68737014549/
Looks like this non-blocking RX processing doesn't work in background as expected
/* USER CODE BEGIN USART1_Init 2 */
HAL_UART_Receive_IT(&huart1, (uint8_t *)aRxBuffer1, RXBUFFERSIZE); //This function will turn on the receive interrupt: flag bit UART_IT_RXNE, and set the receive buffer and the maximum amount of data received by the receive buffer */
__HAL_UART_ENABLE_IT(&huart1, UART_IT_RXNE);
/* USER CODE END USART1_Init 2 */
I receive only once and can't process next incoming bytes, because RX buffer keeps only old value.
Is it something with example or HAL's issue?
HAL_UART_Receive_IT() arms the RX interrupt only once. This is the expected behavior. You need to call it again to re-arm the receiver, after you are done processing the receive buffer.
HAL_UART_Receive_IT() Called only once. If you want to receive data continuously after the call, you must call the function again
main()
.....
HAL_UART_Receive_IT(&huart2, &temp_rx, 1);
.....
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
// USART2 Rx Interrupt
if (huart->Instance == USART2) {
HAL_UART_Receive_IT(&huart2, &temp_rx, 1);
}
I'm working on an application where I process commands of fixed length received via UART.
I'm also using FreeRTOS and the task that handles the incoming commands is suspended until the uart interrupt handler is called, so my code is like this
void USART1_IRQHandler()
{
HAL_UART_IRQHandler(&huart1);
}
void HAL_UART_ErrorCallback(UART_HandleTypeDef *huart){
HAL_UART_Receive_IT(&huart1, uart_rx_buf, CMD_LEN);
}
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart){
BaseType_t higherTaskReady = pdFALSE;
HAL_UART_Receive_IT(&huart1, uart_rx_buf, CMD_LEN); //restart interrupt handler
xSemaphoreGiveFromISR(uart_mutex, &higherTaskReady);
portYIELD_FROM_ISR( higherTaskReady); //Relase the semaphore
}
I am using the ErrorCallBack in case if an overflow occurs. Now I successfully catch every correct command, even if they are issued char by char.
However, I'm trying to make the system more error-proof by considering the case where more characters are received than expected.
The command length is 4 but if I receive, for example, 5 chars, then the first 4 is processed normally but when another command is received it starts from the last unprocessed char, so another 3 chars are needed until I can correctly process the commands again.
Luckily, the ErrorCallback is called whenever I receive more than 4 chars, so I know when it happens, but I need a robust way of cleaning the UART buffer so the previous chars are gone.
One solution I can think of is using UART receive 1 char at a time until it can't receive anymore, but is there a better way to simply flush the buffer?
Yes, the problem is the lack of delimiter, because every byte can can carry a value to be processed from 0 to 255. So, how can you detect the inconsistency?
My solution is a checksum byte in the protocol. If the checksum fails, a blocking-mode UART_Receive function is called in order to put the rest of the data from the "system-buffer" to a "disposable-buffer". In my example the fix size of the protocol is 6, I use the UART6 and I have a global variable RxBuffer. Here is the code:
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *UartHandle)
{
if(UartHandle->Instance==USART6) {
if(your_checksum_is_ok) {
// You can process the incoming data
} else {
char TempBuffer;
HAL_StatusTypeDef hal_status;
do {
hal_status = HAL_UART_Receive(&huart6, (uint8_t*)&TempBuffer, 1, 10);
} while(hal_status != HAL_TIMEOUT);
}
HAL_UART_Receive_IT(&huart6, (uint8_t*)RxBuffer, 6);
}
}
void HAL_UART_ErrorCallback(UART_HandleTypeDef *UartHandle) {
if(UartHandle->Instance==USART6) {
HAL_UART_Receive_IT(&huart6, (uint8_t*)RxBuffer, 6);
}
}
I am working on a project which needs data communication between two stm32 (stm32f103rb and stm32f429zg).
I use stm32f103rb-nucleo examples_ll (I2C _OneBoard_Communication_IT) but it works for one byte and after that, it stops working. I want it to work repetitively.
the code structure is exactly in the way the example is written in the folder related to stm32cubemx repository.
I don't know how to make it work in a loop and by pressing the button, communication gets done every time I push the master and slave push buttons.
I have put the master completion callback function here :
void Master_Complete_Callback(void)
{
if(ubNbDataToReceive == 3)
{
/* Prepare the generation of a Non ACKnowledge condition after next received bytes */
LL_I2C_AcknowledgeNextData(I2C1, LL_I2C_NACK);
/* Read character in Receive Data register.
RXNE flag is cleared by reading data in RXDR register */
aReceiveBuffer[ubReceiveIndex++] = LL_I2C_ReceiveData8(I2C1);
ubNbDataToReceive--;
/* Disable Buffer Interrupts */
LL_I2C_DisableIT_BUF(I2C1);
}
else if(ubNbDataToReceive == 2)
{
/* Generate Stop condition */
LL_I2C_GenerateStopCondition(I2C1);
/* Read character from Receive Data register.
RXNE flag is cleared by reading data in RXDR register */
aReceiveBuffer[ubReceiveIndex++] = LL_I2C_ReceiveData8(I2C1);
ubNbDataToReceive--;
/* Read character from shift register.
RXNE flag is cleared by reading data in RXDR register */
aReceiveBuffer[ubReceiveIndex++] = LL_I2C_ReceiveData8(I2C1);
ubNbDataToReceive--;
}
else
{
if(ubNbDataToReceive > 0)
{
/* Read character from shift register.
RXNE flag is cleared by reading data in RXDR register */
aReceiveBuffer[ubReceiveIndex++] = LL_I2C_ReceiveData8(I2C2);
/* Update ubNbDataToReceive variable */
ubNbDataToReceive--;
}
}
if(ubNbDataToReceive == 0)
{
/* (1) Disable I2C1 transfer event/error interrupts:
* - Disable Events Interrupt
* - Disable Error interrupts
*/
LL_I2C_DisableIT_EVT(I2C1);
LL_I2C_DisableIT_ERR(I2C1);
LL_I2C_EnableIT_EVT(I2C1);
LL_I2C_EnableIT_ERR(I2C1);
/* Read Received character.
RXNE flag is cleared by reading of RXDR register */
if(aReceiveBuffer[ubReceiveIndex-1] == SLAVE_BYTE_TO_SEND)
{
/* Turn LED2 On:
* - Expected byte has been received
* - Master Rx sequence completed successfully
*/
//LED_On();
HAL_UART_Transmit_IT(&huart2,(uint8_t*)"#Data transfer is OK!$",strlen("#Data transfer is OK!$"));
ubNbDataToTransmit = sizeof(SLAVE_BYTE_TO_SEND);
ubNbDataToReceive = sizeof(SLAVE_BYTE_TO_SEND);
}
else
{
/* Call Error function */
Error_Callback();
}
}
}
it is easily understood that the end of the transmission process is when I add HAL_UART function to send to serial port the transmission completion.
but after this time , it works one more time and after that it stops.
I have checked the oscilloscope signal show and after the second time transmission SCL pin gets LOW .
Thanks
Did not use LL for a long time, but isnt I2C interrupt disabled after single transfer with LL_I2C_DisableIT_EVT(I2C1);?? Make sure to enable it again before next transmission.
There is such a thing that two master devices cannot communicate each other via I2C bus. Because master devices do not have DEVICE_ADDRESS. Master devices can communicate only slave devices.
I'm using ST STM32F101xB and μC/OS-II, I was having external clock (HSE) on old board and it's running fine. We wanted to use internal clock (HSI) on new board, however, the RTOS (Appmaintask()) doesn't run using internal clock, i have changed my code as below, any idea what's wrong with the change:
void BSP_Init (void)
{
RCC_DeInit();
//RCC_HSEConfig(RCC_HSE_ON);
//RCC_WaitForHSEStartUp();
RCC_HCLKConfig(RCC_SYSCLK_Div1);
RCC_PCLK2Config(RCC_HCLK_Div1); // APB2 clock divide by 1 => 64MHz
RCC_PCLK1Config(RCC_HCLK_Div2); // APB1 clock divide by 2 => 32MHz
FLASH_SetLatency(FLASH_Latency_2);
FLASH_PrefetchBufferCmd(FLASH_PrefetchBuffer_Enable);
//RCC_PLLConfig(RCC_PLLSource_HSE_Div1, RCC_PLLMul_8); // 64MHz
RCC_PLLConfig(RCC_PLLSource_HSI_Div2, RCC_PLLMul_8);
RCC_PLLCmd(ENABLE);
RCC_LSEConfig(RCC_LSE_OFF);
while (RCC_GetFlagStatus(RCC_FLAG_PLLRDY) == RESET) {
;
}
RCC_SYSCLKConfig(RCC_SYSCLKSource_PLLCLK);
while (RCC_GetSYSCLKSource() != 0x08) {
;
}
//Set the Vector Table base location at 0x08000000
//NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);
// Need to finalize and arange priority for each interrupts in future,
// So that 1 interrupt wont blocks another interrupt.
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_3);
}
void main()
{
INT8U err;
cpuObj = new Cstm32f10x();
BSP_Init();
BSP_IntDisAll(); /* Disable all ints until we are ready to accept them. */
OSInit();
err = OSTaskCreateExt (AppMainTask,
(void *)0,
(OS_STK *)&AppMainTaskStk[APP_MAIN_TASK_STK_SIZE-1],
APP_MAIN_TASK_PRIO,
APP_MAIN_TASK_ID,
(OS_STK *)&AppMainTaskStk[0],
APP_MAIN_TASK_STK_SIZE,
(void *)0,
OS_TASK_OPT_STK_CHK | OS_TASK_OPT_STK_CLR);
OSStart(); // Start multitasking (i.e. give control to uC/OS-II)
}
void AppMainTask (void *p_arg)
{
OS_CPU_SysTickInit();
while(TRUE)
{
OSTimeDly(1);
}
}
Thanks.
Setting up of the PLL is normally performed in the CMSIS start-up code provided by ST/ARM. This code executes as part of the runtime environment start-up before main() is called. I recommend that you use this code for chip initialisation since static data initialisation and static object constructors run before main() and will be running before possibly critical initialisation.
The CMSIS with Cortex-M3 core and STM32F1xx specific device support is included in the STM32 Standard Peripheral Library. The file that actually does the work is system_stm32f10x.c. Other functions you are performing in BSP_Init() such as flash latency are also dealt with by the CMSIS start-up code. Even if you customise this code, I strongly recommend that you use this method of early environment initialisation.
Another possibility is to use the STM32CubeMX utility to generate configuration code. This appears to be a replacement for the apparently now unavailable STM32 MicroXplorer utility.