cancel
Showing results for 
Search instead for 
Did you mean: 

STM32L0 code start and execution problems

MatheusMarkies
Associate II

I'm developing a vibration and temperature sensor solution for industrial machinery.

Previously, my system was equipped with Atmega 328p chips, but it has now been upgraded to an STM32LO53C8T8 chip.

The circuit has a LoRa radio for sending signals to the gateway, a KX122-1037 accelerometer, a MCP9808 temperature sensor, a MAX17048 battery sensor and a MB85RC FRAM. I connected the TX pin to the arduino Mega to get a DEBUG display on the arduino IDE's serial monitor.

I assembled a PCB with the wiring diagram in the attached image, and it worked well for programming the microcontroller. However, I started to experience some problems when executing the code.

  • Firstly, my code is only executed by the chip when the system finishes uploading and resets it. I added an external 10K pull-up resistor to the chip's reset (which wasn't on the PCB). Now I can run the code whenever I pulse GND on the pin. However, it should run whenever the system is connected to power, which is not happening.
  • Secondly, my code is crashing in the accelerometer reading loop, basically I added a loop that reads the accelerometer 2048 times during one second, spacing the readings with a microsecond delay calculated in the setup method. The loop code runs well up to about 30 samples and then stops. I've tested the delay separately and apparently it works. And I've tested the loop with no other code in it, just the delay, and the same error happens.

Full Codes: https://gist.github.com/MatheusMarkies/a85b8288ed40ea9962f3d91e22202695

#include "stm32l0xx_hal.h"

#include "math.h"
#include "string.h"
#include "stdio.h"
#include "LORA.h"
#include "FRAM.h"
#include "KX122.h"
#include "MCP9808.h"
#include "MAX17048.h"
#include "BrasensFirmware.h"

#define SENSOR_KEY "1111A"
TIM_HandleTypeDef htim2;
#define DEBUG_PRINT(msg) HAL_UART_Transmit(&huart1, (uint8_t*)msg, strlen(msg), HAL_MAX_DELAY)
#define min(a, b) ((a) < (b) ? (a) : (b))

Transmission_Data data;
Transmission_VibrationPackage vibrationPackage;

unsigned int sampling_period_us;
unsigned long data_sender_period;

int package_factor = 0;
int acc_sample_factor = 0;

FRAM_Metadata metadata;

uint32_t sizeInBytes = 0;
/* USER CODE END PV */

int main(void) {
	TIM2_Init();
	setup();
	while (1) {
		loop();
	}
}

void SystemClock_Config(void) {
	RCC_OscInitTypeDef RCC_OscInitStruct = { 0 };
	RCC_ClkInitTypeDef RCC_ClkInitStruct = { 0 };
	RCC_PeriphCLKInitTypeDef PeriphClkInit = { 0 };

	/** Configure the main internal regulator output voltage
	 */
	__HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);

	/** Initializes the RCC Oscillators according to the specified parameters
	 * in the RCC_OscInitTypeDef structure.
	 */
	RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_MSI;
	RCC_OscInitStruct.MSIState = RCC_MSI_ON;
	RCC_OscInitStruct.MSICalibrationValue = 0;
	RCC_OscInitStruct.MSIClockRange = RCC_MSIRANGE_5;
	RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
	if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
		Error_Handler();
	}

	/** Initializes the CPU, AHB and APB buses clocks
	 */
	RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK
			| RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;
	RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_MSI;
	RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
	RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;
	RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

	if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) {
		Error_Handler();
	}
	PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1
			| RCC_PERIPHCLK_I2C1;
	PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;
	PeriphClkInit.I2c1ClockSelection = RCC_I2C1CLKSOURCE_PCLK1;
	if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK) {
		Error_Handler();
	}
}

void TIM2_Init(void)
{
    __HAL_RCC_TIM2_CLK_ENABLE();

    htim2.Instance = TIM2;
    htim2.Init.Prescaler = (uint32_t)(HAL_RCC_GetPCLK1Freq() / 1000000) - 1; // 1 MHz
    htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
    htim2.Init.Period = 0xFFFFFFFF; // Máximo período
    htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
    if (HAL_TIM_Base_Init(&htim2) != HAL_OK) {
        Error_Handler();
    }
    if (HAL_TIM_Base_Start(&htim2) != HAL_OK) {
        Error_Handler();
    }
}

