Exemple #1
0
MSC_RAMFUNC_DEFINITION_END


/***************************************************************************//**
 * @brief
 *   Internal flash write function with select write strategy parameter
 * @param[in] address
 *   Write address
 * @param[in] data
 *   Pointer to the first data word to load.
 * @param[in] numBytes
 *   Number of data bytes to load, must be a multiple of 4 bytes.
 * @param[in] writeStrategy
 *   Write strategy to apply.
 * @return
 *   Returns the status of the data load operation
 ******************************************************************************/
MSC_RAMFUNC_DEFINITION_BEGIN
MSC_Status_TypeDef MSC_WriteWordI(uint32_t *address,
                                  void const *data,
                                  uint32_t numBytes,
                                  MSC_WriteStrategy_Typedef writeStrategy)
{
  uint32_t wordCount;
  uint32_t numWords;
  uint32_t pageWords;
  uint32_t* pData;
  MSC_Status_TypeDef retval = mscReturnOk;

  /* Check alignment (Must be aligned to words) */
  EFM_ASSERT(((uint32_t) address & 0x3) == 0);

  /* Check number of bytes. Must be divisable by four */
  EFM_ASSERT((numBytes & 0x3) == 0);

#if defined( _EMU_STATUS_VSCALE_MASK )
  /* VSCALE must be done and flash write requires VSCALE2 */
  EFM_ASSERT(!(EMU->STATUS & _EMU_STATUS_VSCALEBUSY_MASK));
  EFM_ASSERT((EMU->STATUS & _EMU_STATUS_VSCALE_MASK) == EMU_STATUS_VSCALE_VSCALE2);
#endif

  /* Enable writing to the MSC */
  MSC->WRITECTRL |= MSC_WRITECTRL_WREN;

  /* Convert bytes to words */
  numWords = numBytes >> 2;
  EFM_ASSERT(numWords > 0);

  /* The following loop splits the data into chunks corresponding to flash pages.
     The address is loaded only once per page, because the hardware automatically
     increments the address internally for each data load inside a page. */
  for (wordCount = 0, pData = (uint32_t *)data; wordCount < numWords; )
  {
    /* First we load address. The address is auto-incremented within a page.
       Therefore the address phase is only needed once for each page. */
    retval = MSC_LoadVerifyAddress(address + wordCount);
    if (mscReturnOk != retval)
    {
      return retval;
    }
    /* Compute the number of words to write to the current page. */
    pageWords =
      (FLASH_PAGE_SIZE -
       (((uint32_t) (address + wordCount)) & (FLASH_PAGE_SIZE - 1)))
      / sizeof(uint32_t);
    if (pageWords > numWords - wordCount)
    {
      pageWords = numWords - wordCount;
    }
    /* Now write the data in the current page. */
    retval = MSC_LoadWriteData(pData, pageWords, writeStrategy);
    if (mscReturnOk != retval)
    {
      break;
    }
    wordCount += pageWords;
    pData += pageWords;
  }

#if defined( ERRATA_FIX_FLASH_E201_EN )
  /* Fix for errata FLASH_E201 - Potential program failure after Power On.
   *
   * Check if the first word was programmed correctly. If a failure is detected
   * then retry programming of the first word.
   *
   * Full description of errata can be found in the errata document */
  pData = (uint32_t *) data;
  if (*address != *pData)
  {
    retval = MSC_LoadVerifyAddress(address);
    if (mscReturnOk == retval)
    {
      retval = MSC_LoadWriteData(pData, 1, writeStrategy);
    }
  }
#endif

  /* Disable writing to the MSC */
  MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;

#if defined( _MSC_WRITECTRL_WDOUBLE_MASK )
#if ( WORDS_PER_DATA_PHASE == 2 )
  /* Turn off double word write cycle support. */
  MSC->WRITECTRL &= ~MSC_WRITECTRL_WDOUBLE;
#endif
#endif

  return retval;
}
Exemple #2
0
/* "Possible rom access from within a __ramfunc function"               */
#pragma diag_suppress=Ta022
#pragma diag_suppress=Ta023
#endif
#endif /* !EM_MSC_RUN_FROM_FLASH */
static MSC_Status_TypeDef MSC_WriteWordI(uint32_t *address,
                                         void const *data,
                                         uint32_t numBytes,
                                         MSC_WriteStrategy_Typedef writeStrategy)
{
  uint32_t wordCount;
  uint32_t numWords;
  uint32_t pageWords;
  uint32_t* pData;
  MSC_Status_TypeDef retval = mscReturnOk;

  /* Check alignment (Must be aligned to words) */
  EFM_ASSERT(((uint32_t) address & 0x3) == 0);

  /* Check number of bytes. Must be divisable by four */
  EFM_ASSERT((numBytes & 0x3) == 0);

  /* Enable writing to the MSC */
  MSC->WRITECTRL |= MSC_WRITECTRL_WREN;

  /* Convert bytes to words */
  numWords = numBytes >> 2;
  EFM_ASSERT(numWords > 0);

  /* The following loop splits the data into chunks corresponding to flash pages.
     The address is loaded only once per page, because the hardware automatically
     increments the address internally for each data load inside a page. */
  for (wordCount = 0, pData = (uint32_t *)data; wordCount < numWords; )
  {
    /* First we load address. The address is auto-incremented within a page.
       Therefore the address phase is only needed once for each page. */
    retval = MSC_LoadVerifyAddress(address + wordCount);
    if (mscReturnOk != retval)
    {
      return retval;
    }
    /* Compute the number of words to write to the current page. */
    pageWords =
      (FLASH_PAGE_SIZE -
       (((uint32_t) (address + wordCount)) & (FLASH_PAGE_SIZE - 1)))
      / sizeof(uint32_t);
    if (pageWords > numWords - wordCount)
    {
      pageWords = numWords - wordCount;
    }
    /* Now write the data in the current page. */
    retval = MSC_LoadWriteData(pData, pageWords, writeStrategy);
    if (mscReturnOk != retval)
    {
      break;
    }
    wordCount += pageWords;
    pData += pageWords;
  }

  /* Disable writing to the MSC */
  MSC->WRITECTRL &= ~MSC_WRITECTRL_WREN;

#if defined( _MSC_WRITECTRL_WDOUBLE_MASK )
#if ( WORDS_PER_DATA_PHASE == 2 )
  /* Turn off double word write cycle support. */
  MSC->WRITECTRL &= ~MSC_WRITECTRL_WDOUBLE;
#endif
#endif

  return retval;
}