Writing to SAMD21 Flash

Hi there,
I am trying to write (a lot) of sensor data to the internal flash of a SAMD21 chip during execution. I am aware of the FlashStorage library from Cmaglie but it does not quite work for my application (storing 200kB of binary data).
I am also well aware of the limited number of write cycle of the flash and it is not an issue for my application.

I have been reading the SAMD21 datasheet and I am trying to adapt Cmaglie FlashStorage library to do my bidding.
In the example code below I am trying to write a 64 Byte array to one page of flash (but if I can figure it out I would like to write bigger array). The code keep freezing after "Test5" is printed (during the erase operation).
I am not very familiar with pointers and I have kind of tried to adapt the library but I probably made a mistake there since it relies heavily on pointers and I don't understand fully what it does.
I have been careful about the required 256 bytes alignment and the page size, row size and number of page match the particular chip I am using (SAMD21E18A).

Here is the code:

const uint32_t PAGE_SIZE = 64;
const uint32_t PAGES = 4096;
const uint32_t MAX_FLASH = 262144;
const uint32_t ROW_SIZE = 256;
uint8_t ram_buffer[64];
uint32_t adress_row;
const volatile void *flash_address;
const void *data_address;


void setup()
{

	Serial.begin(1000000);
	delay(2000);
	Serial.println("Test");
	adress_row = 0X8000; //leave 32kB for the firmware
	data_address = &ram_buffer;
	flash_address = &adress_row;
	for (int i = 0; i < 64; i++) { ram_buffer[i] =i;  } // fill the buffer
	Serial.println("Test1");


	flash_erase(&adress_row,256); // erase one row
	
	flash_write(flash_address, ram_buffer, 64); //  write the buffer to flash


	for (int i = 0; i < 64; i++) { ram_buffer[i] = 0; } // empty ram_buffer
	for (int i = 0; i < 64; i++) { Serial.println(ram_buffer[i]); delay(10); } 
	delay(100);
	
	flash_read(flash_address, ram_buffer, 64); // read flash and put the data in ram_buffer
	for (int i = 0; i < 64; i++) { Serial.println(ram_buffer[i]); delay(10); } // display data in ram_buffer
}

void loop()
{


	Serial.println("Test");
	delay(2000);
}

void flash_write(const volatile void *flash_ptr, const void *data, uint32_t size)

{
	// Calculate data boundaries
	size = (size + 3) / 4;
	volatile uint32_t *dst_addr = (volatile uint32_t *)flash_ptr;
	const uint8_t *src_addr = (uint8_t *)data;

	// Disable automatic page write
	NVMCTRL->CTRLB.bit.MANW = 1;

	// Do writes in pages
	while (size) {
		// Execute "PBC" Page Buffer Clear
		NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_PBC;
		while (NVMCTRL->INTFLAG.bit.READY == 0) {}

		// Fill page buffer
		uint32_t i;
		for (i = 0; i<(PAGE_SIZE / 4) && size; i++) {
			*dst_addr = flash_read_unaligned_uint32(src_addr);
			src_addr += 4;
			dst_addr++;
			size--;
			Serial.println(size);
		}

		// Execute "WP" Write Page
		NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_WP;
		while (NVMCTRL->INTFLAG.bit.READY == 0) {}
	}
}

static inline uint32_t flash_read_unaligned_uint32(const void *data)
{
	union {
		uint32_t u32;
		uint8_t u8[4];
	} res;
	const uint8_t *d = (const uint8_t *)data;
	res.u8[0] = d[0];
	res.u8[1] = d[1];
	res.u8[2] = d[2];
	res.u8[3] = d[3];
	//Serial.println(res.u32);
	return res.u32;
}

void flash_erase(const volatile void *flash_ptr, uint32_t size)
{
	const uint8_t *ptr = (const uint8_t *)flash_ptr;
	Serial.println("Test2");
	while (size > ROW_SIZE) {
		Serial.println("Test3");
		flash_erase(ptr);
		ptr += ROW_SIZE;
		size -= ROW_SIZE;
	}
	Serial.println("Test4");
	delay(100);
	flash_erase(ptr);
}

void flash_erase(const volatile void *flash_ptr)
{
	NVMCTRL->ADDR.reg = ((uint32_t)flash_ptr) / 2;
	Serial.println("Test5");
	delay(100);
	NVMCTRL->CTRLA.reg = NVMCTRL_CTRLA_CMDEX_KEY | NVMCTRL_CTRLA_CMD_ER;
	delay(1000); Serial.println("Test6"); delay(1000);
	while (!NVMCTRL->INTFLAG.bit.READY) {}
	Serial.println("Test7");
}

void flash_read(const volatile void *flash_ptr, void *data, uint32_t size)
{
	memcpy(data, (const void *)flash_ptr, size);
}

Any insight would be much appreciated!

Thanks,
Olivier