/*
  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);
}
Exemplo n.º 2
0
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);
}
Exemplo n.º 4
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);
}