예제 #1
0
/**********************************************************
 * Writes one word to flash.
 *
 * @param addr
 *    Address to write to. Must be a valid flash address.
 * 
 * @param data
 *    Word to write
 **********************************************************/
static void pgmWord( uint32_t addr, uint32_t data )
{
  MSC->ADDRB    = addr;
  MSC->WRITECMD = MSC_WRITECMD_LADDRIM;
  MSC->WDATA    = data;
  doFlashCmd( MSC_WRITECMD_WRITEONCE );
}
예제 #2
0
/**********************************************************
 * Erases on page of flash. 
 *
 * @param addr
 *    Address of page. Must be a valid flash address.
 * 
 * @param pagesize
 *    Size of one page in bytes
 **********************************************************/
static void eraseSector( uint32_t addr, uint32_t pagesize )
{
  uint32_t *p = (uint32_t*)addr, result;

  /* Check if page already is erased. If so we can
   * simply return. */
  do
  {
    result    = *p++;
    pagesize -= 4;
  } while ( pagesize && ( result == 0xFFFFFFFF ) );

  if ( result != 0xFFFFFFFF )
  {
    /* Erase the page */
    MSC->ADDRB    = addr;
    MSC->WRITECMD = MSC_WRITECMD_LADDRIM;
    doFlashCmd( MSC_WRITECMD_ERASEPAGE );
  }
}
예제 #3
0
uint32_t flashSize(void) {
  return doFlashCmd(AVR32_FLASHC_CMD_SIZE);
}
예제 #4
0
void main(void)
{
  uint8_t  *pBuff;
  uint32_t addr, burst, pageMask, byteCount;

  /* Relocate vector table */
  SCB->VTOR = 0x20000000;
    
  /* Disable interrupts */
  __disable_irq();
  
  /* Signal setup */
  state.flashLoaderStatus = FLASHLOADER_STATUS_NOT_READY;
  state.debuggerStatus = DEBUGGERCMD_NOT_CONNECTED;

  /* Get device info including memory size */
  setupEFM32();
  
  /* Calculate size of available buffers. Two buffers are
   * used. Each buffer will  fill up half of the remaining RAM. 
   * Round down to nearest word boundry */
  state.bufferSize = (state.sramSize - ((uint32_t) &flashBuffer - 0x20000000)) / 2;
  
  /* Only use full 4 bytes (1 word) */
  state.bufferSize = state.bufferSize & 0xFFFFFFFC;
   
  /* Set the address of both buffers  */
  state.bufferAddress1 = (uint32_t) &flashBuffer;
  state.bufferAddress2 = ((uint32_t) &flashBuffer) + state.bufferSize;

  /* Signal setup complete. Ready to accept commands from programmer. */
  state.flashLoaderStatus = FLASHLOADER_STATUS_READY;

  /* Poll debuggerStatus field to listen for commands
   * from programmer */
  while(1)
  {
    
    /* Erase page(s) command */
    if (state.debuggerStatus == DEBUGGERCMD_ERASE_PAGE)
    {
      /* Clear the flag to indicate that we are busy */
      state.flashLoaderStatus = FLASHLOADER_STATUS_NOT_READY;
      state.debuggerStatus = DEBUGGERCMD_NONE;

      /* Enable flash writes */
      MSC->WRITECTRL |= MSC_WRITECTRL_WREN;
      
      /* Get address of first page to erase */
      uint32_t writeAddress = state.writeAddress1;
      
      /* Erase all pages in the given range */
      for (addr = writeAddress; addr < writeAddress + state.numBytes1; addr += state.pageSize)
      {
        eraseSector( addr, state.pageSize );
      }
      
      /* Disable flash writes */
      MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;

      /* Operation complete. Set flag to ready again. */
      state.flashLoaderStatus = FLASHLOADER_STATUS_READY;
    }
    
    /* Mass erase command */
    if (state.debuggerStatus == DEBUGGERCMD_MASS_ERASE)
    {
      /* Clear the flag to indicate that we are busy */
      state.flashLoaderStatus = FLASHLOADER_STATUS_NOT_READY;
      state.debuggerStatus = DEBUGGERCMD_NONE;

      /* Enable flash writes */
      MSC->WRITECTRL |= MSC_WRITECTRL_WREN;
      
      /* Unlock Mass Erase */
      MSC->MASSLOCK = 0x631A;
      
      /* Erase entire flash */
      doFlashCmd(MSC_WRITECMD_ERASEMAIN0 | MSC_WRITECMD_ERASEMAIN1);
      
      /* Reset lock */
      MSC->MASSLOCK = 0;
      
      /* Disable flash writes again */
      MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;

      /* Operation complete. Set flag to ready again. */
      state.flashLoaderStatus = FLASHLOADER_STATUS_READY;
    }
    

    /* Write command */
    if (state.debuggerStatus == DEBUGGERCMD_WRITE_DATA1 || state.debuggerStatus == DEBUGGERCMD_WRITE_DATA2 )
    {
      /* Select buffer based on write command */
      bool useBuffer1 = state.debuggerStatus == DEBUGGERCMD_WRITE_DATA1 ? true : false;
      
      /* Clear the flag to indicate that we are busy */
      state.flashLoaderStatus = FLASHLOADER_STATUS_NOT_READY;
      state.debuggerStatus = DEBUGGERCMD_NONE;

      pageMask  = ~(state.pageSize - 1);
      
      /* Set up buffer, size and destination */
      pBuff     = useBuffer1 ? (uint8_t *)state.bufferAddress1 : (uint8_t *)state.bufferAddress2;
      byteCount = useBuffer1 ? state.numBytes1                 : state.numBytes2;
      addr      = useBuffer1 ? state.writeAddress1             : state.writeAddress2;

      /* Enable flash writes */
      MSC->WRITECTRL |= MSC_WRITECTRL_WREN;

      /* Use double word writes if available */
      if ( ( byteCount > 7 ) && writeDouble )
      {
        if ( addr & 7 )   /* Start address not on 8 byte boundary ? */
        {
          pgmWord( addr, *(uint32_t*)pBuff );
          pBuff     += 4;
          addr      += 4;
          byteCount -= 4;
        }

        /* Enable double word writes */
        MSC->WRITECTRL |= MSC_WRITECTRL_WDOUBLE;
        
        /* Writes as many words as possible using double word writes */
        while ( byteCount > 7 )
        {         
          /* Max burst len is up to next flash page boundary. */
          burst = MIN( byteCount, ( ( addr + state.pageSize ) & pageMask ) - addr );
 
          /* Write data to flash */
          burst -= pgmBurstDouble( addr, (uint32_t*)pBuff, burst );

          pBuff     += burst;
          addr      += burst;
          byteCount -= burst;
        }
        
        /* Wait until operations are complete */
        mscStatusWait( MSC_STATUS_BUSY, 0 );
        
        /* Disable double word writes */
        MSC->WRITECTRL &= ~MSC_WRITECTRL_WDOUBLE;
      }

      /* Writes all remaining bytes */
      while ( byteCount )
      {
        /* Max burst len is up to next flash page boundary. */
        burst = MIN( byteCount, ( ( addr + state.pageSize ) & pageMask ) - addr );

        /* Write data to flash */
        pgmBurst( addr, (uint32_t*)pBuff, burst );

        pBuff     += burst;
        addr      += burst;
        byteCount -= burst;
      }
      
      /* Wait until operations are complete */
      mscStatusWait( MSC_STATUS_BUSY, 0 );

      /* Disable flash writes */
      MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;

      /* Operation complete. Set flag to ready again. */
      state.flashLoaderStatus = FLASHLOADER_STATUS_READY;
    }
  }
}