AnsweredAssumed Answered

KL25Z I2C RTOS api hangs forever (HardFault)

Question asked by jm san on Jun 16, 2017
Latest reply on Jun 30, 2017 by jm san

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.

Outcomes