예제 #1
0
int up_progmem_erasepage(uint16_t page)
{
    uint32_t addr;
    uint16_t count;

    if (page >= STM32_FLASH_NPAGES)
        return -EFAULT;

    /* Get flash ready and begin erasing single page */
    
    if ( !(getreg32(STM32_RCC_CR) & RCC_CR_HSION) )
        return -EPERM;
    
    stm32_flash_unlock();
        
    modifyreg32(STM32_FLASH_CR, 0, FLASH_CR_PER);
    putreg32(page * STM32_FLASH_PAGESIZE, STM32_FLASH_AR);
    modifyreg32(STM32_FLASH_CR, 0, FLASH_CR_STRT);
    
    while( getreg32(STM32_FLASH_SR) & FLASH_SR_BSY ) up_waste();
    
    modifyreg32(STM32_FLASH_CR, FLASH_CR_PER, 0);
    
    /* Verify */
    
    for (addr = page * STM32_FLASH_PAGESIZE + STM32_FLASH_BASE, count = STM32_FLASH_PAGESIZE; 
         count; count-=4, addr += 4) {
         
        if (getreg32(addr) != 0xFFFFFFFF)
            return -EIO;
    }
    
    return STM32_FLASH_PAGESIZE;
}
예제 #2
0
void stm32_rcc_enablelse(void)
{
  /* The LSE is in the RTC domain and write access is denied to this domain
   * after reset, you have to enable write access using DBP bit in the PWR CR
   * register before to configuring the LSE.
   */

  stm32_pwr_enablebkp(true);

#if defined(CONFIG_STM32_STM32L15XX)
  /* Enable the External Low-Speed (LSE) oscillator by setting the LSEON bit
   * the RCC CSR register.
   */

  modifyreg32(STM32_RCC_CSR, 0, RCC_CSR_LSEON);

  /* Wait for the LSE clock to be ready */

  while ((getreg32(STM32_RCC_CSR) & RCC_CSR_LSERDY) == 0)
    {
      up_waste();
    }

#else
  /* Enable the External Low-Speed (LSE) oscillator by setting the LSEON bit
   * the RCC BDCR register.
   */

  modifyreg16(STM32_RCC_BDCR, 0, RCC_BDCR_LSEON);

  /* Wait for the LSE clock to be ready */

  while ((getreg16(STM32_RCC_BDCR) & RCC_BDCR_LSERDY) == 0)
    {
      up_waste();
    }

#endif

  /* Disable backup domain access if it was disabled on entry */

  stm32_pwr_enablebkp(false);
}
예제 #3
0
void stm32_flash_unlock(void)
{
    while( getreg32(STM32_FLASH_SR) & FLASH_SR_BSY ) up_waste();

    if ( getreg32(STM32_FLASH_CR) & FLASH_CR_LOCK ) {
    
        /* Unlock sequence */
        
        putreg32(FLASH_KEY1, STM32_FLASH_KEYR);
        putreg32(FLASH_KEY2, STM32_FLASH_KEYR);
    }
}
예제 #4
0
/**
 * \todo Check for LSE good timeout and return with -1,
 *   possible ISR optimization? or at least ISR should be cough in case of failure
 */
