X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fflash%2Fnor%2Fdsp5680xx_flash.c;h=38649ff0409ddc857b9bcfb9956f92d5ae1cc952;hp=d804088f34980c728e394f26040d1953e6eaf625;hb=42f1cc576ab9b503fadd0b8916a139cd0bc6563e;hpb=c725167ba8e2aa9e43bc86e28b44b6cb444740a8 diff --git a/src/flash/nor/dsp5680xx_flash.c b/src/flash/nor/dsp5680xx_flash.c index d804088f34..38649ff040 100644 --- a/src/flash/nor/dsp5680xx_flash.c +++ b/src/flash/nor/dsp5680xx_flash.c @@ -18,235 +18,253 @@ * GNU General Public License for more details. * * * * You should have received a copy of the GNU General Public License * - * along with this program; if not, write to the * - * Free Software Foundation, Inc., * - * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + * along with this program. If not, see . * ***************************************************************************/ /** * @file dsp5680xx_flash.c * @author Rodrigo L. Rosa * @date Thu Jun 9 18:21:58 2011 - * + * * @brief This file implements the basic functions to run flashing commands * from the TCL interface. * It allows the user to flash the Freescale 5680xx DSP. - * - * + * + * */ - #ifdef HAVE_CONFIG_H #include "config.h" #endif -#ifndef DSP5680XX_FLASH_H -#define DSP5680XX_FLASH_H - #include "imp.h" #include #include #include #include -struct dsp5680xx_flash_bank { - struct working_area *write_algorithm; -}; +static int dsp5680xx_build_sector_list(struct flash_bank *bank) +{ + uint32_t offset = HFM_FLASH_BASE_ADDR; -static int dsp5680xx_build_sector_list(struct flash_bank *bank){ - uint32_t offset = HFM_FLASH_BASE_ADDR; - bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors); - int i; - for (i = 0; i < bank->num_sectors; ++i){ - bank->sectors[i].offset = i*HFM_SECTOR_SIZE; - bank->sectors[i].size = HFM_SECTOR_SIZE; - offset += bank->sectors[i].size; - bank->sectors[i].is_erased = -1; - bank->sectors[i].is_protected = -1; - } - LOG_USER("%s not tested yet.",__FUNCTION__); - return ERROR_OK; - -} + bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors); + int i; -// flash bank dsp5680xx 0 0 0 0 -FLASH_BANK_COMMAND_HANDLER(dsp5680xx_flash_bank_command){ - struct dsp5680xx_flash_bank *nbank; + for (i = 0; i < bank->num_sectors; ++i) { + bank->sectors[i].offset = i * HFM_SECTOR_SIZE; + bank->sectors[i].size = HFM_SECTOR_SIZE; + offset += bank->sectors[i].size; + bank->sectors[i].is_erased = -1; + bank->sectors[i].is_protected = -1; + } + LOG_USER("%s not tested yet.", __func__); + return ERROR_OK; - nbank = malloc(sizeof(struct dsp5680xx_flash_bank)); +} - bank->base = HFM_FLASH_BASE_ADDR; - bank->size = HFM_SIZE_BYTES; // top 4k not accessible - bank->driver_priv = nbank; - bank->num_sectors = HFM_SECTOR_COUNT; - dsp5680xx_build_sector_list(bank); +/* flash bank dsp5680xx 0 0 0 0 */ +FLASH_BANK_COMMAND_HANDLER(dsp5680xx_flash_bank_command) +{ + bank->base = HFM_FLASH_BASE_ADDR; + bank->size = HFM_SIZE_BYTES; /* top 4k not accessible */ + bank->num_sectors = HFM_SECTOR_COUNT; + dsp5680xx_build_sector_list(bank); - return ERROR_OK; + return ERROR_OK; } -/** +/** * A memory mapped register (PROT) holds information regarding sector protection. * Protection refers to undesired core access. * The value in this register is loaded from flash upon reset. - * - * @param bank - * - * @return + * + * @param bank + * + * @return */ -static int dsp5680xx_flash_protect_check(struct flash_bank *bank){ - int retval = ERROR_OK; - uint16_t protected = 0; - retval = dsp5680xx_f_protect_check(bank->target,&protected); - if(retval != ERROR_OK){ - for(int i = 0;isectors[i].is_protected = -1; - return ERROR_OK; - } - for(int i = 0;isectors[2*i].is_protected = 1; - bank->sectors[2*i+1].is_protected = 1; - }else{ - bank->sectors[2*i].is_protected = 0; - bank->sectors[2*i+1].is_protected = 0; - } - protected = (protected >> 1); - } - return retval; +static int dsp5680xx_flash_protect_check(struct flash_bank *bank) +{ + int retval = ERROR_OK; + + uint16_t protected = 0; + + retval = dsp5680xx_f_protect_check(bank->target, &protected); + if (retval != ERROR_OK) { + for (int i = 0; i < HFM_SECTOR_COUNT; i++) + bank->sectors[i].is_protected = -1; + return ERROR_OK; + } + for (int i = 0; i < HFM_SECTOR_COUNT / 2; i++) { + if (protected & 1) { + bank->sectors[2 * i].is_protected = 1; + bank->sectors[2 * i + 1].is_protected = 1; + } else { + bank->sectors[2 * i].is_protected = 0; + bank->sectors[2 * i + 1].is_protected = 0; + } + protected = (protected >> 1); + } + return retval; } -/** +/** * Protection funcionality is not implemented. * The current implementation applies/removes security on the chip. - * The chip is effectively secured/unsecured after the first reset following the execution of this function. - * - * @param bank + * The chip is effectively secured/unsecured after the first reset + * following the execution of this function. + * + * @param bank * @param set Apply or remove security on the chip. * @param first This parameter is ignored. * @param last This parameter is ignored. - * - * @return + * + * @return */ -static int dsp5680xx_flash_protect(struct flash_bank *bank, int set, int first, int last){ - // This applies security to flash module after next reset, it does not actually apply protection (protection refers to undesired access from the core) - int retval; - if(set) - retval = dsp5680xx_f_lock(bank->target); -else{ - retval = dsp5680xx_f_unlock(bank->target); - if (retval == ERROR_OK) { - /* mark all as erased */ - for (int i = 0; i <= (HFM_SECTOR_COUNT-1); i++) - /* FM does not recognize it as erased if erased via JTAG. */ - bank->sectors[i].is_erased = 1; +static int dsp5680xx_flash_protect(struct flash_bank *bank, int set, int first, + int last) +{ +/** + * This applies security to flash module after next reset, it does + * not actually apply protection (protection refers to undesired access from the core) + */ + int retval; + + if (set) + retval = dsp5680xx_f_lock(bank->target); + else { + retval = dsp5680xx_f_unlock(bank->target); + if (retval == ERROR_OK) { + /* mark all as erased */ + for (int i = 0; i <= (HFM_SECTOR_COUNT - 1); i++) + /* FM does not recognize it as erased if erased via JTAG. */ + bank->sectors[i].is_erased = 1; + } } -} - return retval; + return retval; } -/** - * The dsp5680xx use word addressing. The "/2" that appear in the following code are a workaround for the fact that OpenOCD uses byte addressing. - * - * @param bank +/** + * The dsp5680xx use word addressing. The "/2" that appear in the following code + * are a workaround for the fact that OpenOCD uses byte addressing. + * + * @param bank * @param buffer Data to write to flash. - * @param offset + * @param offset * @param count In bytes (2 bytes per address). - * - * @return + * + * @return */ -static int dsp5680xx_flash_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count){ - int retval; - if((offset + count/2)>bank->size){ - LOG_ERROR("%s: Flash bank cannot fit data.",__FUNCTION__); - return ERROR_FAIL; - } - if(offset%2){ - LOG_ERROR("%s: Writing to odd addresses not supported. This chip uses word addressing, Openocd only supports byte addressing. The workaround results in disabling writing to odd byte addresses.",__FUNCTION__); - return ERROR_FAIL; - } - retval = dsp5680xx_f_wr(bank->target, buffer, bank->base + offset/2, count, 0); - uint32_t addr_word; - for(addr_word = bank->base + offset/2;addr_wordsectors[addr_word/(HFM_SECTOR_SIZE/2)].is_erased = 0; - else - bank->sectors[addr_word/(HFM_SECTOR_SIZE/2)].is_erased = -1; - } - return retval; -} +static int dsp5680xx_flash_write(struct flash_bank *bank, const uint8_t* buffer, + uint32_t offset, uint32_t count) +{ + int retval; -static int dsp5680xx_probe(struct flash_bank *bank){ - LOG_DEBUG("%s not implemented",__FUNCTION__); - return ERROR_OK; + if ((offset + count / 2) > bank->size) { + LOG_ERROR("%s: Flash bank cannot fit data.", __func__); + return ERROR_FAIL; + } + if (offset % 2) { + /** + * Writing to odd addresses not supported. + * This chip uses word addressing, Openocd only supports byte addressing. + * The workaround results in disabling writing to odd byte addresses + */ + LOG_ERROR("%s: Writing to odd addresses not supported for this target", __func__); + return ERROR_FAIL; + } + retval = dsp5680xx_f_wr(bank->target, buffer, bank->base + offset / 2, count, 0); + uint32_t addr_word; + + for (addr_word = bank->base + offset / 2; addr_word < count / 2; + addr_word += (HFM_SECTOR_SIZE / 2)) { + if (retval == ERROR_OK) + bank->sectors[addr_word / (HFM_SECTOR_SIZE / 2)].is_erased = 0; + else + bank->sectors[addr_word / (HFM_SECTOR_SIZE / 2)].is_erased = -1; + } + return retval; } -static int dsp5680xx_flash_info(struct flash_bank *bank, char *buf, int buf_size){ - snprintf(buf, buf_size, "\ndsp5680xx flash driver info:\n - Currently only full erase/lock/unlock are implemented. \n - Call with bank==0 and sector 0 to 0.\n - Protect requires arp_init-reset to complete. \n - Before removing protection the master tap must be selected, and arp_init-reset is required to complete unlocking."); +static int dsp5680xx_probe(struct flash_bank *bank) +{ + LOG_DEBUG("%s not implemented", __func__); return ERROR_OK; } -/** - * The flash module (FM) on the dsp5680xx supports both individual sector and mass erase of the flash memory. - * If this function is called with @first == @last == 0 or if @first is the first sector (#0) and @last is the last sector then the mass erase command is executed (much faster than erasing each sector individually). - * - * @param bank - * @param first - * @param last - * - * @return +/** + * The flash module (FM) on the dsp5680xx supports both individual sector + * and mass erase of the flash memory. + * If this function is called with @first == @last == 0 or if @first is the + * first sector (#0) and @last is the last sector then the mass erase command + * is executed (much faster than erasing each sector individually). + * + * @param bank + * @param first + * @param last + * + * @return */ -static int dsp5680xx_flash_erase(struct flash_bank * bank, int first, int last){ - int retval; - retval = dsp5680xx_f_erase(bank->target, (uint32_t) first, (uint32_t) last); - if(retval == ERROR_OK) - for(int i = first;i<=last;i++) - bank->sectors[i].is_erased = 1; - else - // If an error occurred unknown status is set even though some sector could have been correctly erased. - for(int i = first;i<=last;i++) - bank->sectors[i].is_erased = -1; - return retval; +static int dsp5680xx_flash_erase(struct flash_bank *bank, int first, int last) +{ + int retval; + + retval = dsp5680xx_f_erase(bank->target, (uint32_t) first, (uint32_t) last); + if ((!(first | last)) || ((first == 0) && (last == (HFM_SECTOR_COUNT - 1)))) + last = HFM_SECTOR_COUNT - 1; + if (retval == ERROR_OK) + for (int i = first; i <= last; i++) + bank->sectors[i].is_erased = 1; + else + /** + * If an error occurred unknown status + *is set even though some sector could have been correctly erased. + */ + for (int i = first; i <= last; i++) + bank->sectors[i].is_erased = -1; + return retval; } -/** +/** * The flash module (FM) on the dsp5680xx support a blank check function. * This function executes the FM's blank check functionality on each and every sector. - * - * @param bank - * - * @return + * + * @param bank + * + * @return */ -static int dsp5680xx_flash_erase_check(struct flash_bank * bank){ - int retval = ERROR_OK; - uint8_t erased = 0; - uint32_t i; - for(i=0;isectors[i].is_erased == -1){ - retval = dsp5680xx_f_erase_check(bank->target,&erased,i); - if (retval != ERROR_OK){ - bank->sectors[i].is_erased = -1; - }else{ - if(erased) - bank->sectors[i].is_erased = 1; - else - bank->sectors[i].is_erased = 0; - } - } - } - return retval; +static int dsp5680xx_flash_erase_check(struct flash_bank *bank) +{ + int retval = ERROR_OK; + + uint8_t erased = 0; + + uint32_t i; + + for (i = 0; i < HFM_SECTOR_COUNT; i++) { + if (bank->sectors[i].is_erased == -1) { + retval = dsp5680xx_f_erase_check(bank->target, &erased, i); + if (retval != ERROR_OK) { + bank->sectors[i].is_erased = -1; + } else { + if (erased) + bank->sectors[i].is_erased = 1; + else + bank->sectors[i].is_erased = 0; + } + } + } + return retval; } struct flash_driver dsp5680xx_flash = { - .name = "dsp5680xx_flash", - .flash_bank_command = dsp5680xx_flash_bank_command, - .erase = dsp5680xx_flash_erase, - .protect = dsp5680xx_flash_protect, - .write = dsp5680xx_flash_write, - //.read = default_flash_read, - .probe = dsp5680xx_probe, - .auto_probe = dsp5680xx_probe, - .erase_check = dsp5680xx_flash_erase_check, - .protect_check = dsp5680xx_flash_protect_check, - .info = dsp5680xx_flash_info + .name = "dsp5680xx_flash", + .flash_bank_command = dsp5680xx_flash_bank_command, + .erase = dsp5680xx_flash_erase, + .protect = dsp5680xx_flash_protect, + .write = dsp5680xx_flash_write, + /* .read = default_flash_read, */ + .probe = dsp5680xx_probe, + .auto_probe = dsp5680xx_probe, + .erase_check = dsp5680xx_flash_erase_check, + .protect_check = dsp5680xx_flash_protect_check, }; -#endif // dsp5680xx_flash.h