Hello,
I am trying to get the SAI demo code running within an MQX task on a TWR-K64F120M. The normal demo works fine, but in my own project which includes MQX, the first I2C register write causes a problem. Stepping through with the debugger it just hangs at I2C_DRV_SendAddress. Inside this function, the first call to I2C_HAL_WriteByte succeeds, but the second hangs. interrupting in the debugger just shows it somewhere in the kernel.
Breakpoint 2, I2C_DRV_SendAddress (instance=0, device=0x1fff10a0 <g_codecHandler+4>, cmdBuff=0x1fff8e40 "", cmdSize=2,
direction=kI2CSend, timeout_ms=4294967295)
at KSDK_1.2.0/platform/drivers/src/i2c/fsl_i2c_master_driver.c:508
508 assert(instance < I2C_INSTANCE_COUNT);
(gdb) n
510 I2C_Type * base = g_i2cBase[instance];
(gdb) n
512 i2c_master_state_t * master = (i2c_master_state_t *)g_i2cStatePtr[instance];
(gdb) n
516 uint8_t addrBuff[2] = {0};
(gdb) n
517 uint8_t addrSize = 0;
(gdb) n
518 bool isMainXferBlocking = master->isBlocking;
(gdb) n
521 master->isRequesting = true;
(gdb) n
522 master->isBlocking = true;
(gdb) n
527 directionBit = (direction == kI2CReceive) ? 0x1U : 0x0U;
(gdb) n
530 is10bitAddr = ((device->address >> 10U) == 0x1EU) ? true : false;
(gdb) n
533 if (is10bitAddr)
(gdb) n
540 addrByte1 = (uint8_t)device->address;
(gdb) n
546 addrByte1 = addrByte1 << 1U;
(gdb) n
549 addrByte1 |= (uint8_t)((is10bitAddr || cmdBuff) ? 0U : directionBit);
(gdb) n
552 addrBuff[addrSize++] = addrByte1;
(gdb) n
554 if (is10bitAddr)
(gdb) n
561 master->txBuff = addrBuff;
(gdb) n
562 master->txSize = addrSize;
(gdb) n
565 I2C_HAL_WriteByte(base, addrBuff[0]);
(gdb) n
568 I2C_DRV_MasterWait(instance, timeout_ms);
(gdb) n
571 if ((master->status == kStatus_I2C_Success) && cmdBuff)
(gdb) n
573 master->txBuff = cmdBuff;
(gdb) n
574 master->txSize = cmdSize;
(gdb) n
577 I2C_HAL_WriteByte(base, *cmdBuff);
(gdb) n
580 I2C_DRV_MasterWait(instance, timeout_ms);
(gdb) n
^C
Program received signal SIGTRAP, Trace/breakpoint trap.
0x00014f76 in _int_default_isr (vector_number=0x3 <__isr_vector+3>)
at KSDK_1.2.0/rtos/mqx/mqx/source/kernel/int.c:64
64 _GET_KERNEL_DATA(kernel_data);
I have also traced this through from the IRQ side. I see I2C0_IRQHandler get called. This makes it all the way down through I2C_DRV_CompleteTransfer and ultimately hangs inside OSA_SemaPost. Diving into OSA_SemaPost leads me down into _lwsem_post where everything seems to work until it gets to _INT_ENABLE() and hangs.
I'm not really sure where to go from here, so any advice would be appreciated.
Thanks
Solved! Go to Solution.
Renaming the ISR is what I believe you're supposed to do per this writeup:
So I did the same thing with edma and i2s ISRs and now things seem to work. It wasn't enough just to define my own copies of thes functions and not compile in the built in SDK versions. I had to actually rename the ISR before things would start working.
I'm glad it works, but it doesn't seem like the proper fix. Does anyone know what is really going on here?
Renaming the ISR is what I believe you're supposed to do per this writeup:
"However, when using MQX this is no longer possible as the MQX kernel requires those IRQHandler names for its own interrupt handling. It is therefore necessary for the application developer to use a different name for the peripheral driver IRQ handler. The convention used in KSDK is pre-append the IRQHandler name with MQX"
Well, I guess I need to read more of the MQX documentation. Thanks for pointing me to that.
So it seems to be related to the interrupt handler. I was using the I2C handlers defined in drivers/i2c/fsl_i2c_irq.c. I was able to get breakpoints to hit in these calls, so they seemed to be correct and even tried adding OSA_InstallIntHandler(I2C0_IRQn, I2C0_IRQHandler); for good measure. Basically, If I compile in fsl_i2c_irq.c, no matter what I do, nothing works.
My solution was to create my own functionally equivalent copy of the interrupt handler and register it with manually:
void MQX_I2C0_IRQHandler(void) { I2C_DRV_IRQHandler(I2C0_IDX); }
...
OSA_InstallIntHandler(I2C0_IRQn, MQX_I2C0_IRQHandler);
This got me past configuration, but now I get a hangup on DMA. I'm going to try manually registering those ISRs next.