/* Function: void APP_NVMwriteWord (uint32_t address, uint32_t data) Summary: Writes a word in flash memory (4 bytes) */ void APP_NVMwriteWord(uint32_t address, uint32_t data) { /* Base address of where word is to be written */ PLIB_NVM_FlashAddressToModify(NVM_ID_0, virtualToPhysical(address)); /* Word of data to be written */ PLIB_NVM_FlashProvideData(NVM_ID_0 , data); /* Disable flash write/erase operations */ PLIB_NVM_MemoryModifyInhibit(NVM_ID_0); /* Select Word Program operation */ PLIB_NVM_MemoryOperationSelect(NVM_ID_0, WORD_PROGRAM_OPERATION); /* Enable flash write/erase operations */ PLIB_NVM_MemoryModifyEnable(NVM_ID_0); /* Write the unlock key sequence */ PLIB_NVM_FlashWriteKeySequence(NVM_ID_0, 0x0); PLIB_NVM_FlashWriteKeySequence(NVM_ID_0, 0xAA996655); PLIB_NVM_FlashWriteKeySequence(NVM_ID_0, 0x556699AA); /* Start Writing */ PLIB_NVM_FlashWriteStart(NVM_ID_0); bttask_setState(BTTASK_STATE_INTERNAL_NVM_WRITE_START); }
static void PerformOperation(uint32_t nvmop) { // Disable flash write/erase operations PLIB_NVM_MemoryModifyInhibit(NVM_ID_0); PLIB_NVM_MemoryOperationSelect(NVM_ID_0, nvmop); // Allow memory modifications PLIB_NVM_MemoryModifyEnable(NVM_ID_0); /* Unlock the Flash */ PLIB_NVM_FlashWriteKeySequence(NVM_ID_0, 0); PLIB_NVM_FlashWriteKeySequence(NVM_ID_0, NVM_PROGRAM_UNLOCK_KEY1); PLIB_NVM_FlashWriteKeySequence(NVM_ID_0, NVM_PROGRAM_UNLOCK_KEY2); PLIB_NVM_FlashWriteStart(NVM_ID_0); }
/* Function: void APP_NVMDisableOperation (void) Summary: Disables write operations to nvm. */ void APP_NVMDisableOperation(void) { /* Disable future Flash Write/Erase operations */ PLIB_NVM_MemoryModifyInhibit(NVM_ID_0); }
DRV_NVM_BUFFER_HANDLE DRV_NVM_EraseWrite ( DRV_HANDLE handle, uint8_t * destination, uint8_t * source, const unsigned int nBytes ) { int iEntry; DRV_NVM_BUFFER_OBJECT * bufferObj; DRV_NVM_CLIENT_OBJECT * clientObj; DRV_NVM_OBJECT * dObj; bool interruptWasEnabled; uint32_t erasePageAddress; /* Validate the driver handle */ clientObj = _DRV_NVM_ClientHandleValidate(handle); if(NULL == clientObj) { /* Handle is not valid */ return (DRV_NVM_BUFFER_HANDLE_INVALID); } if((NULL == destination) || (NULL == source) ||(0 == nBytes)) { return (DRV_NVM_BUFFER_HANDLE_INVALID); } if(!(clientObj->intent & DRV_IO_INTENT_WRITE)) { /* Driver was not opened for write */ return (DRV_NVM_BUFFER_HANDLE_INVALID); } if((uint32_t)(destination) % DRV_NVM_ROW_SIZE != 0) { /* Address should be row aligned */ return(DRV_NVM_BUFFER_HANDLE_INVALID); } dObj = clientObj->driverObj; /* Disable the interrupt so that any * write operation from an interrupt context * does not interfere. */ interruptWasEnabled = _DRV_NVM_InterruptSourceDisable (dObj->interruptSource); for(iEntry = 0; iEntry < DRV_NVM_BUFFER_OBJECT_NUMBER; iEntry ++) { if(gDrvNVMBufferObject[iEntry].inUse == false) { /* Found a buffer object that can be used */ bufferObj = &gDrvNVMBufferObject[iEntry]; bufferObj->inUse = true; bufferObj->appDataPointer = source; bufferObj->flashMemPointer = destination; bufferObj->size = nBytes; bufferObj->status = DRV_NVM_BUFFER_QUEUED; bufferObj->flag = DRV_NVM_BUFFER_FLAG_ERASE_WRITE; bufferObj->hClient = handle; bufferObj->bufferHandle = (gDrvNVMBufferToken << 16) | iEntry; bufferObj->next = NULL; bufferObj->previous = NULL; /* Set the nBlockPending and block size to 0 to indicate that * we have not started processing this yet. */ bufferObj->nBlocksPending = 0; bufferObj->blockSize = 0; /* Update the token number. If it reaches 0xFFFF * then reset it*/ gDrvNVMBufferToken ++; gDrvNVMBufferToken = (gDrvNVMBufferToken == 0xFFFF) ? 0 : gDrvNVMBufferToken; if(dObj->writeEraseQ == NULL) { /* This means the queue is empty */ dObj->writeEraseQ = bufferObj; /* For an erase write request the number of blocks pending * first will 1 and a page will be erased. The total number * of blocks to program is tracked in the hardware instance * object. */ dObj->nRowsPending = nBytes/DRV_NVM_ROW_SIZE; dObj->appDataMemory = source; dObj->eraseWriteStartAddress = (uint32_t)destination; dObj->eraseWriteStep = DRV_NVM_ERASE_WRITE_STEP_ERASE_COMPLETE; /* Obtain the page address that contains this row and then * set up the buffer object to erase it */ erasePageAddress = ((uint32_t)destination / DRV_NVM_PAGE_SIZE) * DRV_NVM_PAGE_SIZE; bufferObj->status = DRV_NVM_BUFFER_IN_PROGRESS; bufferObj->nBlocksPending = 1; bufferObj->blockSize = DRV_NVM_PAGE_SIZE; bufferObj->flashMemPointer = (uint8_t *)erasePageAddress; /* Make a back up of the page to be erased */ for(iEntry = 0; iEntry < DRV_NVM_PAGE_SIZE; iEntry ++) { dObj->eraseBuffer[iEntry] = bufferObj->flashMemPointer[iEntry]; } PLIB_NVM_MemoryModifyInhibit(dObj->moduleId); _DRV_NVM_EraseBufferObjProcess(dObj, bufferObj); } else { /* This means there is already a buffer queued * up. We add the buffer to the linked list */ DRV_NVM_BUFFER_OBJECT * iterator; iterator = dObj->writeEraseQ; /* Find the last object in the queue */ while(iterator->next != NULL) { iterator = iterator->next; } /* Append the buffer object to the last buffer * object in the queue */ iterator->next = bufferObj; bufferObj->previous = iterator; bufferObj->next = NULL; } if(interruptWasEnabled) { _DRV_NVM_InterruptSourceEnable(dObj->interruptSource); } /*OSAL Mutex UnLock */ return((DRV_NVM_BUFFER_HANDLE)bufferObj->bufferHandle); } } /* Execution reaches here if a buffer object could not be allocated */ if(interruptWasEnabled) { /* Re-Enable the interrupt if it was enabled */ _DRV_NVM_InterruptSourceEnable(dObj->interruptSource); } /* Could not find a buffer object */ return(DRV_NVM_BUFFER_HANDLE_INVALID); }