X-Git-Url: https://review.openocd.org/gitweb?a=blobdiff_plain;f=src%2Fflash%2Fnor%2Flpc2000.c;h=b639d1ef55f695888ff585061be352bcc9a104a8;hb=e74a081a1a1748ad2db95236646d6107e4d61b51;hp=2b1e67177ebe755e9a9188d754984884b0236ef1;hpb=31e3ea7c19d39589ac9a8b2220331206b6d1e25c;p=openocd.git diff --git a/src/flash/nor/lpc2000.c b/src/flash/nor/lpc2000.c index 2b1e67177e..b639d1ef55 100644 --- a/src/flash/nor/lpc2000.c +++ b/src/flash/nor/lpc2000.c @@ -26,13 +26,20 @@ #endif #include "imp.h" -#include "lpc2000.h" #include #include +#include #include - -/* flash programming support for NXP LPC17xx and LPC2xxx devices +/** + * @file + * flash programming support for NXP LPC17xx and LPC2xxx devices. + * + * @todo Provide a way to update CCLK after declaring the flash bank. + * The value which is correct after chip reset will rarely still work + * right after the clocks switch to use the PLL (e.g. 4MHz --> 100 MHz). + */ +/* * currently supported devices: * variant 1 (lpc2000_v1): * - 2104 | 5 | 6 @@ -54,6 +61,50 @@ * - 176x (tested with LPC1768) */ +typedef enum +{ + lpc2000_v1, + lpc2000_v2, + lpc1700 +} lpc2000_variant; + +struct lpc2000_flash_bank +{ + lpc2000_variant variant; + struct working_area *iap_working_area; + uint32_t cclk; + int cmd51_dst_boundary; + int cmd51_can_256b; + int cmd51_can_8192b; + int calc_checksum; + uint32_t cmd51_max_buffer; + int checksum_vector; +}; + +enum lpc2000_status_codes +{ + LPC2000_CMD_SUCCESS = 0, + LPC2000_INVALID_COMMAND = 1, + LPC2000_SRC_ADDR_ERROR = 2, + LPC2000_DST_ADDR_ERROR = 3, + LPC2000_SRC_ADDR_NOT_MAPPED = 4, + LPC2000_DST_ADDR_NOT_MAPPED = 5, + LPC2000_COUNT_ERROR = 6, + LPC2000_INVALID_SECTOR = 7, + LPC2000_SECTOR_NOT_BLANK = 8, + LPC2000_SECTOR_NOT_PREPARED = 9, + LPC2000_COMPARE_ERROR = 10, + LPC2000_BUSY = 11, + LPC2000_PARAM_ERROR = 12, + LPC2000_ADDR_ERROR = 13, + LPC2000_ADDR_NOT_MAPPED = 14, + LPC2000_CMD_NOT_LOCKED = 15, + LPC2000_INVALID_CODE = 16, + LPC2000_INVALID_BAUD_RATE = 17, + LPC2000_INVALID_STOP_BIT = 18, + LPC2000_CRP_ENABLED = 19 +}; + static int lpc2000_build_sector_list(struct flash_bank *bank) { struct lpc2000_flash_bank *lpc2000_info = bank->driver_priv; @@ -143,10 +194,13 @@ static int lpc2000_build_sector_list(struct flash_bank *bank) case 256 * 1024: bank->num_sectors = 15; break; - case 512 * 1024: case 500 * 1024: bank->num_sectors = 27; break; + case 512 * 1024: + case 504 * 1024: + bank->num_sectors = 28; + break; default: LOG_ERROR("BUG: unknown bank->size encountered"); exit(-1); @@ -157,7 +211,7 @@ static int lpc2000_build_sector_list(struct flash_bank *bank) for (i = 0; i < bank->num_sectors; i++) { - if ((i >= 0) && (i < 8)) + if (i < 8) { bank->sectors[i].offset = offset; bank->sectors[i].size = 4 * 1024; @@ -165,7 +219,7 @@ static int lpc2000_build_sector_list(struct flash_bank *bank) bank->sectors[i].is_erased = -1; bank->sectors[i].is_protected = 1; } - if ((i >= 8) && (i < 22)) + else if (i < 22) { bank->sectors[i].offset = offset; bank->sectors[i].size = 32 * 1024; @@ -173,7 +227,7 @@ static int lpc2000_build_sector_list(struct flash_bank *bank) bank->sectors[i].is_erased = -1; bank->sectors[i].is_protected = 1; } - if ((i >= 22) && (i < 27)) + else if (i < 28) { bank->sectors[i].offset = offset; bank->sectors[i].size = 4 * 1024; @@ -242,7 +296,7 @@ static int lpc2000_iap_call(struct flash_bank *bank, int code, uint32_t param_ta struct target *target = bank->target; struct mem_param mem_params[2]; struct reg_param reg_params[5]; - struct armv4_5_algorithm armv4_5_info; /* for LPC2000 */ + struct arm_algorithm armv4_5_info; /* for LPC2000 */ struct armv7m_algorithm armv7m_info; /* for LPC1700 */ uint32_t status_code; uint32_t iap_entry_point = 0; /* to make compiler happier */ @@ -263,8 +317,10 @@ static int lpc2000_iap_call(struct flash_bank *bank, int code, uint32_t param_ta switch(lpc2000_info->variant) { case lpc1700: - target_buffer_set_u32(target, jump_gate, ARMV7M_T_BX(12)); - target_buffer_set_u32(target, jump_gate + 4, ARMV7M_T_B(0xfffffe)); + target_buffer_set_u32(target, jump_gate, + ARMV4_5_T_BX(12)); + target_buffer_set_u32(target, jump_gate + 4, + ARMV5_T_BKPT(0)); break; case lpc2000_v1: case lpc2000_v2: @@ -272,7 +328,7 @@ static int lpc2000_iap_call(struct flash_bank *bank, int code, uint32_t param_ta target_buffer_set_u32(target, jump_gate + 4, ARMV4_5_B(0xfffffe, 0)); break; default: - LOG_ERROR("BUG: unknown bank->size encountered"); + LOG_ERROR("BUG: unknown lpc2000_info->variant encountered"); exit(-1); } @@ -292,8 +348,8 @@ static int lpc2000_iap_call(struct flash_bank *bank, int code, uint32_t param_ta break; case lpc2000_v1: case lpc2000_v2: - armv4_5_info.common_magic = ARMV4_5_COMMON_MAGIC; - armv4_5_info.core_mode = ARMV4_5_MODE_SVC; + armv4_5_info.common_magic = ARM_COMMON_MAGIC; + armv4_5_info.core_mode = ARM_MODE_SVC; armv4_5_info.core_state = ARM_STATE_ARM; iap_entry_point = 0x7ffffff1; break; @@ -335,12 +391,12 @@ static int lpc2000_iap_call(struct flash_bank *bank, int code, uint32_t param_ta init_reg_param(®_params[4], "lr", 32, PARAM_OUT); buf_set_u32(reg_params[4].value, 0, 32, (lpc2000_info->iap_working_area->address + 0x04) | 1); /* bit0 of LR = 1 to return in Thumb mode */ - target_run_algorithm(target, 2, mem_params, 5, reg_params, lpc2000_info->iap_working_area->address, lpc2000_info->iap_working_area->address + 0x4, 10000, &armv7m_info); + target_run_algorithm(target, 2, mem_params, 5, reg_params, lpc2000_info->iap_working_area->address, 0, 10000, &armv7m_info); break; case lpc2000_v1: case lpc2000_v2: /* IAP stack */ - init_reg_param(®_params[3], "r13_svc", 32, PARAM_OUT); + init_reg_param(®_params[3], "sp_svc", 32, PARAM_OUT); buf_set_u32(reg_params[3].value, 0, 32, lpc2000_info->iap_working_area->address + 0xb4); /* return address */ @@ -354,7 +410,6 @@ static int lpc2000_iap_call(struct flash_bank *bank, int code, uint32_t param_ta exit(-1); } - status_code = target_buffer_get_u32(target, mem_params[1].value); result_table[0] = target_buffer_get_u32(target, mem_params[1].value + 0x04); result_table[1] = target_buffer_get_u32(target, mem_params[1].value + 0x08); @@ -583,7 +638,6 @@ static int lpc2000_write(struct flash_bank *bank, uint8_t *buffer, uint32_t offs if ((offset == 0) && (count >= 0x20) && lpc2000_info->calc_checksum) { uint32_t checksum = 0; - int i; for (i = 0; i < 8; i++) { LOG_DEBUG("Vector 0x%2.2x: 0x%8.8" PRIx32, i * 4, buf_get_u32(buffer + (i * 4), 0, 32)); @@ -729,7 +783,7 @@ static int lpc2000_protect_check(struct flash_bank *bank) return ERROR_OK; } -static int lpc2000_info(struct flash_bank *bank, char *buf, int buf_size) +static int get_lpc2000_info(struct flash_bank *bank, char *buf, int buf_size) { struct lpc2000_flash_bank *lpc2000_info = bank->driver_priv; @@ -780,7 +834,7 @@ COMMAND_HANDLER(lpc2000_handle_part_id_command) static const struct command_registration lpc2000_exec_command_handlers[] = { { .name = "part_id", - .handler = &lpc2000_handle_part_id_command, + .handler = lpc2000_handle_part_id_command, .mode = COMMAND_EXEC, .help = "print part id of lpc2000 flash bank ", }, @@ -797,17 +851,16 @@ static const struct command_registration lpc2000_command_handlers[] = { }; struct flash_driver lpc2000_flash = { - .name = "lpc2000", - .commands = lpc2000_command_handlers, - .flash_bank_command = &lpc2000_flash_bank_command, - .erase = &lpc2000_erase, - .protect = &lpc2000_protect, - .write = &lpc2000_write, - .probe = &lpc2000_probe, - .auto_probe = &lpc2000_probe, - .erase_check = &lpc2000_erase_check, - .protect_check = &lpc2000_protect_check, - .info = &lpc2000_info, - }; - - + .name = "lpc2000", + .commands = lpc2000_command_handlers, + .flash_bank_command = lpc2000_flash_bank_command, + .erase = lpc2000_erase, + .protect = lpc2000_protect, + .write = lpc2000_write, + .read = default_flash_read, + .probe = lpc2000_probe, + .auto_probe = lpc2000_probe, + .erase_check = lpc2000_erase_check, + .protect_check = lpc2000_protect_check, + .info = get_lpc2000_info, +};