2024-06-25 03:08 AM
Hi There,
We have IO expander that is connected using I2C
File: Application.C has functions for change the IO value of the IO Expander
there is a UART that the user can connect to and change the value of the IO Expander (using CLI)
Following functions are at Application.C file
void PORT_Enable(uint8_t PORT_NUM){
switch (PORT_NUM){
case PORT1:
Set_Bit_IO_Expander2_Status_PDIO(PDIO_Status,PORT_NUM);
PORT_Information[PORT_NUM].Enable_VBUS = 1;
break;
}
}
void Set_Bit_IO_Expander2_Status_PDIO(uint8_t Data,uint8_t Index)
{
PDIO_SET_RESET[0] = OUTPUT_PORT1; //write command to output Port 1.0-1.7
Data |= (1 << Index); // implement '1' into bit#index
PDIO_SET_RESET[1] = Data; //update byte to send to Set Port 1.0-1.7
while (HAL_I2C_GetState(&hi2c2) != HAL_I2C_STATE_READY){}
pcal9555_writeRegister(&hi2c2, 0x42, PDIO_SET_RESET, 2);
}
the following function are at COM.C file
void executeSerialCommand1(char *uart1RxBuf)
{
if(strcmp(uart1RxBuf,"port3 Enable") == 0){
PORT_Enable(3);
}
there is a loop with timmer that read the IO Expander's pins every 100mSec
this code is at Application.C file
void Application_Handler(void)
{
////////////////////////////////////////////////////////////////////////////
//Do every 10ms
////////////////////////////////////////////////////////////////////////////
if (TimeElapsed_10ms)
{
TimeElapsed_10ms = 0;
}
////////////////////////////////////////////////////////////////////////////
//Do every 100ms
////////////////////////////////////////////////////////////////////////////
if (TimeElapsed_100ms)
{
TimeElapsed_100ms = 0;
Update_Port_Params();
}
}
on startup, the system set all ports to '1'
therefore, there is no issue with "PORT_Enable()" function when calling it from the Application.C file
when using the UART to set port3 the application doesn't work properly and enters a loop
We use IO_Expander.C file for activating I2C communication
HAL_StatusTypeDef pcal9555_writeRegister(I2C_HandleTypeDef *hi2c, uint16_t address, uint8_t *pData, uint16_t Size){
// HAL_Status = HAL_I2C_Master_Transmit_IT(hi2c,(uint16_t) ADT7411_ADDRESS, pData, Size);
//return HAL_Status;
HAL_Status = HAL_I2C_Master_Transmit_IT(hi2c,address, pData, Size);
while (HAL_I2C_GetState(hi2c) != HAL_I2C_STATE_READY){
/* Error_Handler() function is called when Timeout error occurs.
When Acknowledge failure occurs (Slave don't acknowledge its address)
Master restarts communication */
if ((HAL_I2C_GetError(hi2c) != HAL_I2C_ERROR_AF) && (HAL_I2C_GetError(hi2c) != HAL_I2C_ERROR_NONE))
{
Error_Handler();
}
}
return HAL_Status;
}
it seams that HAL_Status is not READY when calling it from the UART so it has a loop at
while (HAL_I2C_GetState(hi2c) != HAL_I2C_STATE_READY){
when we call the function from the Application.C file, there is no issue
print of the Watch list at the While statment:
any advice will be appreciated
thank you
2024-06-30 06:10 AM
Any Help will be appreciated :)
2024-06-30 07:18 AM
Are you calling it from an interrupt / callback ?
If you're calling it from foreground and background you're going to encounter situations where you're mid usage.
Other than that look at how the functions / structures are shared between different files.
2024-06-30 07:22 AM
Since you have not attached the full project, we can only guess on the probable issue. You seems to access the I2c bus from timer as well as from the uart handler. you can put one volatile variable such as I2c busy or something to avoid simultaneous access to the bus. or alternately since you have the status already, you can take it from previous read, set the port expander IO in the next 100ms cycle from a structure or variable. there will be max delay of 100ms only.
2024-07-03 11:12 AM
Hi there,
It seams that this is the only reasonable situation,
i will check that and update you all