cancel
Showing results for 
Search instead for 
Did you mean: 

FreeRTOS on STM32G0B1: Unable to use as I2C Slave

minhaj97haider
Associate

Hello, good afternoon.

I have two Nucleo boards STM32G071RB that I have written an I2C interface for. It is basically a command interface, where Master sends a command, and polls the slave later to get the response. I have tested my application thoroughly, it is working great between these two Dev Boards.

Now for the actual work, I am replacing the slave with an internally developed board based on STM32G0B1, running FreeRTOS (I am fairly new to RTOS). Between the RTOS G0B1 Slave and the G071 Master, I see the Master send the slave address; The slave reads its address and holds the clock line low permanently; It does not trigger AddressCpltCallback, allowing me to receive the data. Sometimes the Oscilloscope would show 16-20 bits on the SDA/SCL lines instead of the usual 8-9 (not sure what setting i messed with to get that), but end result remains the same, after these bits, Slave will hold the SCL low indefinitely. Any ideas where I went wrong could help, thanks.

 

MASTER BOARD:

 

 

static void MX_I2C1_Init(void)
{
p_i2c->p_i2cHandle.Instance = I2C1;
p_i2c->p_i2cHandle.Init.Timing = 0x00100413;
p_i2c->p_i2cHandle.Init.OwnAddress1 = I2C_ADDRESS;
p_i2c->p_i2cHandle.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
p_i2c->p_i2cHandle.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
p_i2c->p_i2cHandle.Init.OwnAddress2 = 0;
p_i2c->p_i2cHandle.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
p_i2c->p_i2cHandle.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
p_i2c->p_i2cHandle.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;

if (HAL_I2C_Init(&p_i2c->p_i2cHandle) != HAL_OK) Error_Handler();
if (HAL_I2CEx_ConfigAnalogFilter(&p_i2c->p_i2cHandle, I2C_ANALOGFILTER_ENABLE) != HAL_OK) Error_Handler();
if (HAL_I2CEx_ConfigDigitalFilter(&p_i2c->p_i2cHandle, 0) != HAL_OK) Error_Handler();
HAL_I2CEx_EnableFastModePlus(I2C_FASTMODEPLUS_I2C1);
}


int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
BSP_LED_Init(LED4);
BSP_PB_Init(BUTTON_USER,BUTTON_MODE_GPIO);
StmI2cControl_Init(4000, i2c_MasterRxProcess); //Sets User variables to zero, calls MX_I2C1_Init()

while (1)
{
while (BSP_PB_GetState(BUTTON_USER) != GPIO_PIN_RESET)
{
BSP_LED_On(LED4);
HAL_Delay( (100*ubMasterDutyCycle)/(ubMasterFrequency) );
BSP_LED_Off(LED4);
HAL_Delay( (100*(10-ubMasterDutyCycle))/(ubMasterFrequency) );
}
while (BSP_PB_GetState(BUTTON_USER) != GPIO_PIN_SET);

p_i2cItf->pf_sendCommand(0U, command, &msg_data, 1U);//Parses data and calls TransmitSeq
HAL_Delay(1000);
p_i2cItf->pf_pollSlave();
}
}

HAL_StatusTypeDef StmI2cControl_TransmitSeq(void)
{
assert(NULL != p_i2c);
HAL_StatusTypeDef RetVal = HAL_OK;
p_i2c->size_Tx = 1;
RetVal = HAL_I2C_Master_Seq_Transmit_IT(&p_i2c->p_i2cHandle, I2C_ADDRESS, p_i2c->aTxMsg, 6U, I2C_LAST_FRAME);
return RetVal;
}

void HAL_I2C_MasterTxCpltCallback(I2C_HandleTypeDef *I2cHandle)
{
	i2cBuffer_AddRecord(p_i2c->aTxMsg);
}

 

 

SLAVE BOARD (FreeRTOS):

 

void MX_I2C1_Init(void)
{
hi2c1.Instance = I2C1;
hi2c1.Init.Timing = 0x00100413;
hi2c1.Init.OwnAddress1 = 0x20;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;

if (HAL_I2C_Init(&hi2c1) != HAL_OK) Error_Handler();
if (HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE) != HAL_OK) Error_Handler();
if (HAL_I2CEx_ConfigDigitalFilter(&hi2c1, 0) != HAL_OK) Error_Handler();
HAL_I2CEx_EnableFastModePlus(I2C_FASTMODEPLUS_I2C1);
}