uint32_t micros()
{
    return __HAL_TIM_GET_COUNTER(&htim2);
}

void delayMicroseconds(uint32_t us) {
    uint32_t start = micros();
    uint32_t target = start + us;

    if (target < start) {
        // Overflow do contador
        while (micros() >= start) {
            // Espera até o overflow ocorrer
        }
    }

    while (micros() < target) {
        // Espera até atingir o tempo desejado
    }
}



uint16_t address = 0;

unsigned long writeMicroseconds;
int current_sample = 0;

void writeVibrationInformation() {
	data.rms_accel[0] = 0.0;
	data.rms_accel[1] = 0.0;
	data.rms_accel[2] = 0.0;

	data.rms_vel[0] = 0.0;
	data.rms_vel[1] = 0.0;
	data.rms_vel[2] = 0.0;

	float velocity_x = 0.0;
	float velocity_y = 0.0;
	float velocity_z = 0.0;

	int d = 0;
	int count = 0;
	DEBUG_PRINT("read...\r\n");
	//FOR

	for (int i = 0; i < SAMPLES; i++) {
			Vibration vibration = KX122_ReadAccelData(&hi2c1);

			count++;

			FRAM_WriteFloat(&hi2c1, &metadata,
					address + SAMPLES * 0 * sizeof(float), vibration.x);
			FRAM_WriteFloat(&hi2c1, &metadata,
					address + SAMPLES * 1 * sizeof(float), vibration.y);
			FRAM_WriteFloat(&hi2c1, &metadata,
					address + SAMPLES * 2 * sizeof(float), vibration.z);

			address += sizeof(float);

			d++;
			count = 0;

			data.rms_accel[0] += (vibration.x * vibration.x);
			data.rms_accel[1] += (vibration.y * vibration.y);
			data.rms_accel[2] += (vibration.z * vibration.z);

			float deltaTime = sampling_period_us / 1e6;
			velocity_x += vibration.x * deltaTime; //Ax * dT
			velocity_y += vibration.y * deltaTime; //Ay * dT
			velocity_z += vibration.z * deltaTime; //Az * dT

			data.rms_vel[0] += (velocity_x * velocity_x);
			data.rms_vel[1] += (velocity_y * velocity_y);
			data.rms_vel[2] += (velocity_z * velocity_z);

			delayMicroseconds(sampling_period_us);
		}


	data.rms_accel[0] = sqrt(data.rms_accel[0] / SAMPLES);
	data.rms_accel[1] = sqrt(data.rms_accel[1] / SAMPLES);
	data.rms_accel[2] = sqrt(data.rms_accel[2] / SAMPLES);

	data.rms_vel[0] = sqrt(data.rms_vel[0] / SAMPLES);
	data.rms_vel[1] = sqrt(data.rms_vel[1] / SAMPLES);
	data.rms_vel[2] = sqrt(data.rms_vel[2] / SAMPLES);

    char buffer[256];
    snprintf(buffer, sizeof(buffer),
             "RMS Accel: %.2f, %.2f, %.2f\r\nRMS Vel: %.2f, %.2f, %.2f\r\n",
             data.rms_accel[0], data.rms_accel[1], data.rms_accel[2],
             data.rms_vel[0], data.rms_vel[1], data.rms_vel[2]);
    DEBUG_PRINT(buffer);
}

HAL_StatusTypeDef MCP9808_ReadTemperature_LowPower(double *temperature) {
	HAL_StatusTypeDef status;

	status = MCP9808_Wake(&hi2c1);
	if (status != HAL_OK) {
		return status;
	}

	HAL_Delay(50);

	status = MCP9808_ReadTemperature(&hi2c1, temperature);

    char buffer[256];
    snprintf(buffer, sizeof(buffer), "Temp: %d \r\n", *temperature);
	DEBUG_PRINT(buffer);

	if (status != HAL_OK) {
		return status;
	}

	status = MCP9808_Shutdown(&hi2c1);
	return status;
}

