void SpiFlash::readCmd(cTerm & t,int argc,char *argv[]) { if (argc > 2) { cyg_uint32 addr = (cyg_uint32)strtoul(argv[1],NULL,16); cyg_uint32 num = (cyg_uint32)strtoul(argv[2],NULL,16); cyg_uint8 buff[num]; int error = cyg_flash_read(addr, buff, num, 0); if (!error) { t<<t.format(GREEN("Read %d bytes from serial flash at address 0x%08X\n"), num, addr); // for (cyg_uint32 i = 0 ; i < num ; i++) // { // diag_printf(" 0x%02X", buff[i]); // // } diag_dump_buf(buff, num); diag_printf("\n"); } else { t<<(RED("Error reading from serial flash!\n")); printfError(error); } } else { t<<"You need to supply an address and number of bytes to read\n"; } }
/** * Restore parameters of object dictionary from flash memory. * \param[in] FlashAddress Use CO_OD_Flash_Adress for the normal parameter * block and CO_OD_Flash_Default_Param for the * default parameters */ static CO_SDO_abortCode_t restoreParameters(cyg_flashaddr_t FlashAddress, uint8_t ParametersSub) { CO_DBG_PRINT("Restore parameters\n"); cyg_flashaddr_t ErrorAddress; int Result = cyg_flash_read(FlashAddress, &CO_OD_ROM, sizeof(CO_OD_ROM), &ErrorAddress); CHECK_FLASH_RESULT(Result); if (CYG_FLASH_ERR_OK != Result) { return CO_SDO_AB_HW; } return CO_SDO_AB_NONE; }
/** * Initialize flash library and data storage in flash * We use two blocks in flash for data storage. One block is used for the * default data that will be restored. The default parameters are stored * at address CO_OD_Flash_Default_Param. The data that will be loaded at * startup or saved if user modifies data is store at CO_OD_Flash_Adress. */ void CO_FlashInit(void) { int i = 0; // // Initialize flash library // int Result = cyg_flash_init(0); CHECK_FLASH_RESULT(Result); #ifdef CYGDBG_IO_CANOPEN_DEBUG cyg_flash_set_global_printf(diag_printf); #endif // // Read info about flash device (number of blocks. block size) // Result = cyg_flash_get_info(0, &flash_info); CHECK_FLASH_RESULT(Result); CO_DBG_PRINT("Flash info dev %d: 0x%x - 0x%x, %d blocks\n", 0, flash_info.start, flash_info.end, flash_info.num_block_infos); const cyg_flash_block_info_t* block_info = flash_info.block_info; for (i = 0; i < flash_info.num_block_infos; ++i) { CO_DBG_PRINT("Block %d: block size: %d blocks: %d\n", i, block_info->block_size, block_info->blocks); block_info++; } // // Calculate addresses for flash data and default flash data // block_info = &flash_info.block_info[flash_info.num_block_infos - 1]; CO_DBG_PRINT("Last block - block size: %d blocks: %d\n", block_info->block_size, block_info->blocks); CO_OD_Flash_Adress = flash_info.end + 1 + (CYGNUM_CANOPEN_FLASH_DATA_BLOCK * block_info->block_size); CO_DBG_PRINT("CO_OD_Flash_Adress 0x%8x\n", CO_OD_Flash_Adress); CO_OD_Flash_Default_Param = CO_OD_Flash_Adress - block_info->block_size; CO_DBG_PRINT("CO_OD_Flash_Default_Param 0x%8x\n", CO_OD_Flash_Default_Param); // // Before we can access the data, we need to make sure, that the flash // block are properly initialized. We do this by reading the block into // a local sCO_OD_ROM variable and verifying the FirstWord and LastWord // members // cyg_flashaddr_t ErrorAddress; struct sCO_OD_ROM DefaultObjDicParam; Result = cyg_flash_read(CO_OD_Flash_Default_Param, &DefaultObjDicParam, sizeof(DefaultObjDicParam), &ErrorAddress); CHECK_FLASH_RESULT(Result); // // If the default parameters are not present in flash, then we know that // we need to create them for later restore // if ((DefaultObjDicParam.FirstWord != CO_OD_FIRST_LAST_WORD) ||(DefaultObjDicParam.LastWord != CO_OD_FIRST_LAST_WORD)) { storeParameters(CO_OD_Flash_Adress, OD_H1010_STORE_PARAM_ALL); storeParameters(CO_OD_Flash_Default_Param, OD_H1010_STORE_PARAM_ALL); } else { restoreParameters(CO_OD_Flash_Adress, OD_H1010_STORE_PARAM_ALL); } }
__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; }