cancel
Showing results for 
Search instead for 
Did you mean: 

ism330dhcx ctrl3_c sw_reset I2C callback behavour

WrenchInTheWorks
Associate II

Hello awsome peaple of the ST fourms,

I've been writing a program on the MB1551-U585AI1-D01 STM32U5 dev board, after getting DMA working and writing some AzureRTOS aware platform functions for the MEMS sensors on the board I have been very successful in communicating with both the ISM330DHCX (IMU) and IIS2MDCTR (Magnetometer).

However, I have a single issuse that has just popped up that has me puzzeld. During setup of the ISM330DHCX I first check the WHO_AM_I to make sure the sensor is present and talking, I then attempt to software reset it. 

	// Initialize IMU
	stmdev_ctx_t  imu_dev_ctx;
	imu_dev_ctx.write_reg = imu_platform_write;
	imu_dev_ctx.read_reg = imu_platform_read;
	imu_dev_ctx.handle = NULL;

	uint8_t whoamI, rst;
	ism330dhcx_device_id_get(&imu_dev_ctx, &whoamI);
	if (whoamI != ISM330DHCX_ID) {
	    //TODO: Handle device not found
        tx_thread_suspend(&imu_thread_ptr);
	}

	// Reset the device
	// The bellow is me testing how the device behaves after the reset
	/*
	ism330dhcx_ctrl3_c_t data;
	HAL_I2C_Mem_Read_DMA(&hi2c2, IMU_ADDRESS, ISM330DHCX_CTRL3_C, 1, &data, 1);
	HAL_Delay(10);
	data.sw_reset = 1;
	HAL_I2C_Mem_Write_DMA(&hi2c2, IMU_ADDRESS, ISM330DHCX_CTRL3_C, 1, &data, 1);
	HAL_Delay(100);
	*/

	ism330dhcx_reset_set(&imu_dev_ctx, 1);
	do {
	    ism330dhcx_reset_get(&imu_dev_ctx, &rst);
	    tx_thread_sleep(1);
	} while (rst);

//continue to configure IMU

int32_t imu_platform_write(void *handle, uint8_t reg, uint8_t *bufp, uint16_t len) {
	return I2C_Write((uint16_t)IMU_ADDRESS, (uint16_t) reg, bufp, len);
}

int32_t imu_platform_read(void *handle, uint8_t reg, uint8_t *bufp, uint16_t len) {
	return I2C_Read((uint16_t) IMU_ADDRESS, (uint16_t) reg, bufp, len);
}

However, after the the reset command is sent there is no HAL_I2C_MemTxCpltCallback call, this is diffrent to the IIS2MDCTR where after setting the reset bit there is a callback. My platform drivers are shared between the two sensors and use semphores to manage resorce acsses as well as to wait for DMA to complete, therfore if there is no callback the I2C bus gets locked. That is what is confusing me, the I2C and RTOS code is the same for both sensors, the only diffrence being the address that is fed to the platfrom functions. I would thus expect the senors to behave the same in this regard, to either both callback or neither to call back.

#include <platform_functions.h>

//I2C semaphores
TX_SEMAPHORE I2C_bus_platform_semaphore;
TX_SEMAPHORE I2C_TX_clpt_platform_semaphore;
TX_SEMAPHORE I2C_RX_clpt_platform_semaphore;

//I2C semaphore create function
UINT I2C_Platfrom_Init(void) {

	if (tx_semaphore_create(&I2C_bus_platform_semaphore, "I2C Platform Semaphore", 1) == TX_SEMAPHORE_ERROR) {
		return TX_SEMAPHORE_ERROR;
	}

	if (tx_semaphore_create(&I2C_TX_clpt_platform_semaphore, "I2C Platform TX Semaphore", 0) == TX_SEMAPHORE_ERROR) {
		return TX_SEMAPHORE_ERROR;
	}

	if (tx_semaphore_create(&I2C_RX_clpt_platform_semaphore, "I2C Platform RX Semaphore", 0) == TX_SEMAPHORE_ERROR) {
		return TX_SEMAPHORE_ERROR;
	}
	return TX_SUCCESS;
}

