Saving config data with FlashIAP on STM32L476RG isn't persisting the data

I’m attempting to do what is a relatively common task: use a bit of my STM32L476RG’s flash as user data storage to persist a configuration across reboots of the device. I’m following what is described at microcontroller - Allocating memory in Flash for user data (STM32F4 HAL) - Stack Overflow for the linker setup and the Mbed OS documentation for FlashIAP.

I’ve got a custom linker file that includes the following:

MEMORY
{
  FLASH (rx)  : ORIGIN = 0x08000000, LENGTH = 0x100000 - 128k
  DATA  (rwx) : ORIGIN = 0x080E0000, LENGTH = 128k
  SRAM2 (rwx) : ORIGIN = 0x10000000 + (((98 * 4) + 7) & 0xFFFFFFF8), LENGTH = 0x8000 - (((98 * 4) + 7) & 0xFFFFFFF8)
  SRAM1 (rwx) : ORIGIN = 0x20000000, LENGTH = 0x18000
}

[...]

    .user_data :
    {
        . = ALIGN(8);
        *(.user_data)
        . = ALIGN(8);
    } > DATA

In my code I have a couple of defines for the start of the user data and the size, as well as a static variable that points to that location in flash:

#define FLASH_USER_DATA_START 0x080E0000
#define FLASH_USER_DATA_SIZE 0x20000 // 128k

static uint8_t userConfig[64] __attribute__((__section__(".user_data")));
static const char *testBuffer = "Hello";

My code to store the data is:

void MFConfiguration::Save()
{
  auto flash = new FlashIAP();

  flash->init();
  flash->erase(FLASH_USER_DATA_START, FLASH_USER_DATA_SIZE);
  flash->program(testBuffer, FLASH_USER_DATA_START, 8);
  flash->deinit();
}

If I step through this in the debugger the erase step works correctly (userConfig becomes all 0xff as expected) and after the program step I see Hello in userConfig.

However when I re-run the app under the debugger, userConfig is 0x00 :frowning:

Anyone have any tips for what I might be missing? Thanks!

Ok, answering my own question. You must program an entire sector (2048 bytes in my case). Changing my code to write a full 2048 byte buffer made it work!