Dear Victor
Thank you. More on this problem. The platform is FRDM-K64F. It is a touch sensor interface with PTE24(SCL), PTE25(SDA), reset to sensor (PTB23), IRQ (PTD1).
PTD1 configured as a GPIO with code here:
//IRQ interface as a GPIO with interrupt enabled
const gpio_input_pin_user_config_t irqPin =
{
.pinName = GPIO_MAKE_PIN(HW_GPIOD, 1),
.config.isPullEnable = true,
.config.pullSelect = kPortPullUp,
.config.isPassiveFilterEnabled = false,
.config.interrupt = kPortIntFallingEdge,
};
The interrupt function is like:
void PORTD_IRQHandler(void)
{
PORT_HAL_ClearPinIntFlag(PORTD_BASE, 1);
debug_func();
HAL_I2CWriteRegister(reg, val);
}
I2C is implemented with CMSIS with definition:
/* I2C Driver */
#define _I2C_Driver_(n) Driver_I2C##n
#define I2C_Driver_(n) _I2C_Driver_(n)
extern ARM_DRIVER_I2C I2C_Driver_(0);
#define ptrI2C (&I2C_Driver_(0))
No I2C interrupt enabled, I think. Instead, this touch sensor will assert the IRQ pin from high to low whenever a finger is detected. That is why kPortIntFallingEdge is there in const gpio_input_pin_user_config_t irqPin.
HAL_I2CWriteRegister(uint8_t reg, uint16_t val) is declared like this:
static bool HAL_I2CWriteRegister(uint8_t reg, uint16_t val)
{
uint8_t data[3] = {reg, (uint8_t)(val>>8), (uint8_t)val};
ptrI2C->MasterTransmit(0x48, data, 3, false);
while (ptr2C->GetStatus().busy);
if(ptrI2C->GetDataCount() !=3)
{
return -1;
}
return 0;
}
This same I2C write function works 100% OK in the main loop. It also works in a thread when Bare Metal Abstraction Layer is used, but not in the ISR. It always hang up at the infinite while loop while (ptr2C->GetStatus().busy) in ISR. As a debug action I placed another led toggle function debug_func() in the same ISR which works OK.
This puzzles me a lot.
I agree that semaphore can be used but, why the I2C function doesn't work in ISR? I have implemented the same code in Texas Instruments Tiva C and it works OK, even though there is a blocking function in ISR like the I2C...
John