Mysterious NVM write protection
Figured it out. I was issuing the Erase Page command instead of the Erase Block command. Erase page is only for the USER data page in flash and not the main flash bank. 

Here is the code that worked for me:

if((flash_addr % BLOCK_SIZE) == 0)
{
    // Set the NVM block address that we want to erase
    NVMCTRL-&gt;ADDR.reg = blockAddress;

    // Unlock the region that contains our address
    NVMCTRL-&gt;CTRLB.reg = NVMCTRL_CTRLB_CMDEX_KEY | NVMCTRL_CTRLB_CMD_UR;

    // Wait until the NVM controller is ready
    while (0 == NVMCTRL-&gt;STATUS.bit.READY);

    // Erase the block that contains our address
    NVMCTRL-&gt;CTRLB.reg = NVMCTRL_CTRLB_CMDEX_KEY | NVMCTRL_CTRLB_CMD_EB;

    // Wait until the NVM controller is ready
    while (0 == NVMCTRL-&gt;STATUS.bit.READY);
}

for (int i = 0; i &lt; PAGE_SIZE /4; i++)
{
    flash_buf[i] = *(uint32_t *) (memoryLocation + (i));
}
while (0 == NVMCTRL-&gt;STATUS.bit.READY);