void readBatteryData(uint16_t* soc) {
    uint16_t voltage;
    char msg[64];

    if (MAX17048_ReadVoltage(&hi2c1, &voltage) == HAL_OK) {
        snprintf(msg, sizeof(msg), "Voltage: %u mV\r\n", voltage);
        DEBUG_PRINT(msg);
    } else {
        DEBUG_PRINT("Failed to read voltage\r\n");
    }

    if (MAX17048_ReadSOC(&hi2c1, soc) == HAL_OK) {
        snprintf(msg, sizeof(msg), "State of Charge: %u%%\r\n", *soc);
        DEBUG_PRINT(msg);
    } else {
        DEBUG_PRINT("Failed to read SOC\r\n");
    }
}

void I2C_Scan() {
    char msg[64];
    HAL_StatusTypeDef result;
    uint8_t i;

    DEBUG_PRINT("Scanning I2C bus:\r\n");

    for (i = 1; i < 128; i++) {

        result = HAL_I2C_IsDeviceReady(&hi2c1, (uint16_t)(i << 1), 1, 10);
        if (result == HAL_OK) {
            snprintf(msg, sizeof(msg), "Device found at 0x%02X\r\n", i);
            DEBUG_PRINT(msg);
        } else {

        }
    }
    DEBUG_PRINT("I2C scan completed.\r\n");
}


void setup() {
    DEBUG_PRINT("Starting...\r\n");
    I2C_Scan();

    if (KX122_Init(&hi2c1) != HAL_ERROR)
        DEBUG_PRINT("Ready KX122\r\n");
    else
        DEBUG_PRINT("Error in KX122 connection\r\n");

    if (MCP9808_Init(&hi2c1) != HAL_ERROR)
        DEBUG_PRINT("Ready MCP9808\r\n");
    else
        DEBUG_PRINT("Error in MCP9808 connection\r\n");

    if (MAX17048_Init(&hi2c1) != HAL_ERROR)
        DEBUG_PRINT("Ready MAX17048\r\n");
    else
        DEBUG_PRINT("Error in MAX17048 connection\r\n");

    if (FRAM_Init(&hi2c1) != HAL_ERROR)
        DEBUG_PRINT("Ready FRAM\r\n");
    else
        DEBUG_PRINT("Error in FRAM connection\r\n");

    DEBUG_PRINT("Ready!\r\n");

    FRAM_InitMetadata(&metadata);

    char buffer[50];
    snprintf(buffer, sizeof(buffer), "Next Memory Adds: %d\r\n", metadata.nextFreeAddress);
    DEBUG_PRINT(buffer);

    package_factor = 3 * ceil((float)(SAMPLES) / (float)TRANSMISSION_DATA_PACKAGE);
    data_sender_period = round(1000 * ((float)DATA_TRANSMISSION_PERIOD / (float)package_factor));
    sampling_period_us = round(1000000 * (SAMPLES / (float)ACC_DATA_RATE));
    acc_sample_factor = floor((float)ACC_DATA_RATE / (float)SAMPLES);

    sizeInBytes = FRAM_MEMORY_SIZE;

    FRAM_Format(&hi2c1, &metadata);

    DEBUG_PRINT("Starting Temperature Reading:\r\n");
    double temp;
    MCP9808_ReadTemperature_LowPower(&temp);

    char bufferTemp[50];
    snprintf(bufferTemp, sizeof(bufferTemp), "Temp: %.2f\r\n", temp);  // Usar %.2f para imprimir double
    DEBUG_PRINT(bufferTemp);

    DEBUG_PRINT("Starting Battery Reading:\r\n");
    int16_t bat = 0;
    readBatteryData(&bat);

    char bufferBat[50];
    snprintf(bufferBat, sizeof(bufferBat), "Bat: %d\r\n", bat);
    DEBUG_PRINT(bufferBat);

    Vibration vibration = KX122_ReadAccelData(&hi2c1);

    char bufferVib[50];
    snprintf(bufferVib, sizeof(bufferVib), "RMS Accel: %.2f, %.2f, %.2f\r\n",
             vibration.x, vibration.y, vibration.z);  // Usar %.2f para imprimir double
    DEBUG_PRINT(bufferVib);

    // Teste de escrita e leitura da FRAM
    float test_value = 123.456f;
    float read_value = 0.0f;
    uint16_t test_address = 0x0000;

    if (FRAM_WriteFloat(&hi2c1, &metadata, test_address, test_value) == HAL_OK) {
        DEBUG_PRINT("FRAM write success\r\n");

        if (FRAM_ReadFloat(&hi2c1, test_address, &read_value) == HAL_OK) {
            char buffer[100];
            snprintf(buffer, sizeof(buffer), "FRAM read success, value: %.3f\r\n", read_value);
            DEBUG_PRINT(buffer);

            if (fabs(test_value - read_value) < 0.001f) {
                DEBUG_PRINT("FRAM test passed\r\n");
            } else {
                DEBUG_PRINT("FRAM test failed: values do not match\r\n");
            }
        } else {
            DEBUG_PRINT("FRAM read failed\r\n");
        }
    } else {
        DEBUG_PRINT("FRAM write failed\r\n");
    }

    DEBUG_PRINT("Testando delayMicroseconds...\r\n");
        uint32_t start_test = micros();
        delayMicroseconds(1000000);  // 1 segundo
        uint32_t end_test = micros();
        char bufferDelay[50];
        snprintf(bufferDelay, sizeof(bufferDelay), "Atraso: %lu us\r\n", end_test - start_test);
        DEBUG_PRINT(bufferDelay);

    DEBUG_PRINT("Starting Vibration Reading:\r\n");
        writeVibrationInformation();
}


