X-Git-Url: https://review.openocd.org/gitweb?p=openocd.git;a=blobdiff_plain;f=src%2Fflash%2Fstellaris.c;h=dc9de7425a947fa31da00bab189ef2ad45c58d8f;hp=68a5179d00c40051605de92ff2c2762b77563d15;hb=86ca2270f40d650a849e778518e7aa9c2c713341;hpb=bc08425e6df6a2dc799d4f5eb6ccc6fc26029477 diff --git a/src/flash/stellaris.c b/src/flash/stellaris.c index 68a5179d00..dc9de7425a 100644 --- a/src/flash/stellaris.c +++ b/src/flash/stellaris.c @@ -43,20 +43,25 @@ #include #include +#define DID0_VER(did0) ((did0>>28)&0x07) int stellaris_register_commands(struct command_context_s *cmd_ctx); int stellaris_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank); int stellaris_erase(struct flash_bank_s *bank, int first, int last); int stellaris_protect(struct flash_bank_s *bank, int set, int first, int last); int stellaris_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count); +int stellaris_auto_probe(struct flash_bank_s *bank); int stellaris_probe(struct flash_bank_s *bank); int stellaris_erase_check(struct flash_bank_s *bank); int stellaris_protect_check(struct flash_bank_s *bank); int stellaris_info(struct flash_bank_s *bank, char *buf, int buf_size); +int stellaris_read_part_info(struct flash_bank_s *bank); u32 stellaris_get_flash_status(flash_bank_t *bank); void stellaris_set_flash_mode(flash_bank_t *bank,int mode); u32 stellaris_wait_status_busy(flash_bank_t *bank, u32 waitbits, int timeout); +int stellaris_read_part_info(struct flash_bank_s *bank); + flash_driver_t stellaris_flash = { .name = "stellaris", @@ -66,6 +71,7 @@ flash_driver_t stellaris_flash = .protect = stellaris_protect, .write = stellaris_write, .probe = stellaris_probe, + .auto_probe = stellaris_auto_probe, .erase_check = stellaris_erase_check, .protect_check = stellaris_protect_check, .info = stellaris_info @@ -74,35 +80,142 @@ flash_driver_t stellaris_flash = struct { u32 partno; - char partname[]; + char *partname; } StellarisParts[] = { {0x01,"LM3S101"}, {0x02,"LM3S102"}, + {0x19,"LM3S300"}, {0x11,"LM3S301"}, {0x12,"LM3S310"}, + {0x1A,"LM3S308"}, {0x13,"LM3S315"}, {0x14,"LM3S316"}, + {0x17,"LM3S317"}, + {0x18,"LM3S318"}, {0x15,"LM3S328"}, + {0x2A,"LM3S600"}, {0x21,"LM3S601"}, + {0x2B,"LM3S608"}, {0x22,"LM3S610"}, {0x23,"LM3S611"}, {0x24,"LM3S612"}, {0x25,"LM3S613"}, {0x26,"LM3S615"}, + {0x28,"LM3S617"}, + {0x29,"LM3S618"}, {0x27,"LM3S628"}, + {0x38,"LM3S800"}, {0x31,"LM3S801"}, + {0x39,"LM3S808"}, {0x32,"LM3S811"}, {0x33,"LM3S812"}, {0x34,"LM3S815"}, + {0x36,"LM3S817"}, + {0x37,"LM3S818"}, {0x35,"LM3S828"}, + {0x51,"LM3S2110"}, + {0x52,"LM3S2739"}, + {0x53,"LM3S2651"}, + {0x54,"LM3S2939"}, + {0x55,"LM3S2965"}, + {0x56,"LM3S2432"}, + {0x57,"LM3S2620"}, + {0x58,"LM3S2950"}, + {0x59,"LM3S2412"}, + {0x5A,"LM3S2533"}, + {0x61,"LM3S8630"}, + {0x62,"LM3S8970"}, + {0x63,"LM3S8730"}, + {0x64,"LM3S8530"}, + {0x65,"LM3S8930"}, + {0x71,"LM3S6610"}, + {0x72,"LM3S6950"}, + {0x73,"LM3S6965"}, + {0x74,"LM3S6110"}, + {0x75,"LM3S6432"}, + {0x76,"LM3S6537"}, + {0x77,"LM3S6753"}, + {0x78,"LM3S6952"}, + {0x82,"LM3S6422"}, + {0x83,"LM3S6633"}, + {0x84,"LM3S2139"}, + {0x85,"LM3S2637"}, + {0x86,"LM3S8738"}, + {0x88,"LM3S8938"}, + {0x89,"LM3S6938"}, + {0x8B,"LM3S6637"}, + {0x8C,"LM3S8933"}, + {0x8D,"LM3S8733"}, + {0x8E,"LM3S8538"}, + {0x8F,"LM3S2948"}, + {0xA1,"LM3S6100"}, + {0xA2,"LM3S2410"}, + {0xA3,"LM3S6730"}, + {0xA4,"LM3S2730"}, + {0xA5,"LM3S6420"}, + {0xA6,"LM3S8962"}, + {0xB3,"LM3S1635"}, + {0xB4,"LM3S1850"}, + {0xB5,"LM3S1960"}, + {0xB7,"LM3S1937"}, + {0xB8,"LM3S1968"}, + {0xB9,"LM3S1751"}, + {0xBA,"LM3S1439"}, + {0xBB,"LM3S1512"}, + {0xBC,"LM3S1435"}, + {0xBD,"LM3S1637"}, + {0xBE,"LM3S1958"}, + {0xBF,"LM3S1110"}, + {0xC0,"LM3S1620"}, + {0xC1,"LM3S1150"}, + {0xC2,"LM3S1165"}, + {0xC3,"LM3S1133"}, + {0xC4,"LM3S1162"}, + {0xC5,"LM3S1138"}, + {0xC6,"LM3S1332"}, + {0xC7,"LM3S1538"}, + {0xD0,"LM3S6815"}, + {0xD1,"LM3S6816"}, + {0xD2,"LM3S6915"}, + {0xD3,"LM3S6916"}, + {0xD4,"LM3S2016"}, + {0xD5,"LM3S1615"}, + {0xD6,"LM3S1616"}, + {0xD7,"LM3S8971"}, + {0xD8,"LM3S1108"}, + {0xD9,"LM3S1101"}, + {0xDA,"LM3S1608"}, + {0xDB,"LM3S1601"}, + {0xDC,"LM3S1918"}, + {0xDD,"LM3S1911"}, + {0xDE,"LM3S2108"}, + {0xDF,"LM3S2101"}, + {0xE0,"LM3S2608"}, + {0xE1,"LM3S2601"}, + {0xE2,"LM3S2918"}, + {0xE3,"LM3S2911"}, + {0xE4,"LM3S6118"}, + {0xE5,"LM3S6111"}, + {0xE6,"LM3S6618"}, + {0xE7,"LM3S6611"}, + {0xE8,"LM3S6918"}, + {0xE9,"LM3S6911"}, {0,"Unknown part"} }; +char * StellarisClassname[2] = +{ + "Sandstorm", + "Fury" +}; + /*************************************************************************** * openocd command interface * ***************************************************************************/ +/* flash_bank stellaris 0 0 + */ int stellaris_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, char **args, int argc, struct flash_bank_s *bank) { stellaris_flash_bank_t *stellaris_info; @@ -117,13 +230,7 @@ int stellaris_flash_bank_command(struct command_context_s *cmd_ctx, char *cmd, c bank->base = 0x0; bank->driver_priv = stellaris_info; - stellaris_info->target_name ="Unknown target"; - stellaris_info->target = get_target_by_num(strtoul(args[5], NULL, 0)); - if (!stellaris_info->target) - { - ERROR("no target '%i' configured", args[5]); - exit(-1); - } + stellaris_info->target_name = "Unknown target"; /* part wasn't probed for info yet */ stellaris_info->did1 = 0; @@ -144,7 +251,7 @@ int stellaris_register_commands(struct command_context_s *cmd_ctx) int stellaris_info(struct flash_bank_s *bank, char *buf, int buf_size) { - int printed; + int printed, device_class; stellaris_flash_bank_t *stellaris_info = bank->driver_priv; stellaris_read_part_info(bank); @@ -157,7 +264,17 @@ int stellaris_info(struct flash_bank_s *bank, char *buf, int buf_size) return ERROR_FLASH_OPERATION_FAILED; } - printed = snprintf(buf, buf_size, "\nLMI Stellaris information: Chip is %s v%i.%02i\n",stellaris_info->target_name, (stellaris_info->did0>>8)&0xFF, (stellaris_info->did0)&0xFF); + if (DID0_VER(stellaris_info->did0)>0) + { + device_class = (stellaris_info->did0>>16)&0xFF; + } + else + { + device_class = 0; + } + printed = snprintf(buf, buf_size, "\nLMI Stellaris information: Chip is class %i(%s) %s v%c.%i\n", + device_class, StellarisClassname[device_class], stellaris_info->target_name, + 'A' + (stellaris_info->did0>>8)&0xFF, (stellaris_info->did0)&0xFF); buf += printed; buf_size -= printed; @@ -184,8 +301,7 @@ int stellaris_info(struct flash_bank_s *bank, char *buf, int buf_size) u32 stellaris_get_flash_status(flash_bank_t *bank) { - stellaris_flash_bank_t *stellaris_info = bank->driver_priv; - target_t *target = stellaris_info->target; + target_t *target = bank->target; u32 fmc; target_read_u32(target, FLASH_CONTROL_BASE|FLASH_FMC, &fmc); @@ -198,9 +314,9 @@ u32 stellaris_get_flash_status(flash_bank_t *bank) void stellaris_read_clock_info(flash_bank_t *bank) { stellaris_flash_bank_t *stellaris_info = bank->driver_priv; - target_t *target = stellaris_info->target; + target_t *target = bank->target; u32 rcc, pllcfg, sysdiv, usesysdiv, bypass, oscsrc; - unsigned long tmp, mainfreq; + unsigned long mainfreq; target_read_u32(target, SCB_BASE|RCC, &rcc); DEBUG("Stellaris RCC %x",rcc); @@ -246,7 +362,7 @@ void stellaris_read_clock_info(flash_bank_t *bank) void stellaris_set_flash_mode(flash_bank_t *bank,int mode) { stellaris_flash_bank_t *stellaris_info = bank->driver_priv; - target_t *target = stellaris_info->target; + target_t *target = bank->target; u32 usecrl = (stellaris_info->mck_freq/1000000ul-1); DEBUG("usecrl = %i",usecrl); @@ -275,8 +391,7 @@ u32 stellaris_wait_status_busy(flash_bank_t *bank, u32 waitbits, int timeout) int stellaris_flash_command(struct flash_bank_s *bank,u8 cmd,u16 pagen) { u32 fmc; - stellaris_flash_bank_t *stellaris_info = bank->driver_priv; - target_t *target = stellaris_info->target; + target_t *target = bank->target; fmc = FMC_WRKEY | cmd; target_write_u32(target, FLASH_CONTROL_BASE|FLASH_FMC, fmc); @@ -294,8 +409,8 @@ int stellaris_flash_command(struct flash_bank_s *bank,u8 cmd,u16 pagen) int stellaris_read_part_info(struct flash_bank_s *bank) { stellaris_flash_bank_t *stellaris_info = bank->driver_priv; - target_t *target = stellaris_info->target; - u32 did0,did1, status; + target_t *target = bank->target; + u32 did0,did1, ver, fam, status; int i; /* Read and parse chip identification register */ @@ -305,16 +420,11 @@ int stellaris_read_part_info(struct flash_bank_s *bank) target_read_u32(target, SCB_BASE|DC1, &stellaris_info->dc1); DEBUG("did0 0x%x, did1 0x%x, dc0 0x%x, dc1 0x%x",did0, did1, stellaris_info->dc0,stellaris_info->dc1); - if (((did0>>27)&0x7)) - { - WARNING("Unkown did0 version, cannot identify target"); - return ERROR_FLASH_OPERATION_FAILED; - - } - - if (did1>>24) + ver = did0 >> 28; + if((ver != 0) && (ver != 1)) { - WARNING("Unkown did1 version/family, cannot positively identify target as a Stellaris"); + WARNING("Unknown did0 version, cannot identify target"); + return ERROR_FLASH_OPERATION_FAILED; } if (did1 == 0) @@ -322,7 +432,14 @@ int stellaris_read_part_info(struct flash_bank_s *bank) WARNING("Cannot identify target as a Stellaris"); return ERROR_FLASH_OPERATION_FAILED; } - + + ver = did1 >> 28; + fam = (did1 >> 24) & 0xF; + if(((ver != 0) && (ver != 1)) || (fam != 0)) + { + WARNING("Unknown did1 version/family, cannot positively identify target as a Stellaris"); + } + for (i=0;StellarisParts[i].partno;i++) { if (StellarisParts[i].partno==((did1>>16)&0xFF)) @@ -333,7 +450,7 @@ int stellaris_read_part_info(struct flash_bank_s *bank) stellaris_info->did0 = did0; stellaris_info->did1 = did1; - + stellaris_info->num_lockbits = 1+stellaris_info->dc0&0xFFFF; stellaris_info->num_pages = 2*(1+stellaris_info->dc0&0xFFFF); stellaris_info->pagesize = 1024; @@ -341,13 +458,11 @@ int stellaris_read_part_info(struct flash_bank_s *bank) stellaris_info->pages_in_lockregion = 2; target_read_u32(target, SCB_BASE|FMPPE, &stellaris_info->lockbits); - // Read main and master clock freqency register + /* Read main and master clock freqency register */ stellaris_read_clock_info(bank); status = stellaris_get_flash_status(bank); - WARNING("stellaris flash only tested for LM3S811 series"); - return ERROR_OK; } @@ -357,11 +472,13 @@ int stellaris_read_part_info(struct flash_bank_s *bank) int stellaris_erase_check(struct flash_bank_s *bank) { + /* + stellaris_flash_bank_t *stellaris_info = bank->driver_priv; - target_t *target = stellaris_info->target; + target_t *target = bank->target; int i; - /* */ + */ return ERROR_OK; } @@ -371,7 +488,11 @@ int stellaris_protect_check(struct flash_bank_s *bank) u32 status; stellaris_flash_bank_t *stellaris_info = bank->driver_priv; - target_t *target = stellaris_info->target; + + if (bank->target->state != TARGET_HALTED) + { + return ERROR_TARGET_NOT_HALTED; + } if (stellaris_info->did1 == 0) { @@ -395,13 +516,13 @@ int stellaris_erase(struct flash_bank_s *bank, int first, int last) int banknr; u32 flash_fmc, flash_cris; stellaris_flash_bank_t *stellaris_info = bank->driver_priv; - target_t *target = stellaris_info->target; + target_t *target = bank->target; - if (stellaris_info->target->state != TARGET_HALTED) + if (bank->target->state != TARGET_HALTED) { return ERROR_TARGET_NOT_HALTED; } - + if (stellaris_info->did1 == 0) { stellaris_read_part_info(bank); @@ -409,7 +530,7 @@ int stellaris_erase(struct flash_bank_s *bank, int first, int last) if (stellaris_info->did1 == 0) { - WARNING("Cannot identify target as an AT91SAM"); + WARNING("Cannot identify target as Stellaris"); return ERROR_FLASH_OPERATION_FAILED; } @@ -428,6 +549,7 @@ int stellaris_erase(struct flash_bank_s *bank, int first, int last) if ((first == 0) && (last == (stellaris_info->num_pages-1))) { + target_write_u32(target, FLASH_FMA, 0); target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE); /* Wait until erase complete */ do @@ -436,6 +558,19 @@ int stellaris_erase(struct flash_bank_s *bank, int first, int last) } while(flash_fmc & FMC_MERASE); + /* if device has > 128k, then second erase cycle is needed */ + if(stellaris_info->num_pages * stellaris_info->pagesize > 0x20000) + { + target_write_u32(target, FLASH_FMA, 0x20000); + target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_MERASE); + /* Wait until erase complete */ + do + { + target_read_u32(target, FLASH_FMC, &flash_fmc); + } + while(flash_fmc & FMC_MERASE); + } + return ERROR_OK; } @@ -467,13 +602,13 @@ int stellaris_erase(struct flash_bank_s *bank, int first, int last) int stellaris_protect(struct flash_bank_s *bank, int set, int first, int last) { - u32 cmd, fmppe, flash_fmc, flash_cris; + u32 fmppe, flash_fmc, flash_cris; int lockregion; stellaris_flash_bank_t *stellaris_info = bank->driver_priv; - target_t *target = stellaris_info->target; + target_t *target = bank->target; - if (stellaris_info->target->state != TARGET_HALTED) + if (bank->target->state != TARGET_HALTED) { return ERROR_TARGET_NOT_HALTED; } @@ -542,15 +677,18 @@ int stellaris_protect(struct flash_bank_s *bank, int set, int first, int last) u8 stellaris_write_code[] = { -/* Call with : +/* + Call with : r0 = buffer address r1 = destination address r2 = bytecount (in) - endaddr (work) + + Used registers: r3 = pFLASH_CTRL_BASE r4 = FLASHWRITECMD r5 = #1 - r6 = scratch - r7 + r6 = bytes written + r7 = temp reg */ 0x07,0x4B, /* ldr r3,pFLASH_CTRL_BASE */ 0x08,0x4C, /* ldr r4,FLASHWRITECMD */ @@ -578,8 +716,7 @@ u8 stellaris_write_code[] = int stellaris_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 wcount) { - stellaris_flash_bank_t *stellaris_info = bank->driver_priv; - target_t *target = stellaris_info->target; + target_t *target = bank->target; u32 buffer_size = 8192; working_area_t *source; working_area_t *write_algorithm; @@ -588,6 +725,8 @@ int stellaris_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 armv7m_algorithm_t armv7m_info; int retval; + DEBUG("(bank=%08X buffer=%08X offset=%08X wcount=%08X)", + (unsigned int)bank, (unsigned int)buffer, offset, wcount); /* flash write code */ if (target_alloc_working_area(target, sizeof(stellaris_write_code), &write_algorithm) != ERROR_OK) @@ -601,6 +740,8 @@ int stellaris_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 /* memory buffer */ while (target_alloc_working_area(target, buffer_size, &source) != ERROR_OK) { + DEBUG("called target_alloc_working_area(target=%08X buffer_size=%08X source=%08X)", + (unsigned int)target, buffer_size, (unsigned int)source); buffer_size /= 2; if (buffer_size <= 256) { @@ -671,17 +812,19 @@ int stellaris_write_block(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 int stellaris_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count) { stellaris_flash_bank_t *stellaris_info = bank->driver_priv; - target_t *target = stellaris_info->target; - u32 dst_min_alignment, wcount, bytes_remaining = count; + target_t *target = bank->target; u32 address = offset; - u32 fcr,flash_cris,flash_fmc; + u32 flash_cris,flash_fmc; u32 retval; - if (stellaris_info->target->state != TARGET_HALTED) + if (bank->target->state != TARGET_HALTED) { return ERROR_TARGET_NOT_HALTED; } - + + DEBUG("(bank=%08X buffer=%08X offset=%08X count=%08X)", + (unsigned int)bank, (unsigned int)buffer, offset, count); + if (stellaris_info->did1 == 0) { stellaris_read_part_info(bank); @@ -749,7 +892,7 @@ int stellaris_write(struct flash_bank_s *bank, u8 *buffer, u32 offset, u32 count target_write_u32(target, FLASH_FMA, address); target_write_buffer(target, FLASH_FMD, 4, buffer); target_write_u32(target, FLASH_FMC, FMC_WRKEY | FMC_WRITE); - //DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); + /* DEBUG("0x%x 0x%x 0x%x",address,buf_get_u32(buffer, 0, 32),FMC_WRKEY | FMC_WRITE); */ /* Wait until write complete */ do { @@ -776,18 +919,20 @@ int stellaris_probe(struct flash_bank_s *bank) /* we can't probe on an stellaris * if this is an stellaris, it has the configured flash */ - stellaris_flash_bank_t *stellaris_info = bank->driver_priv; - if (stellaris_info->did1 == 0) + if (bank->target->state != TARGET_HALTED) { - stellaris_read_part_info(bank); + return ERROR_TARGET_NOT_HALTED; } - if (stellaris_info->did1 == 0) - { - WARNING("Cannot identify target as a LMI Stellaris"); - return ERROR_FLASH_OPERATION_FAILED; - } - - return ERROR_OK; + /* stellaris_read_part_info() already takes care about error checking and reporting */ + return stellaris_read_part_info(bank); +} + +int stellaris_auto_probe(struct flash_bank_s *bank) +{ + stellaris_flash_bank_t *stellaris_info = bank->driver_priv; + if (stellaris_info->did1) + return ERROR_OK; + return stellaris_probe(bank); }