void stm32_rcc_enablelse(void)
{
    /* Enable LSE */
    modifyreg16(STM32_RCC_BDCR, 0, RCC_BDCR_LSEON);

    /* We could wait for ISR here ... */
    while( !(getreg16(STM32_RCC_BDCR) & RCC_BDCR_LSERDY) ) up_waste();
    
    /* Select LSE as RTC Clock Source */
    modifyreg16(STM32_RCC_BDCR, RCC_BDCR_RTCSEL_MASK, RCC_BDCR_RTCSEL_LSE);
    
    /* Enable Clock */
    modifyreg16(STM32_RCC_BDCR, 0, RCC_BDCR_RTCEN);    
}
예제 #5
0
int up_progmem_write(uint32_t addr, const void *buf, size_t count)
{
    uint16_t *hword = (uint16_t *)buf;
    size_t written = count;

    /* STM32 requires half-word access */
    
    if (count & 1)
        return -EINVAL;
        
    /* Check for valid address range */
        
    if ( (addr+count) >= STM32_FLASH_SIZE)
        return -EFAULT;

    /* Get flash ready and begin flashing */
    
    if ( !(getreg32(STM32_RCC_CR) & RCC_CR_HSION) )
        return -EPERM;
        
    stm32_flash_unlock();
    
    modifyreg32(STM32_FLASH_CR, 0, FLASH_CR_PG);
    
    for (addr += STM32_FLASH_BASE; count; count--, hword++, addr+=2) {
            
        /* Write half-word and wait to complete */
    
        putreg16(*hword, addr);
        
        while( getreg32(STM32_FLASH_SR) & FLASH_SR_BSY ) up_waste();
        
        /* Verify */
        
        if (getreg32(STM32_FLASH_SR) & FLASH_SR_WRPRT_ERR) {
            modifyreg32(STM32_FLASH_CR, FLASH_CR_PG, 0);
            return -EROFS;
        }
        
        if (getreg16(addr) != *hword) {
            modifyreg32(STM32_FLASH_CR, FLASH_CR_PG, 0);
            return -EIO;
        }
        
    }
    
    modifyreg32(STM32_FLASH_CR, FLASH_CR_PG, 0);
    return written;
}
예제 #6
0
void stm32_spi2select(FAR struct spi_dev_s *dev, enum spi_dev_e devid, bool selected)
{
    spidbg("devid: %d CS: %s\n", (int)devid, selected ? "assert" : "de-assert");
    
    if (devid == SPIDEV_WIRELESS) {
    
        stm32_gpiowrite(GPIO_CC1101_CS, !selected);

        /* Wait for MISO to go low, indicates that Quart has stabilized */
        if (selected) {
            while( stm32_gpioread(GPIO_SPI2_MISO) ) up_waste();
        }
        
    }
}
예제 #7
0
static void flash_unlock(uintptr_t base)
{
  while ((getreg32(base + STM32_FLASH_SR_OFFSET) & FLASH_SR_BSY) != 0)
    {
      up_waste();
    }

  if ((getreg32(base + STM32_FLASH_CR_OFFSET) & FLASH_CR_LOCK) != 0)
    {
      /* Unlock sequence */

      putreg32(FLASH_KEY1, base + STM32_FLASH_KEYR_OFFSET);
      putreg32(FLASH_KEY2, base + STM32_FLASH_KEYR_OFFSET);
    }
}
예제 #8
0
ssize_t up_progmem_write(size_t addr, const void *buf, size_t count)
{
  uintptr_t base;
  uint16_t *hword = (uint16_t *)buf;
  size_t written = count;

#if defined(STM32_FLASH_DUAL_BANK)
  /* Handle paged FLASH */

  if (page >= STM32_FLASH_BANK0_NPAGES)
    {
      base = STM32_FLASH_BANK1_BASE;
    }
  else
#endif
    {
      base = STM32_FLASH_BANK0_BASE;
    }

  /* STM32 requires half-word access */

  if (count & 1)
    {
      return -EINVAL;
    }

  /* Check for valid address range */

  if (addr >= STM32_FLASH_BASE)
    {
      addr -= STM32_FLASH_BASE;
    }

  if ((addr+count) > STM32_FLASH_SIZE)
    {
      return -EFAULT;
    }

  sem_lock();

  if ((getreg32(base + STM32_RCC_CR_OFFSET) & RCC_CR_HSION) == 0)
    {
      sem_unlock();
      return -EPERM;
    }

  /* Get flash ready and begin flashing */

  flash_unlock(base);

  modifyreg32(base + STM32_FLASH_CR_OFFSET, 0, FLASH_CR_PG);

  for (addr += STM32_FLASH_BASE; count; count -= 2, hword++, addr += 2)
    {
      /* Write half-word and wait to complete */

      putreg16(*hword, addr);

      while ((getreg32(base + STM32_FLASH_SR_OFFSET) & FLASH_SR_BSY) != 0)
        {
          up_waste();
        }

      /* Verify */

      if ((getreg32(base + STM32_FLASH_SR_OFFSET) & FLASH_SR_WRPRT_ERR) != 0)
        {
          modifyreg32(base + STM32_FLASH_CR_OFFSET, FLASH_CR_PG, 0);
          sem_unlock();
          return -EROFS;
        }

      if (getreg16(addr) != *hword)
        {
          modifyreg32(base + STM32_FLASH_CR_OFFSET, FLASH_CR_PG, 0);
          sem_unlock();
          return -EIO;
        }
    }

  modifyreg32(base + STM32_FLASH_CR_OFFSET, FLASH_CR_PG, 0);

  sem_unlock();
  return written;
}
예제 #9
0
ssize_t up_progmem_eraseblock(size_t block)
{
  uintptr_t base;
  size_t page_address;

  if (block >= STM32_FLASH_NPAGES)
    {
      return -EFAULT;
    }

#if defined(STM32_FLASH_DUAL_BANK)
  /* Handle paged FLASH */

  if (block >= STM32_FLASH_BANK0_NPAGES)
    {
      base = STM32_FLASH_BANK1_BASE;
    }
  else
#endif
    {
      base = STM32_FLASH_BANK0_BASE;
    }

  sem_lock();

  if ((getreg32(base + STM32_RCC_CR_OFFSET) & RCC_CR_HSION) == 0)
    {
      sem_unlock();
      return -EPERM;
    }

  /* Get flash ready and begin erasing single page */

  flash_unlock(base);

  modifyreg32(base + STM32_FLASH_CR_OFFSET, 0, FLASH_CR_PER);

  /* Must be valid - page index checked above */

  page_address = up_progmem_getaddress(block);
  putreg32(page_address, base + STM32_FLASH_AR_OFFSET);

  modifyreg32(base + STM32_FLASH_CR_OFFSET, 0, FLASH_CR_STRT);

  while ((getreg32(base + STM32_FLASH_SR_OFFSET) & FLASH_SR_BSY) != 0)
    {
      up_waste();
    }

  modifyreg32(base + STM32_FLASH_CR_OFFSET, FLASH_CR_PER, 0);
  sem_unlock();

  /* Verify */

  if (up_progmem_ispageerased(block) == 0)
    {
      return up_progmem_erasesize(block); /* success */
    }
  else
    {
      return -EIO; /* failure */
    }
}