unsigned long readMilliseconds;

bool energy_save = false;

float temperatureValue;
int current_package = 0;
int reset_counter = 0;
bool sendDataDelay = false;
int axis = 0;
void readAndSendFRAMData() {
	DEBUG_PRINT("readAndSendFRAMData...\r\n");
	if (energy_save) {
		readMilliseconds = millis();
		sendDataDelay = true;
		energy_save = false;
	} else if (millis() > (readMilliseconds + data_sender_period)) {
		sendDataDelay = true;
	}

	if (current_package >= (2 * package_factor / 3))
		axis = 2;
	else if (current_package >= (package_factor / 3))
		axis = 1;
	else
		axis = 0;

	if (sendDataDelay) {
		int start = TRANSMISSION_DATA_PACKAGE * current_package
				- TRANSMISSION_DATA_PACKAGE * axis * package_factor / 3;

		int end = (start + TRANSMISSION_DATA_PACKAGE);

		if (current_package > 0)
			start += 1;

		for (int i = start; i <= end; i++) {
			uint16_t address = i * sizeof(float)
					+ SAMPLES * axis * sizeof(float);
			float value = 0.0;

			if (SAMPLES >= i) {
				FRAM_ReadFloat(&hi2c1, address, &value);
			}

			vibrationPackage.dataPackage[i - start] = value;
		}

		strncpy(vibrationPackage.key, SENSOR_KEY, sizeof(vibrationPackage.key));

		vibrationPackage.type = 'P';

		vibrationPackage.start = start;
		vibrationPackage.end = min(end, SAMPLES);

		vibrationPackage.axis = axis;

		LoRa_Idle(&hspi1);

		sendVibrationPackage(vibrationPackage);

		readMilliseconds = millis();
		sendDataDelay = false;

		//if (report) {
		//temperatureValue += readTemperature() / package_factor;
		current_package++;
		//reset_counter = 0;

		LoRa_Sleep(&hspi1);
		energy_save = true;
	}
}

