Skip to main content
Explorer
November 25, 2024
Question

FreeRTOS on STM32G0B1: Unable to use as I2C Slave

  • November 25, 2024
  • 1 reply
  • 996 views

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.

 

    This topic has been closed for replies.

    1 reply

    ST Employee
    November 25, 2024

    Hello @minhaj97haider 

     

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

     

    We'll contact you directly.

     

    Regards,

    Roger