I am trying to port the KL25Z Accelerometer I2C example to FreeRTOS so that instead of using the SDK's I2C driver it uses the FreeRTOS's I2C driver.
After configuring I2C pins and release I2C bus I try to Init the IC2 RTOS driver.
I2C_MasterGetDefaultConfig(&masterConfig);
masterConfig.baudRate_Bps = I2C_BAUDRATE;
sourceClock = ACCEL_I2C_CLK_FREQ;
//I2C_MasterInit(BOARD_ACCEL_I2C_BSEADDR, &masterConfig, sourceClock);
NVIC_SetPriority(ACCEL_I2C_MASTER_IRQN, configMAX_PRIORITIES - 1);status = I2C_RTOS_Init(&master_rtos_handle, ACCEL_I2C_MASTER, &masterConfig, sourceClock);
status reported to be 0x00
Then I configure the first transfer message
i2c_master_transfer_t masterXfer;
memset(&masterXfer, 0, sizeof(masterXfer));masterXfer.slaveAddress = 0x1DU;
masterXfer.direction = kI2C_Write;
masterXfer.subaddress = 0;
masterXfer.subaddressSize = 0;
masterXfer.data = &who_am_i_reg;
masterXfer.dataSize = 1;
masterXfer.flags = kI2C_TransferNoStopFlag;
This message is only to check that the Accelerometer is there. The slave Adress direction is already set to 0x1DU because I want to jump the part of the example which tries a set of addresses to check devices.
Then I start the transfer:
g_m_handle = &master_rtos_handle.drv_handle;
status = I2C_RTOS_Transfer(&master_rtos_handle, &masterXfer);
The task goes inside the I2C_RTOS_Transfer takes the semaphore and starts:
status = I2C_MasterTransferNonBlocking(handle->base, &handle->drv_handle, transfer);
if (status != kStatus_Success)
{
xSemaphoreGive(handle->mutex);
return status;
}
status again reported to be 0x00 so the transfer is a sucess.
But then the task tries to Take the semaphore again but the semaphore is never given.
/* Wait for transfer to finish */
xSemaphoreTake(handle->semaphore, portMAX_DELAY);
If I am not mistaken after the I2C_MasterTransferNonBlocking is completed the task should call I2C_RTOS_Callback which in turn should Give the Semaphore.
static void I2C_RTOS_Callback(I2C_Type *base, i2c_master_handle_t *drv_handle, status_t status, void *userData)
{i2c_rtos_handle_t *handle = (i2c_rtos_handle_t *)userData;
BaseType_t reschedule;
handle->async_status = status;
xSemaphoreGiveFromISR(handle->semaphore, &reschedule);
portYIELD_FROM_ISR(reschedule);}
But the I2C_RTOS_Callback is never called so the semaphore is never given and so the code hangs in
xSemaphoreTake(handle->semaphore, portMAX_DELAY);
I tried the code with a set of priorities higher and lower than 5, but none seem to work.The debugger trace shows that the program follows this path:
xSemaphoreTake -> xQueueGenericReceive --> vTaskPlaceOnEventList ---> vListInsert --> pxNewListItem->pxNext = pxIterator->pxNext; --> ldr r0,=HardFault_Handler
What on earth I am missing here?
Thank you.
Solved! Go to Solution.
Hi, thank you for the reply, I just resolved this issue calling the RTOS code after initialitzating the RTOS environment and the scheduler.
It was a problem of design.
Hi, Jm,
I have the FRDM board of Kl family, can you post your project here so that I can help to debug to track the cause of the hardfault event?
BR
Xiangjun Rong
Hi, thank you for the reply, I just resolved this issue calling the RTOS code after initialitzating the RTOS environment and the scheduler.
It was a problem of design.
Could you upload an example or explain detailed how you solved this? I have the same problem and can't seem to resolve it.
Update 1: The problem seems to be that if I try to use (transfer - receive functions ) I2C RTOS driver at the main loop before creating the tasks and starting the scheduler the system seems to enter that hard fault in the xQueue.
I think that my design is incorrect due to whatever i am missing to allow me use I2C RTOS driver (transfer - receive functions) at the main function before starting the task scheduler. I think in the rtos examples provided by the SDK they all configure RTOS driver in the main loop and then use the transfer receive functions inside the task after starting the scheduler an the task themselves.
I did that design only because I need to send and receive to configure the external devices before entering the reading tasks. That's it just wanting to configure things before starting all scheduler stuff.
How to allow the RTOS use IRQ - Callbacks at main before starting the scheduler?