void loop() {
	DEBUG_PRINT("loop...\r\n");
	readAndSendFRAMData();

	if (current_package >= package_factor) {
		writeVibrationInformation();
		temperatureValue = 0;
		MCP9808_ReadTemperature_LowPower( &temperatureValue);
		data.temperature = temperatureValue;
		strncpy(data.key, SENSOR_KEY, sizeof(data.key));
		data.type = 'D';

		uint16_t soc = 0;
		readBatteryData(&soc); // Passing the address of soc

		data.battery = soc;

		sendData(data);
		current_package = 0;
	}
}

void sendVibrationPackage(Transmission_VibrationPackage sendingVibrationPackage) {
	LoRa_Idle(&hspi1);

	uint8_t buffer[sizeof(Transmission_VibrationPackage)];
	memcpy(buffer, &sendingVibrationPackage,
			sizeof(Transmission_VibrationPackage));

	LoRa_Transmit(&hspi1, buffer, sizeof(Transmission_VibrationPackage));

	LoRa_Sleep(&hspi1);
}

void sendData(Transmission_Data sendingData) {
	LoRa_Idle(&hspi1);

	uint8_t buffer[sizeof(Transmission_Data)];
	memcpy(buffer, &sendingData, sizeof(Transmission_Data));

	LoRa_Transmit(&hspi1, buffer, sizeof(Transmission_Data));

	LoRa_Sleep(&hspi1);
}

Here I take the accelerometer reading:

void writeVibrationInformation() {
	data.rms_accel[0] = 0.0;
	data.rms_accel[1] = 0.0;
	data.rms_accel[2] = 0.0;

	data.rms_vel[0] = 0.0;
	data.rms_vel[1] = 0.0;
	data.rms_vel[2] = 0.0;

	float velocity_x = 0.0;
	float velocity_y = 0.0;
	float velocity_z = 0.0;

	int d = 0;
	int count = 0;
	DEBUG_PRINT("read...\r\n");
	//FOR

	for (int i = 0; i < SAMPLES; i++) {
			Vibration vibration = KX122_ReadAccelData(&hi2c1);

			count++;

			FRAM_WriteFloat(&hi2c1, &metadata,
					address + SAMPLES * 0 * sizeof(float), vibration.x);
			FRAM_WriteFloat(&hi2c1, &metadata,
					address + SAMPLES * 1 * sizeof(float), vibration.y);
			FRAM_WriteFloat(&hi2c1, &metadata,
					address + SAMPLES * 2 * sizeof(float), vibration.z);

			address += sizeof(float);

			d++;
			count = 0;

			data.rms_accel[0] += (vibration.x * vibration.x);
			data.rms_accel[1] += (vibration.y * vibration.y);
			data.rms_accel[2] += (vibration.z * vibration.z);

			float deltaTime = sampling_period_us / 1e6;
			velocity_x += vibration.x * deltaTime; //Ax * dT
			velocity_y += vibration.y * deltaTime; //Ay * dT
			velocity_z += vibration.z * deltaTime; //Az * dT

			data.rms_vel[0] += (velocity_x * velocity_x);
			data.rms_vel[1] += (velocity_y * velocity_y);
			data.rms_vel[2] += (velocity_z * velocity_z);

			delayMicroseconds(sampling_period_us);
		}


	data.rms_accel[0] = sqrt(data.rms_accel[0] / SAMPLES);
	data.rms_accel[1] = sqrt(data.rms_accel[1] / SAMPLES);
	data.rms_accel[2] = sqrt(data.rms_accel[2] / SAMPLES);

	data.rms_vel[0] = sqrt(data.rms_vel[0] / SAMPLES);
	data.rms_vel[1] = sqrt(data.rms_vel[1] / SAMPLES);
	data.rms_vel[2] = sqrt(data.rms_vel[2] / SAMPLES);

    char buffer[256];
    snprintf(buffer, sizeof(buffer),
             "RMS Accel: %.2f, %.2f, %.2f\r\nRMS Vel: %.2f, %.2f, %.2f\r\n",
             data.rms_accel[0], data.rms_accel[1], data.rms_accel[2],
             data.rms_vel[0], data.rms_vel[1], data.rms_vel[2]);
    DEBUG_PRINT(buffer);
}

