Hello,
In my quest of working with pstorage_raw.c I found an annoying situation when I tried to clear small portions (as I thought by using raw I would have full control).
The pstorage_clear
method directly calls sd_flash_page_erase(page);
and by doing that, corrupts other data I had saved on the same page.
My approach to that was to write my own pstorage_clear
which would deal with single word up to page deletions, even if the cleared block spans to new pages.
Here is my implementation of the cmd_process
function:
static uint32_t cmd_process(void){
uint32_t retval;
uint32_t storage_addr;
cmd_queue_element_t * p_cmd;
retval = NRF_ERROR_FORBIDDEN;
p_cmd = &m_cmd_queue.cmd[m_cmd_queue.rp];
storage_addr = p_cmd->storage_addr.block_id;
uint32_t size = p_cmd->size;
uint32_t offset = p_cmd->offset;
switch (p_cmd->op_code) {
case PSTORAGE_STORE_OP_CODE: {
uint8_t * p_data_addr = p_cmd->p_data_addr;
offset = (m_round_val * SOC_MAX_WRITE_SIZE);
size = p_cmd->size - offset;
p_data_addr += offset;
storage_addr += (p_cmd->offset + offset);
if (size < SOC_MAX_WRITE_SIZE){
retval = sd_flash_write(((uint32_t *)storage_addr),
(uint32_t *)p_data_addr,
size / sizeof(uint32_t));
}
else {
retval = sd_flash_write(((uint32_t *)storage_addr),
(uint32_t *)p_data_addr,
SOC_MAX_WRITE_SIZE / sizeof(uint32_t));
}
}
break;
case PSTORAGE_CLEAR_OP_CODE: {
uint32_t page_start, page_end, page;
page_start = (storage_addr / PSTORAGE_FLASH_PAGE_SIZE);
page_end = ((storage_addr + size) / PSTORAGE_FLASH_PAGE_SIZE);
for(page = page_start; page <= page_end; page++){
// get page
memcpy(page_swap, (uint32_t *)(page * PSTORAGE_FLASH_PAGE_SIZE), PSTORAGE_FLASH_PAGE_SIZE);
// first page
if(page == page_start){
offset = (storage_addr - (page * PSTORAGE_FLASH_PAGE_SIZE)); // distance from page start
if((size + offset) > PSTORAGE_FLASH_PAGE_SIZE){ // if it goes to another page, delete from this page to the end
memset(page_swap + offset, 0xFF, PSTORAGE_FLASH_PAGE_SIZE - offset);
else // if not, delete from offset to size
memset(page_swap + offset, 0xFF, size);
} else if(page == page_end){ // second page
memset(page_swap, 0xFF, size - (PSTORAGE_FLASH_PAGE_SIZE - offset)); // delete the remaining size
}
retval = sd_flash_page_erase(page);
if (retval != NRF_SUCCESS)
break;
retval = sd_flash_write((uint32_t *) (page * PSTORAGE_FLASH_PAGE_SIZE), (uint32_t *) page_swap, PSTORAGE_FLASH_PAGE_SIZE / sizeof(uint32_t));
if (retval != NRF_SUCCESS)
break;
}
}
break;
default:
// Should never reach here.
break;
}
if (retval == NRF_SUCCESS)
{
m_cmd_queue.flash_access = true;
}
return retval;
}
In this implementation, I use a 1KB RAM buffer serving as swap page, which is fine for my application.
The problem here is that I am getting NRF_ERROR_BUSY
on the sd_flash_write
call from the PSTORAGE_CLEAR_OP_CODE
branch. The page is cleared, but the data from swap RAM buffer fails to be re-written on that page. And also, the queue is never empty anymore, so the command is not processed again.
By using the pstorage queue, wouldn't I supposed to have CPU time to do this operation as well? What am I missing here?
Sorry, but complex questions require long explanations.
Thanks in advance and best regards,
Victor