X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fflash%2Fnor%2Fdsp5680xx_flash.c;h=38649ff0409ddc857b9bcfb9956f92d5ae1cc952;hp=9fa7b06fe35c6789bbc5aed3de2867dec0a9f7fb;hb=f9d7554ee490e39a5cba3cd4eb2c28ec72ba407f;hpb=7b0ead520dcf6969954f42255a01e63b89f96cd6 diff --git a/src/flash/nor/dsp5680xx_flash.c b/src/flash/nor/dsp5680xx_flash.c index 9fa7b06fe3..38649ff040 100644 --- a/src/flash/nor/dsp5680xx_flash.c +++ b/src/flash/nor/dsp5680xx_flash.c @@ -18,201 +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; + + 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; } -// flash bank dsp5680xx 0 0 0 0 -FLASH_BANK_COMMAND_HANDLER(dsp5680xx_flash_bank_command){ - struct dsp5680xx_flash_bank *nbank; +/* 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); - nbank = malloc(sizeof(struct dsp5680xx_flash_bank)); + return ERROR_OK; +} - 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); +/** + * 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 + */ +static int dsp5680xx_flash_protect_check(struct flash_bank *bank) +{ + int retval = ERROR_OK; - return ERROR_OK; -} + uint16_t protected = 0; -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; + 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; } -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); - if(retval == ERROR_OK){ - for(int i = first;isectors[i].is_protected = 1; - } - }else{ - retval = dsp5680xx_f_unlock(bank->target); - if(retval == ERROR_OK) - for(int i = first;isectors[i].is_protected = 0; - } - 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 + * @param set Apply or remove security on the chip. + * @param first This parameter is ignored. + * @param last This parameter is ignored. + * + * @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; -/* -static int dsp5680xx_write_block(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count){ - LOG_USER("%s not implemented",__FUNCTION__); - return ERROR_OK; + 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; } -static int dsp5680xx_write_single(struct flash_bank *bank, uint8_t *buffer, uint32_t offset, uint32_t count){ - LOG_USER("%s not implemented",__FUNCTION__); - return ERROR_OK; -} -*/ - -//-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -//-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -// Flash stuff test -//-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -//-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - -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); - if(retval == ERROR_OK) - bank->sectors[0].is_erased = 0; - else - bank->sectors[0].is_erased = -1; - 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 + * @param buffer Data to write to flash. + * @param offset + * @param count In bytes (2 bytes per address). + * + * @return + */ +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; } -/* -static int dsp5680xx_set_write_enable(struct target *target, int enable){ - LOG_USER("%s not implemented",__FUNCTION__); - 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 + */ +static int dsp5680xx_flash_erase(struct flash_bank *bank, int first, int last) +{ + int retval; -static int dsp5680xx_check_flash_completion(struct target* target, unsigned int timeout_ms){ - LOG_USER("%s not implemented",__FUNCTION__); - return ERROR_OK; -} -*/ - -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; + 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; } -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; +/** + * 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 + */ +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