In this part I run a test in the loop with debug and delay:

	for (int i = 0; i < SAMPLES; i++) {
	    char bufferDelay[100];
	    snprintf(bufferDelay, sizeof(bufferDelay), "Iteracao: %d, Atraso: %d us\r\n", i, sampling_period_us);
	    DEBUG_PRINT(bufferDelay);

	    // Log antes do delay
	    DEBUG_PRINT("Antes do delay...\r\n");
	    uint32_t start_test = micros();
	    delayMicroseconds(sampling_period_us);
	    uint32_t end_test = micros();
	    DEBUG_PRINT("Depois do delay...\r\n");

	    snprintf(bufferDelay, sizeof(bufferDelay), "Delay real: %lu us\r\n", end_test - start_test);
	    DEBUG_PRINT(bufferDelay);

	    // Log para verificar se a iteração foi completada
	    snprintf(bufferDelay, sizeof(bufferDelay), "Iteracao %d completada\r\n", i);
	    DEBUG_PRINT(bufferDelay);
	}

I've tried removing the reading from the accelerometer and testing it. My code runs in the while loop, and it also hangs after a short time.

23 REPLIES 23

Sounds like you've got some blocking delays in the loop?

Apparently yes, but I developed the libraries used in the readings and didn't add any delay.

Vibration KX122_ReadAccelData(I2C_HandleTypeDef *hi2c) {
    uint8_t data[6];
    Vibration vib = {0};

    if (KX122_ReadRegister(hi2c, KX122_XOUT_L, &data[0]) != HAL_OK) return vib;
    if (KX122_ReadRegister(hi2c, KX122_XOUT_H, &data[1]) != HAL_OK) return vib;
    if (KX122_ReadRegister(hi2c, KX122_YOUT_L, &data[2]) != HAL_OK) return vib;
    if (KX122_ReadRegister(hi2c, KX122_YOUT_H, &data[3]) != HAL_OK) return vib;
    if (KX122_ReadRegister(hi2c, KX122_ZOUT_L, &data[4]) != HAL_OK) return vib;
    if (KX122_ReadRegister(hi2c, KX122_ZOUT_H, &data[5]) != HAL_OK) return vib;

    int16_t raw_x = (int16_t)((data[1] << 8) | data[0]);
    int16_t raw_y = (int16_t)((data[3] << 8) | data[2]);
    int16_t raw_z = (int16_t)((data[5] << 8) | data[4]);

    // Converting raw data to Gs (assuming default sensitivity)
    double sensitivity = 0.000061; // 61 μg/LSB for ±2g range
    vib.x = raw_x * sensitivity;
    vib.y = raw_y * sensitivity;
    vib.z = raw_z * sensitivity;

    return vib;
}

static HAL_StatusTypeDef KX122_WriteRegister(I2C_HandleTypeDef *hi2c, uint8_t reg, uint8_t value) {
    uint8_t data[2] = { reg, value };
    return HAL_I2C_Master_Transmit(hi2c, KX122_I2C_ADDRESS << 1, data, 2, HAL_MAX_DELAY);
}

static HAL_StatusTypeDef KX122_ReadRegister(I2C_HandleTypeDef *hi2c, uint8_t reg, uint8_t *data) {
    HAL_StatusTypeDef status = HAL_I2C_Master_Transmit(hi2c, KX122_I2C_ADDRESS << 1, &reg, 1, HAL_MAX_DELAY);
    if (status == HAL_OK) {
        status = HAL_I2C_Master_Receive(hi2c, KX122_I2C_ADDRESS << 1, data, 1, HAL_MAX_DELAY);
    }
    return status;
}
HAL_StatusTypeDef FRAM_WriteData(I2C_HandleTypeDef *hi2c, FRAM_Metadata *metadata, uint16_t memAddress, uint8_t *data, uint16_t dataSize) {
    uint8_t *buffer = malloc(dataSize + 2);
    if (buffer == NULL) return HAL_ERROR;
    buffer[0] = (memAddress >> 8) & 0xFF;
    buffer[1] = memAddress & 0xFF;
    memcpy(&buffer[2], data, dataSize);
    HAL_StatusTypeDef status = HAL_I2C_Master_Transmit(hi2c, FRAM_I2C_ADDRESS << 1, buffer, dataSize + 2, HAL_MAX_DELAY);
    free(buffer);
    if (status == HAL_OK) {
        FRAM_UpdateMetadata(metadata, memAddress, dataSize);
    }
    return status;
}