void HAL_I2C_MemTxCpltCallback(I2C_HandleTypeDef *hi2c) {
    // Transmission complete
	if (hi2c->Instance == I2C_Handle.Instance) {
		tx_semaphore_put(&I2C_TX_clpt_platform_semaphore);
	}
}

void HAL_I2C_MemRxCpltCallback(I2C_HandleTypeDef *hi2c) {
    // Reception complete
	if (hi2c->Instance == I2C_Handle.Instance) {
		tx_semaphore_put(&I2C_RX_clpt_platform_semaphore);
	}
}


//I2C read function
int32_t I2C_Read(uint16_t address, uint16_t reg, uint8_t *data, uint16_t len) {
	tx_semaphore_get(&I2C_bus_platform_semaphore, TX_WAIT_FOREVER);
	HAL_StatusTypeDef status = HAL_I2C_Mem_Read_DMA(&I2C_Handle, address + 1, reg, I2C_MEMADD_SIZE_8BIT, data, len);
	tx_semaphore_get(&I2C_RX_clpt_platform_semaphore, TX_WAIT_FOREVER);
	tx_semaphore_put(&I2C_bus_platform_semaphore);
	return status;
}

//I2C write function

int32_t I2C_Write(uint16_t address, uint16_t reg, const uint8_t *data, uint16_t len) {
	tx_semaphore_get(&I2C_bus_platform_semaphore, TX_WAIT_FOREVER);
	HAL_StatusTypeDef status = HAL_I2C_Mem_Write_DMA(&I2C_Handle, address, reg, I2C_MEMADD_SIZE_8BIT, data, len);
	tx_semaphore_get(&I2C_TX_clpt_platform_semaphore, TX_WAIT_FOREVER);
	tx_semaphore_put(&I2C_bus_platform_semaphore);
	return status;
}

//GetTick function
int32_t Platform_Get_Tick(void) {
	return tx_time_get();
}

For now I can get around this by just not reseting the device since all other driver functions work as expected but I feel that leaves things prone to errors in device config sliping in so I would love to know the explnation for this behavour.

 

Cheers,

Michael

 

3 REPLIES 3
Karl Yamashita
Principal

In your I2C_Write function, did you check to see if the HAL status is HAL_OK?

Maybe the software reset happens before the device can ACK? 

 

Don't worry, I won't byte.
TimerCallback tutorial! | UART and DMA Idle tutorial!

If you find my solution useful, please click the Accept as Solution so others see the solution.

Good day @Karl Yamashita,

HAL is fine, as far as I can tell it transmits fine since I can write to other regs. Not sure if the bellow image will be readable.

WrenchInTheWorks_1-1739595688851.png

 

I'm thinking the same thing about it reseting before acking but I would be surprised since thats not how the mag sensor behaves. Does I2C in blocking mode wait for an ACK? I would asume it does, in that case things are even stranger because using I2C in blocking without DMA still returns HAL_OK and as far as I can tell resets the device.

Cheers,

Michael

So... it just started working. I'm not sure what I did but I have a feeling that I might have put a bad value or somthing into a reserved reg. It might have had somthing todo with a bad value being put into bit 7. From what I can tell instead of reading form the reg and then updating what was read I sent a bunch of new values by mistake to CTRL3_C which might have triggerd BOOT and I asume wiped the device to a state where it started working again. I think I need to be more carful where I put my bits and bytes... haha.

WrenchInTheWorks_0-1739596951747.png

One final question before I close this topic, whats the diffrence between BOOT and SW_RESET? Is SW_RESET todo with the FSM and MLC? Prehaps I should be reseting BOOT instead of SW_RESET to wipe the device config?