void StmI2CControl_InitI2CSlave(void) {
p_slave_stm_i2c = &stmI2C;
p_slave_stm_i2c->i2c_interface.p_i2c_obj = &stmI2C;
p_slave_stm_i2c->p_i2c_handle = &hi2c1;

/* Create the queues and assign handles */
p_slave_stm_i2c->rx_queue_handle = osMessageQueueNew(I2C_QUEUE_LENGTH, sizeof(i2c_msg_t), &rx_queueAttributes);
p_slave_stm_i2c->tx_queue_handle = osMessageQueueNew(I2C_QUEUE_LENGTH, sizeof(i2c_msg_t), &tx_queueAttributes);
p_slave_stm_i2c->cmd_queue_handle = osMessageQueueNew(I2C_QUEUE_LENGTH, sizeof(i2c_msg_t), &cmd_queueAttributes);

p_slave_stm_i2c->i2c_interface.pf_slave_transmit_it = (I2CInterface_Slave_Transmit_IT_t)StmI2CInterface_SlaveTransmit;
p_slave_stm_i2c->i2c_interface.pf_slave_receive_it = (I2CInterface_Slave_Receive_IT_t)StmI2CInterface_SlaveReceive;

i2c_cmd_taskHandle = osThreadNew(StmI2CControl_handleReceiveCmd, NULL, &i2c_cmd_task_attributes);

//Enable Slave Listen, for when Master sends Slave address on I2C Bus
if(HAL_I2C_EnableListen_IT(p_slave_stm_i2c->p_i2c_handle) != HAL_OK) Error_Handler();

HAL_NVIC_SetPriority(I2C1_IRQn, 3, 0);
HAL_NVIC_EnableIRQ(I2C1_IRQn);
}

HAL_StatusTypeDef StmI2CInterface_SlaveReceive(void) {
assert(p_slave_stm_i2c != NULL);
HAL_StatusTypeDef RetVal = HAL_I2C_Slave_Seq_Receive_IT(p_slave_stm_i2c->p_i2c_handle, &rx_i2c_msg.pui8_raw_msg[0], 6U, I2C_LAST_FRAME_NO_STOP);

return RetVal;
}

void HAL_I2C_ListenCpltCallback(I2C_HandleTypeDef *hi2c) {
if(HAL_I2C_EnableListen_IT(hi2c) != HAL_OK) Error_Handler();
}

void HAL_I2C_AddrCallback(I2C_HandleTypeDef *hi2c, uint8_t TransferDirection, uint16_t AddrMatchCode)
{
UNUSED(AddrMatchCode);
UNUSED(hi2c);

/* Master is transmitting */
if(TransferDirection == I2C_DIRECTION_TRANSMIT)
{
if(p_slave_stm_i2c->i2c_interface.pf_slave_receive_it() != HAL_OK) Error_Handler();
}
else //Slave will transmit data
{
if(p_slave_stm_i2c->i2c_interface.pf_slave_transmit_it() != HAL_OK) Error_Handler();
}
}

void HAL_I2C_SlaveRxCpltCallback(I2C_HandleTypeDef *hi2c)
{
UNUSED(hi2c);
assert(NULL != p_slave_stm_i2c);
if(rx_i2c_msg.ui8_msg_type == i2c_mT_Reset_Slave)
{
//Flush Slave Buffer
StmI2cControl_flushCmdBuffer();
}
else if (osMessageQueuePut(p_slave_stm_i2c->rx_queue_handle, &rx_i2c_msg, 0, 0) != osOK) Error_Handler();
return;
}

 

 

My guess so far is that the I2C Interrupt is still disabled. Maybe I need to enable it through some RTOS function? Much thanks for your help.

In the attached images, A1 (top) is Data, A2 (bottom) is clock.

 

1 REPLY 1
Roger SHIVELY
ST Employee

Hello @minhaj97haider 

 

This post has been escalated to the ST Online Support Team for additional assistance.

 

We'll contact you directly.

 

Regards,

Roger