HAL_StatusTypeDef FRAM_ReadData(I2C_HandleTypeDef *hi2c, uint16_t memAddress, uint8_t *data, uint16_t dataSize) {
    uint8_t buffer[2];
    buffer[0] = (memAddress >> 8) & 0xFF;
    buffer[1] = memAddress & 0xFF;
    HAL_StatusTypeDef status = HAL_I2C_Master_Transmit(hi2c, FRAM_I2C_ADDRESS << 1, buffer, 2, HAL_MAX_DELAY);
    if (status == HAL_OK) {
        status = HAL_I2C_Master_Receive(hi2c, FRAM_I2C_ADDRESS << 1, data, dataSize, HAL_MAX_DELAY);
    }
    return status;
}

HAL_StatusTypeDef FRAM_WriteStruct(I2C_HandleTypeDef *hi2c, FRAM_Metadata *metadata, uint16_t memAddress, void *data, size_t dataSize) {
    return FRAM_WriteData(hi2c, metadata, memAddress, (uint8_t *)data, dataSize);
}

HAL_StatusTypeDef FRAM_ReadStruct(I2C_HandleTypeDef *hi2c, uint16_t memAddress, void *data, size_t dataSize) {
    return FRAM_ReadData(hi2c, memAddress, (uint8_t *)data, dataSize);
}

HAL_StatusTypeDef FRAM_WriteFloat(I2C_HandleTypeDef *hi2c, FRAM_Metadata *metadata, uint16_t memAddress, float value) {
    return FRAM_WriteStruct(hi2c, metadata, memAddress, &value, sizeof(float));
}

HAL_I2C_Master_Receive(hi2c, FRAM_I2C_ADDRESS << 1, data, dataSize, HAL_MAX_DELAY);

Excuse my ignorance, but could HAL_MAX_DELAY be causing this?

But if your libraries busy-wait for operations which take significant time - that is effectively an inline delay.

 

Does this really need to be done as 6 separate transactions?

 

    if (KX122_ReadRegister(hi2c, KX122_XOUT_L, &data[0]) != HAL_OK) return vib;
    if (KX122_ReadRegister(hi2c, KX122_XOUT_H, &data[1]) != HAL_OK) return vib;
    if (KX122_ReadRegister(hi2c, KX122_YOUT_L, &data[2]) != HAL_OK) return vib;
    if (KX122_ReadRegister(hi2c, KX122_YOUT_H, &data[3]) != HAL_OK) return vib;
    if (KX122_ReadRegister(hi2c, KX122_ZOUT_L, &data[4]) != HAL_OK) return vib;
    if (KX122_ReadRegister(hi2c, KX122_ZOUT_H, &data[5]) != HAL_OK) return vib;

 

Is it not possible to do that as a single "burst" read?

 

EDIT:

Yes, it is possible to "burst" read:

AndrewNeil_0-1719936223012.png

Look at the overheads for reading each byte separately (sequence 3) rather than multiple bytes together (sequence 4):

AndrewNeil_1-1719936295766.png

 

 

I've implemented a single read from the data buffer, but it still takes a long time. I don't know if I'm asking too much in wanting the read to be done instantly, on the Atmega it worked fine.
The time to do all 2048 reads is 2.2 seconds. (I measured this by putting the read function in the loop and turning on a led after it was executed, so I was able to measure the time by measuring how long it takes for the led to light up.)

As I now know that my second problem is related to the reading time of the I2C I believe I will have to create another topic focused on this.

But I still have the first problem mentioned in this topic, in which my chip doesn't start the program automatically when it's plugged into the power supply; it only starts after I restart it manually or after uploading code to it.