Пример #1
0
int
flash_unlock(void *addr, int len, void **err_addr)
{
    unsigned short *block, *end_addr;
    int stat = 0;
    typedef int code_fun(unsigned short *, int, int);
    code_fun *_flash_unlock_block;
    int d_cache, i_cache;

    if (!flash_info.init) {
        return FLASH_ERR_NOT_INIT;
    }

#ifdef CYGSEM_IO_FLASH_SOFT_WRITE_PROTECT
    if (plf_flash_query_soft_wp(addr,len))
        return FLASH_ERR_PROTECT;
#endif

    _flash_unlock_block = (code_fun*) __anonymizer(&flash_unlock_block);

    block = (unsigned short *)((CYG_ADDRESS)addr & flash_info.block_mask);
    end_addr = (unsigned short *)((CYG_ADDRESS)addr+len);

    /* Check to see if end_addr overflowed */
    if( (end_addr < block) && (len > 0) ){
        end_addr = (unsigned short *) ((CYG_ADDRESS) flash_info.end - 1);
    }

#ifdef CYGSEM_IO_FLASH_CHATTER
    (*flash_info.pf)("... Unlock from %p-%p: ", block, end_addr);
#endif

    HAL_FLASH_CACHES_OFF(d_cache, i_cache);
    FLASH_Enable(block, end_addr);
    while (block < end_addr) {
        unsigned short *tmp_block;
        stat = (*_flash_unlock_block)(block, flash_info.block_size, flash_info.blocks);
        stat = flash_hwr_map_error(stat);
        if (stat) {
            *err_addr = (void *)block;
            break;
        }

        tmp_block = block + flash_info.block_size / sizeof(*block);
        if(tmp_block < block){
            // If block address overflows, set block value to end on this loop
            block = end_addr;
        }
        else{
            block = tmp_block;
        }
#ifdef CYGSEM_IO_FLASH_CHATTER
        (*flash_info.pf)(".");
#endif
    }
    FLASH_Disable(block, end_addr);
    HAL_FLASH_CACHES_ON(d_cache, i_cache);
#ifdef CYGSEM_IO_FLASH_CHATTER
    (*flash_info.pf)("\n");
#endif
    return (stat);
}
Пример #2
0
int
flash_program(void *_addr, void *_data, int len, void **err_addr)
{
    int stat = 0;
    int size;
    typedef int code_fun(void *, void *, int, unsigned long, int);
    code_fun *_flash_program_buf;
    unsigned char *addr = (unsigned char *)_addr;
    unsigned char *data = (unsigned char *)_data;
    CYG_ADDRESS tmp;
    int d_cache, i_cache;

    if (!flash_info.init) {
        return FLASH_ERR_NOT_INIT;
    }

#ifdef CYGSEM_IO_FLASH_SOFT_WRITE_PROTECT
    if (plf_flash_query_soft_wp(addr,len))
        return FLASH_ERR_PROTECT;
#endif

    _flash_program_buf = (code_fun*) __anonymizer(&flash_program_buf);

#ifdef CYGSEM_IO_FLASH_CHATTER
    (*flash_info.pf)("... Program from %p-%p at %p: ", (void*)data, 
                     (void*)(((CYG_ADDRESS)data)+len), (void*)addr);
#endif

    HAL_FLASH_CACHES_OFF(d_cache, i_cache);
    FLASH_Enable((unsigned short*)addr, (unsigned short *)(addr+len));
    while (len > 0) {
        size = len;
        if (size > flash_info.block_size) size = flash_info.block_size;

        tmp = (CYG_ADDRESS)addr & ~flash_info.block_mask;
        if (tmp) {
                tmp = flash_info.block_size - tmp;
                if (size>tmp) size = tmp;

        }

        stat = (*_flash_program_buf)(addr, data, size, 
                                     flash_info.block_mask, flash_info.buffer_size);
        stat = flash_hwr_map_error(stat);
#ifdef CYGSEM_IO_FLASH_VERIFY_PROGRAM
        if (0 == stat) // Claims to be OK
            if (memcmp(addr, data, size) != 0) {                
                stat = 0x0BAD;
#ifdef CYGSEM_IO_FLASH_CHATTER
                (*flash_info.pf)("V");
#endif
            }
#endif
        if (stat) {
            *err_addr = (void *)addr;
            break;
        }
#ifdef CYGSEM_IO_FLASH_CHATTER
        (*flash_info.pf)(".");
#endif
        len -= size;
        addr += size/sizeof(*addr);
        data += size/sizeof(*data);
    }
    FLASH_Disable((unsigned short*)addr, (unsigned short *)(addr+len));
    HAL_FLASH_CACHES_ON(d_cache, i_cache);
#ifdef CYGSEM_IO_FLASH_CHATTER
    (*flash_info.pf)("\n");
#endif
    return (stat);
}
Пример #3
0
int
flash_read(void *_addr, void *_data, int len, void **err_addr)
{
#ifdef CYGSEM_IO_FLASH_READ_INDIRECT
    int stat = 0;
    int size;
    typedef int code_fun(void *, void *, int, unsigned long, int);
    code_fun *_flash_read_buf;
    unsigned char *addr = (unsigned char *)_addr;
    unsigned char *data = (unsigned char *)_data;
    CYG_ADDRESS tmp;
    int d_cache, i_cache;

    if (!flash_info.init) {
        return FLASH_ERR_NOT_INIT;
    }

    _flash_read_buf = (code_fun*) __anonymizer(&flash_read_buf);

#ifdef CYGSEM_IO_FLASH_CHATTER
    (*flash_info.pf)("... Read from %p-%p at %p: ", (void*)data, 
                     (void*)(((CYG_ADDRESS)data)+len), (void*)addr);
#endif

    HAL_FLASH_CACHES_OFF(d_cache, i_cache);
    FLASH_Enable((unsigned short*)addr, (unsigned short *)(addr+len));
    while (len > 0) {
        size = len;
        if (size > flash_info.block_size) size = flash_info.block_size;

        tmp = (CYG_ADDRESS)addr & ~flash_info.block_mask;
        if (tmp) {
                tmp = flash_info.block_size - tmp;
                if (size>tmp) size = tmp;

        }

        stat = (*_flash_read_buf)(addr, data, size, 
                                     flash_info.block_mask, flash_info.buffer_size);
        stat = flash_hwr_map_error(stat);
#ifdef CYGSEM_IO_FLASH_VERIFY_PROGRAM_
        if (0 == stat) // Claims to be OK
            if (memcmp(addr, data, size) != 0) {                
                stat = 0x0BAD;
#ifdef CYGSEM_IO_FLASH_CHATTER
                (*flash_info.pf)("V");
#endif
            }
#endif
        if (stat) {
            *err_addr = (void *)addr;
            break;
        }
#ifdef CYGSEM_IO_FLASH_CHATTER
        (*flash_info.pf)(".");
#endif
        len -= size;
        addr += size/sizeof(*addr);
        data += size/sizeof(*data);
    }
    FLASH_Disable((unsigned short*)addr, (unsigned short *)(addr+len));
    HAL_FLASH_CACHES_ON(d_cache, i_cache);
#ifdef CYGSEM_IO_FLASH_CHATTER
    (*flash_info.pf)("\n");
#endif
    return (stat);
#else // CYGSEM_IO_FLASH_READ_INDIRECT
    // Direct access to FLASH memory is possible - just move the requested bytes
    if (!flash_info.init) {
        return FLASH_ERR_NOT_INIT;
    }
    memcpy(_data, _addr, len);
    return FLASH_ERR_OK;
#endif
}
Пример #4
0
int
flash_erase(void *addr, int len, void **err_addr)
{
    unsigned short *block, *end_addr;
    int stat = 0;
    typedef int code_fun(unsigned short *, unsigned int);
    code_fun *_flash_erase_block;
    int d_cache, i_cache;

    if (!flash_info.init) {
        return FLASH_ERR_NOT_INIT;
    }

#ifdef CYGSEM_IO_FLASH_SOFT_WRITE_PROTECT
    if (plf_flash_query_soft_wp(addr,len))
        return FLASH_ERR_PROTECT;
#endif

     _flash_erase_block = (code_fun*) __anonymizer(&flash_erase_block);

    block = (unsigned short *)((CYG_ADDRESS)addr & flash_info.block_mask);
    end_addr = (unsigned short *)((CYG_ADDRESS)addr+len);

    /* Check to see if end_addr overflowed */
    if( (end_addr < block) && (len > 0) ){
        end_addr = (unsigned short *) ((CYG_ADDRESS) flash_info.end - 1);
    }

#ifdef CYGSEM_IO_FLASH_CHATTER
    (*flash_info.pf)("... Erase from %p-%p: ", (void*)block, (void*)end_addr);
#endif

    HAL_FLASH_CACHES_OFF(d_cache, i_cache);
    FLASH_Enable(block, end_addr);
    while (block < end_addr) {
        // Supply the blocksize for a gross check for erase success
        unsigned short *tmp_block;
#if !defined(CYGSEM_IO_FLASH_READ_INDIRECT)
        int i;
        unsigned char *dp;
        bool erased = true;

        dp = (unsigned char *)block;
        for (i = 0;  i < flash_info.block_size;  i++) {
            if (*dp++ != (unsigned char)0xFF) {
                erased = false;
                break;
            }
        }
#else
        bool erased = false;
#endif

        if (!erased) {
            stat = (*_flash_erase_block)(block, flash_info.block_size);
            stat = flash_hwr_map_error(stat);
        }
        if (stat) {
            *err_addr = (void *)block;
            break;
        }

        // Check to see if block will overflow
        tmp_block = block + flash_info.block_size / sizeof(*block);
        if(tmp_block < block){
            // If block address overflows, set block value to end on this loop
            block = end_addr;
        }
        else{
            block = tmp_block;
        }
#ifdef CYGSEM_IO_FLASH_CHATTER
        (*flash_info.pf)(".");
#endif
    }
    FLASH_Disable(block, end_addr);
    HAL_FLASH_CACHES_ON(d_cache, i_cache);
#ifdef CYGSEM_IO_FLASH_CHATTER
    (*flash_info.pf)("\n");
#endif
    return (stat);
}
Пример #5
0
__externC int
cyg_flash_unlock(const cyg_flashaddr_t flash_base,
                 size_t len,
                 cyg_flashaddr_t *err_address)
{
  cyg_flashaddr_t block, end_addr;
  struct cyg_flash_dev * dev;
  size_t unlock_count;
  int stat = CYG_FLASH_ERR_OK;
  HAL_FLASH_CACHES_STATE(d_cache, i_cache);

  dev = find_dev(flash_base, &stat);
  if (!dev) return stat;
  if (!dev->funs->flash_block_unlock) return CYG_FLASH_ERR_INVALID;

  CHECK_SOFT_WRITE_PROTECT(flash_base, len);

  LOCK(dev);
  if (len > (dev->end + 1 - flash_base)) {
      end_addr = dev->end;
  } else {
      end_addr = flash_base + len - 1;
  }
  block         = flash_block_begin(flash_base, dev);
  unlock_count  = (end_addr + 1) - block;

  CHATTER(dev, "... Unlocking from %p-%p: ", (void*)block, (void*)end_addr);

  HAL_FLASH_CACHES_OFF(d_cache, i_cache);
  FLASH_Enable(flash_base, end_addr);
  while (unlock_count > 0) {
    size_t    block_size  = flash_block_size(dev, block);
    if (unlock_count < block_size) {
        unlock_count = block_size;
    }
    stat = dev->funs->flash_block_unlock(dev,block);

    if (CYG_FLASH_ERR_OK != stat && err_address) {
      *err_address = block;
      break;
    }
    block           += block_size;
    unlock_count    -= block_size;

    CHATTER(dev, ".");
  }
  FLASH_Disable(flash_base, end_addr);
  HAL_FLASH_CACHES_ON(d_cache, i_cache);
  CHATTER(dev, "\n");
  UNLOCK(dev);
  if (stat != CYG_FLASH_ERR_OK) {
    return stat;
  }

  // Recurse if necessary for the next device
  if (len > (dev->end + 1 - flash_base)) {
    return cyg_flash_lock(dev->end+1,
                          len - (dev->end + 1 - flash_base),
                          err_address);
  }
  return CYG_FLASH_ERR_OK;
}
Пример #6
0
__externC int
cyg_flash_read(const cyg_flashaddr_t flash_base,
               void *ram_base,
               size_t len,
               cyg_flashaddr_t *err_address)
{
  struct cyg_flash_dev * dev;
  cyg_flashaddr_t addr, end_addr;
  unsigned char * ram = (unsigned char *)ram_base;
  size_t read_count;
  int stat = CYG_FLASH_ERR_OK;

  dev = find_dev(flash_base, &stat);
  if (!dev) return stat;

  LOCK(dev);
  addr = flash_base;
  if (len > (dev->end + 1 - flash_base)) {
      end_addr = dev->end;
  } else {
      end_addr = flash_base + len - 1;
  }
  read_count = (end_addr + 1) - flash_base;

  //  CHATTER(dev, "... Read from %p-%p to %p: ", addr, end_addr, ram_base);

  // If the flash is directly accessible, just read it in one go. This
  // still happens with the mutex locked to protect against concurrent
  // programs/erases.
  if (! dev->funs->flash_read) {
      memcpy(ram, (void*)addr, read_count);
  } else {
#ifndef CYGHWR_IO_FLASH_INDIRECT_READS
      CYG_FAIL("read function supplied but indirect reads not enabled");
      stat = CYG_FLASH_ERR_PROTOCOL;
      if (err_address) {
          *err_address = addr;
      }
#else
      // We have to indirect through the device driver.
      // The first read may be in the middle of a block. Do the necessary
      // adjustment here rather than inside the loop.
      size_t            offset;
      cyg_flashaddr_t   block = flash_block_begin(flash_base, dev);
      HAL_FLASH_CACHES_STATE(d_cache, i_cache);
      if (addr == block) {
          offset = 0;
      } else {
          offset = addr - block;
      }
      HAL_FLASH_CACHES_OFF(d_cache, i_cache);
      FLASH_Enable(flash_base, end_addr);
      while (read_count > 0) {
          size_t block_size = flash_block_size(dev, addr);
          size_t this_read;
          if (read_count > (block_size - offset)) {
              this_read = block_size - offset;
          } else {
              this_read = read_count;
          }
          // Only the first block may need the offset
          offset      = 0;

          FLASH_WATCHDOG_RESET;
          stat = dev->funs->flash_read(dev, addr, ram, this_read);
          if (CYG_FLASH_ERR_OK != stat && err_address) {
              *err_address = addr;
              break;
          }
          //          CHATTER(dev, ".");
          read_count  -= this_read;
          addr        += this_read;
          ram         += this_read;
      }
      FLASH_Disable(flash_base, end_addr);
      HAL_FLASH_CACHES_ON(d_cache, i_cache);
#endif
  }
  //  CHATTER(dev, "\n");
  UNLOCK(dev);
  if (stat != CYG_FLASH_ERR_OK) {
    return (stat);
  }
  if (len > (dev->end + 1 - flash_base)) {
      FLASH_WATCHDOG_RESET;
      return cyg_flash_read(dev->end+1, ram,
                            len - (dev->end + 1 - flash_base),
                            err_address);
  }
  return CYG_FLASH_ERR_OK;
}
Пример #7
0
__externC int
cyg_flash_program(cyg_flashaddr_t flash_base,
                  const void *ram_base,
                  size_t len,
                  cyg_flashaddr_t *err_address)
{
  struct cyg_flash_dev * dev;
  cyg_flashaddr_t addr, end_addr, block;
  const unsigned char * ram = ram_base;
  size_t write_count, offset;
  int stat = CYG_FLASH_ERR_OK;
  HAL_FLASH_CACHES_STATE(d_cache, i_cache);

  dev = find_dev(flash_base, &stat);
  if (!dev) return stat;

  CHECK_SOFT_WRITE_PROTECT(flash_base, len);

  LOCK(dev);
  addr = flash_base;
  if (len > (dev->end + 1 - flash_base)) {
    end_addr = dev->end;
  } else {
    end_addr = flash_base + len - 1;
  }
  write_count = (end_addr + 1) - flash_base;

  // The first write may be in the middle of a block. Do the necessary
  // adjustment here rather than inside the loop.
  block = flash_block_begin(flash_base, dev);
  if (addr == block) {
      offset = 0;
  } else {
      offset = addr - block;
  }

  CHATTER(dev, "... Program from %p-%p to %p: ", ram_base, ((CYG_ADDRESS)ram_base)+write_count, addr);

  HAL_FLASH_CACHES_OFF(d_cache, i_cache);
  FLASH_Enable(flash_base, end_addr);
  while (write_count > 0) {
    size_t block_size = flash_block_size(dev, addr);
    size_t this_write;
    if (write_count > (block_size - offset)) {
        this_write = block_size - offset;
    } else {
        this_write = write_count;
    }
    // Only the first block may need the offset.
    offset       = 0;

    FLASH_WATCHDOG_RESET;
    stat = dev->funs->flash_program(dev, addr, ram, this_write);
#ifdef CYGSEM_IO_FLASH_VERIFY_PROGRAM
    if (CYG_FLASH_ERR_OK == stat) // Claims to be OK
      if (!dev->funs->flash_read && memcmp((void *)addr, ram, this_write) != 0) {
        stat = CYG_FLASH_ERR_DRV_VERIFY;
        CHATTER(dev, "V");
      }
#endif
    if (CYG_FLASH_ERR_OK != stat) {
        if (err_address)
            *err_address = addr;
        break;
    }
    CHATTER(dev, ".");
    write_count -= this_write;
    addr        += this_write;
    ram         += this_write;
  }
  FLASH_Disable(flash_base, end_addr);
  HAL_FLASH_CACHES_ON(d_cache, i_cache);
  CHATTER(dev, "\n");
  UNLOCK(dev);
  if (stat != CYG_FLASH_ERR_OK) {
    return (stat);
  }
  if (len > (dev->end + 1 - flash_base)) {
    FLASH_WATCHDOG_RESET;
    return cyg_flash_program(dev->end+1, ram,
                             len - (dev->end + 1 - flash_base),
                             err_address);
  }
  return CYG_FLASH_ERR_OK;
}
Пример #8
0
__externC int
cyg_flash_erase(cyg_flashaddr_t flash_base,
                size_t len,
                cyg_flashaddr_t *err_address)
{
  cyg_flashaddr_t block, end_addr;
  struct cyg_flash_dev * dev;
  size_t erase_count;
  int stat = CYG_FLASH_ERR_OK;
  HAL_FLASH_CACHES_STATE(d_cache, i_cache);

  dev = find_dev(flash_base, &stat);
  if (!dev) return stat;

  CHECK_SOFT_WRITE_PROTECT(flash_base, len);

  LOCK(dev);

  // Check whether or not we are going past the end of this device, on
  // to the next one. If so the next device will be handled by a
  // recursive call later on.
  if (len > (dev->end + 1 - flash_base)) {
      end_addr = dev->end;
  } else {
      end_addr = flash_base + len - 1;
  }
  // erase can only happen on a block boundary, so adjust for this
  block         = flash_block_begin(flash_base, dev);
  erase_count   = (end_addr + 1) - block;

  CHATTER(dev, "... Erase from %p-%p: ", (void*)block, (void*)end_addr);

  HAL_FLASH_CACHES_OFF(d_cache, i_cache);
  FLASH_Enable(flash_base, end_addr);
  while (erase_count > 0) {
    int i;
    unsigned char *dp;
    bool erased = false;
    size_t block_size = flash_block_size(dev, block);

    // Pad to the block boundary, if necessary
    if (erase_count < block_size) {
        erase_count = block_size;
    }

    // If there is a read function it probably means the flash
    // cannot be read directly.
    if (!dev->funs->flash_read) {
      erased = true;
      dp = (unsigned char *)block;
      for (i = 0;  i < block_size;  i++) {
        if (*dp++ != (unsigned char)0xFF) {
          erased = false;
          break;
        }
      }
    }
    if (!erased) {
      FLASH_WATCHDOG_RESET;
      stat = dev->funs->flash_erase_block(dev,block);
    }
    if (CYG_FLASH_ERR_OK != stat) {
        if (err_address)
            *err_address = block;
        break;
    }
    block       += block_size;
    erase_count -= block_size;
    CHATTER(dev, ".");
  }
  FLASH_Disable(flash_base, end_addr);
  HAL_FLASH_CACHES_ON(d_cache, i_cache);
  CHATTER(dev, "\n");
  UNLOCK(dev);
  if (stat != CYG_FLASH_ERR_OK) {
    return stat;
  }

  // If there are multiple flash devices in series the erase operation
  // may touch successive devices. This can be handled by recursion.
  // The stack overheads should be minimal because the number of
  // devices will be small.
  if (len > (dev->end + 1 - flash_base)) {
    return cyg_flash_erase(dev->end+1,
                           len - (dev->end + 1 - flash_base),
                           err_address);
  }
  return CYG_FLASH_ERR_OK;
}