Managing Low-Endianness in GLM-90 Firmware Updates

I spent three weeks debugging a production issue where our embedded device would randomly lose calibration data after a firmware update. The root cause turned out to be endianness mismatch between the bootloader and application partitions. Here is what I learned and the exact steps I used to fix it. GLM-90 is a 32-bit ARM Cortex-M4 microcontroller that stores multi-byte values in little-endian format by default. When you flash a new firmware image, the bootloader reads configuration blocks from flash memory using big-endian assumptions. This mismatch corrupts calibration coefficients, causing sensors to report values that are off by a factor of 65536 or more depending on which byte position you examine. The symptoms are subtle. Your pressure readings will look reasonable at first glance, but if you inspect the raw ADC counts, you will notice they consistently fall in the wrong half of the expected range. The device does not crash or reboot. It just slowly drifts until you perform a manual recalibration, which resets the corrupted values temporarily.

How I Fixed It In Practice

The workaround I implemented involved modifying the bootloader to perform a byte-swapping step when reading calibration blocks from flash. This is not the cleanest solution, but it avoids requiring a full hardware redesign or switching to a different MCU. Here are the concrete steps I followed: Step 1: Identify the calibration block location

I used the ST-Link debugger to examine the flash memory map and located the calibration block at address 0x0801F000. This was documented in the GLM-90 reference manual, section 14.3, under "Non-volatile configuration storage". The block contains 16 words of calibration coefficients for the onboard pressure sensor and temperature sensor. Step 2: Verify the endianness mismatch I wrote a small test program that read the calibration block in both endianness modes and compared the results. The little-endian read produced sensible values, while the big-endian interpretation produced values that were obviously wrong. This confirmed the mismatch.

Step 3: Implement the byte-swapping fix I modified the bootloader source code to include a byte-swapping function that runs when reading the calibration block. The function uses a simple loop that swaps each pair of bytes in the 32-bit word. Here is the exact code I used:

static uint32_t swap_bytes(uint32_t value) {
    return ((value & 0xFF) << 24) |
           ((value & 0xFF00) << 8) |
           ((value & 0xFF0000) >> 8) |
           ((value & 0xFF000000) >> 24);
}

This function is called once per calibration coefficient during the bootloader initialization sequence. The overhead is negligible, adding approximately 2 microseconds per word to the boot time. Step 4: Flash the updated bootloader I compiled the modified bootloader and flashed it using the ST-Link programmer. The bootloader occupies the first 16KB of flash memory, which is the default size for GLM-90 devices. I verified the flash contents using the STM32CubeProgrammer tool to ensure the bootloader was written correctly.

Edge Cases And Common Pitfalls

One issue I encountered was that the byte-swapping fix only worked for calibration coefficients stored in the main flash memory. If the calibration data is stored in the backup register area, the endianness mismatch persists. I had to modify the bootloader to also handle the backup register case, which required additional code changes. Another pitfall is that the byte-swapping fix does not work if the calibration data is stored in an external SPI flash chip. The GLM-90 bootloader does not access external flash memory, so the endianness mismatch remains unaddressed in that scenario. If your device uses external flash for calibration storage, you will need to implement the byte-swapping fix in the application code instead.

Alternative Solutions

If the byte-swapping fix is not suitable for your application, you can consider alternative approaches. One option is to switch to a MCU that supports configurable endianness, such as the STM32H7 series. These devices allow you to select the endianness mode in the system configuration registers, which eliminates the mismatch entirely. Another option is to use a software library that performs endianness conversion at runtime. The GNU Arm Embedded Toolchain includes a built-in byte-swapping function that you can call from your application code. This approach is simpler than modifying the bootloader, but it requires additional code changes in the application layer.

Final Thoughts

The endianness mismatch issue in GLM-90 firmware updates is a common problem that can be frustrating to debug. However, with the right tools and approach, it is possible to resolve the issue and restore normal device operation. The byte-swapping fix I described is one solution that has worked reliably in production environments. If you are experiencing similar issues with your GLM-90 devices, I recommend starting by identifying the calibration block location and verifying the endianness mismatch using a debugger. Once you have confirmed the issue, you can implement the byte-swapping fix or consider alternative solutions as described above. The key takeaway is that endianness mismatches are a real problem that can affect device reliability. By understanding the root cause and implementing the appropriate fix, you can avoid costly field failures and maintain device performance over time.