[prev in list] [next in list] [prev in thread] [next in thread]
List: openocd-development
Subject: [OpenOCD-devel] [PATCH]: 9ba9956 Flash/LPC2000: Add support for LPC11XX, LPC13XX parts, with auto-pr
From: gerrit () openocd ! zylin ! com
Date: 2014-03-29 19:32:40
Message-ID: 20140329193241.3C9D5242D2 () openocd ! zylin ! com
[Download RAW message or body]
This is an automated email from Gerrit.
Cosmin Gorgovan (cosmin@linux-geek.org) just uploaded a new patch set to Gerrit, \
which you can find at http://openocd.zylin.com/2071
-- gerrit
commit 9ba9956395a49f686d1dfa86be8afe96cea26c97
Author: Cosmin Gorgovan <cosmin@linux-geek.org>
Date: Sat Mar 29 19:20:08 2014 +0000
Flash/LPC2000: Add support for LPC11XX, LPC13XX parts, with auto-probing
LPC1100 and LPC1300 devices are mostly compatible with the lpc1700 variant
of the LPC2000 driver, but use a fixed flash sector size of 4KB.
Auto-probing has been implemented using the IAP 'Read Part ID' command.
The IDs for all LPC13XX and LPC11UXX devices have been added.
Auto-probing is only enabled if the flash bank size in the flash bank
is 0, otherwise the size passed to the flash bank command is used.
Change-Id: I033515f4ff6bc61d3b9babd27096f78c99cea927
Signed-off-by: Cosmin Gorgovan <cosmin@linux-geek.org>
diff --git a/src/flash/nor/lpc2000.c b/src/flash/nor/lpc2000.c
index 69c8b03..64a52fc 100644
--- a/src/flash/nor/lpc2000.c
+++ b/src/flash/nor/lpc2000.c
@@ -67,12 +67,44 @@
* - 810 | 1 | 2 (tested with LPC810/LPC812)
*/
+#define LPC11U12_201_1 0x095C802B
+#define LPC11U12_201_2 0x295C802B
+#define LPC11U13_201_1 0x097A802B
+#define LPC11U13_201_2 0x297A802B
+#define LPC11U14_201_1 0x0998802B
+#define LPC11U14_201_2 0x2998802B
+#define LPC11U23_301 0x2972402B
+#define LPC11U24_301 0x2988402B
+#define LPC11U24_401 0x2980002B
+#define LPC11U34_311 0x0003D440
+#define LPC11U34_421 0x0001CC40
+#define LPC11U35_401 0x0001BC40
+#define LPC11U35_501 0x0000BC40
+#define LPC11U36_401 0x00019C40
+#define LPC11U37_401 0x00017C40
+#define LPC11U37H_401 0x00007C44
+#define LPC11U37_501 0x00007C40
+
+#define LPC1311 0x2C42502B
+#define LPC1311_1 0x1816902B
+#define LPC1313 0x2C40102B
+#define LPC1313_1 0x1830102B
+#define LPC1315 0x3A010523
+#define LPC1316 0x1A018524
+#define LPC1317 0x1A020525
+#define LPC1342 0x3D01402B
+#define LPC1343 0x3D00002B
+#define LPC1345 0x28010541
+#define LPC1346 0x08018542
+#define LPC1347 0x08020543
+
typedef enum {
lpc2000_v1,
lpc2000_v2,
lpc1700,
lpc4300,
lpc800,
+ lpc1100,
} lpc2000_variant;
struct lpc2000_flash_bank {
@@ -88,6 +120,7 @@ struct lpc2000_flash_bank {
uint32_t iap_max_stack;
uint32_t cmd51_src_offset;
uint32_t lpc4300_bank;
+ bool probed;
};
enum lpc2000_status_codes {
@@ -329,6 +362,25 @@ static int lpc2000_build_sector_list(struct flash_bank *bank)
bank->sectors[i].is_protected = 1;
}
+ } else if (lpc2000_info->variant == lpc1100) {
+ if ((bank->size % (4 * 1024)) != 0) {
+ LOG_ERROR("BUG: unknown bank->size encountered,\nLPC1100 flash size must be a \
multiple of 4096"); + exit(-1);
+ }
+ lpc2000_info->cmd51_max_buffer = 1024;
+ bank->num_sectors = bank->size / 4096;
+
+ bank->sectors = malloc(sizeof(struct flash_sector) * bank->num_sectors);
+
+ for (int i = 0; i < bank->num_sectors; i++) {
+ bank->sectors[i].offset = offset;
+ /* all sectors are 4kB-sized */
+ bank->sectors[i].size = 4 * 1024;
+ offset += bank->sectors[i].size;
+ bank->sectors[i].is_erased = -1;
+ bank->sectors[i].is_protected = 1;
+ }
+
} else {
LOG_ERROR("BUG: unknown lpc2000_info->variant encountered");
exit(-1);
@@ -360,6 +412,7 @@ static int lpc2000_iap_working_area_init(struct flash_bank *bank, \
struct working /* write IAP code to working area */
switch (lpc2000_info->variant) {
case lpc800:
+ case lpc1100:
case lpc1700:
case lpc4300:
target_buffer_set_u32(target, jump_gate, ARMV4_5_T_BX(12));
@@ -397,6 +450,7 @@ static int lpc2000_iap_call(struct flash_bank *bank, struct \
working_area *iap_wo
switch (lpc2000_info->variant) {
case lpc800:
+ case lpc1100:
case lpc1700:
armv7m_info.common_magic = ARMV7M_COMMON_MAGIC;
armv7m_info.core_mode = ARM_MODE_THREAD;
@@ -448,6 +502,7 @@ static int lpc2000_iap_call(struct flash_bank *bank, struct \
working_area *iap_wo
switch (lpc2000_info->variant) {
case lpc800:
+ case lpc1100:
case lpc1700:
case lpc4300:
/* IAP stack */
@@ -562,6 +617,7 @@ FLASH_BANK_COMMAND_HANDLER(lpc2000_flash_bank_command)
return ERROR_COMMAND_SYNTAX_ERROR;
struct lpc2000_flash_bank *lpc2000_info = calloc(1, sizeof(*lpc2000_info));
+ lpc2000_info->probed = false;
bank->driver_priv = lpc2000_info;
@@ -601,6 +657,13 @@ FLASH_BANK_COMMAND_HANDLER(lpc2000_flash_bank_command)
lpc2000_info->cmd51_can_8192b = 0;
lpc2000_info->checksum_vector = 7;
lpc2000_info->iap_max_stack = 148;
+ } else if (strcmp(CMD_ARGV[6], "lpc1100") == 0) {
+ lpc2000_info->variant = lpc1100;
+ lpc2000_info->cmd51_dst_boundary = 256;
+ lpc2000_info->cmd51_can_256b = 1;
+ lpc2000_info->cmd51_can_8192b = 0;
+ lpc2000_info->checksum_vector = 7;
+ lpc2000_info->iap_max_stack = 128;
} else {
LOG_ERROR("unknown LPC2000 variant: %s", CMD_ARGV[6]);
free(lpc2000_info);
@@ -612,7 +675,6 @@ FLASH_BANK_COMMAND_HANDLER(lpc2000_flash_bank_command)
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[7], lpc2000_info->cclk);
lpc2000_info->calc_checksum = 0;
- lpc2000_build_sector_list(bank);
uint32_t temp_base = 0;
COMMAND_PARSE_NUMBER(u32, CMD_ARGV[1], temp_base);
@@ -890,9 +952,119 @@ static int lpc2000_write(struct flash_bank *bank, const uint8_t \
*buffer, uint32_ return retval;
}
+static int get_lpc2000_part_id(struct flash_bank *bank, uint32_t *part_id)
+{
+ if (bank->target->state != TARGET_HALTED) {
+ LOG_ERROR("Target not halted");
+ return ERROR_TARGET_NOT_HALTED;
+ }
+
+ uint32_t param_table[5] = {0};
+ uint32_t result_table[4];
+ struct working_area *iap_working_area;
+
+ int retval = lpc2000_iap_working_area_init(bank, &iap_working_area);
+
+ if (retval != ERROR_OK)
+ return retval;
+
+ int status_code = lpc2000_iap_call(bank, iap_working_area, 54, param_table, \
result_table); +
+ if (status_code == LPC2000_CMD_SUCCESS)
+ *part_id = result_table[0];
+
+ return status_code;
+}
+
+static int lpc2000_auto_probe_flash(struct flash_bank *bank)
+{
+ uint32_t part_id;
+ int retval;
+
+ if (bank->target->state != TARGET_HALTED) {
+ LOG_ERROR("Target not halted");
+ return ERROR_TARGET_NOT_HALTED;
+ }
+
+ retval = get_lpc2000_part_id(bank, &part_id);
+ if (retval != LPC2000_CMD_SUCCESS) {
+ LOG_ERROR("Could not get part ID");
+ return retval;
+ }
+
+ switch (part_id) {
+ case LPC1311:
+ case LPC1311_1:
+ bank->size = 8 * 1024;
+ break;
+
+ case LPC11U12_201_1:
+ case LPC11U12_201_2:
+ case LPC1342:
+ bank->size = 16 * 1024;
+ break;
+
+ case LPC11U13_201_1:
+ case LPC11U13_201_2:
+ case LPC11U23_301:
+ bank->size = 24 * 1024;
+ break;
+
+ case LPC11U14_201_1:
+ case LPC11U14_201_2:
+ case LPC11U24_301:
+ case LPC11U24_401:
+ case LPC1313:
+ case LPC1313_1:
+ case LPC1315:
+ case LPC1343:
+ case LPC1345:
+ bank->size = 32 * 1024;
+ break;
+
+ case LPC11U34_311:
+ bank->size = 40 * 1024;
+ break;
+
+ case LPC11U34_421:
+ case LPC1316:
+ case LPC1346:
+ bank->size = 48 * 1024;
+ break;
+
+ case LPC11U35_401:
+ case LPC11U35_501:
+ case LPC1317:
+ case LPC1347:
+ bank->size = 64 * 1024;
+ break;
+
+ case LPC11U36_401:
+ bank->size = 96 * 1024;
+ break;
+
+ case LPC11U37_401:
+ case LPC11U37H_401:
+ case LPC11U37_501:
+ bank->size = 128 * 1024;
+ break;
+ }
+
+ return ERROR_OK;
+}
+
static int lpc2000_probe(struct flash_bank *bank)
{
- /* we can't probe on an lpc2000 if this is an lpc2xxx, it has the configured flash \
*/ + struct lpc2000_flash_bank *lpc2000_info = bank->driver_priv;
+
+ if (!lpc2000_info->probed) {
+ if (bank->size == 0)
+ lpc2000_auto_probe_flash(bank);
+
+ lpc2000_build_sector_list(bank);
+ lpc2000_info->probed = true;
+ }
+
return ERROR_OK;
}
@@ -937,23 +1109,15 @@ COMMAND_HANDLER(lpc2000_handle_part_id_command)
return ERROR_TARGET_NOT_HALTED;
}
- uint32_t param_table[5] = {0};
- uint32_t result_table[4];
- struct working_area *iap_working_area;
-
- retval = lpc2000_iap_working_area_init(bank, &iap_working_area);
-
- if (retval != ERROR_OK)
- return retval;
-
- int status_code = lpc2000_iap_call(bank, iap_working_area, 54, param_table, \
result_table); + uint32_t part_id;
+ int status_code = get_lpc2000_part_id(bank, &part_id);
if (status_code != 0x0) {
if (status_code == ERROR_FLASH_OPERATION_FAILED) {
command_print(CMD_CTX, "no sufficient working area specified, can't access \
LPC2000 IAP interface"); } else
command_print(CMD_CTX, "lpc2000 IAP returned status code %i", status_code);
} else
- command_print(CMD_CTX, "lpc2000 part id: 0x%8.8" PRIx32, result_table[0]);
+ command_print(CMD_CTX, "lpc2000 part id: 0x%8.8" PRIx32, part_id);
return retval;
}
diff --git a/tcl/target/lpc1xxx.cfg b/tcl/target/lpc1xxx.cfg
index 304504c..42d5707 100644
--- a/tcl/target/lpc1xxx.cfg
+++ b/tcl/target/lpc1xxx.cfg
@@ -99,17 +99,23 @@ $_TARGETNAME configure -work-area-phys 0x10000000 -work-area-size \
$_CPURAMSIZE # The LPC11xx devies have 8/16/24/32/48/56/64kB of flash memory (at \
0x00000000) # The LPC12xx devies have 32/48/64/80/96/128kB of flash memory (at \
0x00000000) # The LPC11Uxx devies have 16/24/32/40/48/64/96/128kB of flash memory \
(at 0x00000000)
-# The LPC13xx devies have 8/16/32kB of flash memory (at 0x00000000)
+# The LPC13xx devies have 8/16/32/48/64kB of flash memory (at 0x00000000)
# The LPC17xx devies have 32/64/128/256/512kB of flash memory (at 0x00000000)
#
-# All are compatible with the "lpc1700" variant of the LPC2000 flash driver
-# (same cmd51 destination boundary alignment, and all three support 256 byte
-# transfers).
+# All would be compatible with the "lpc1700" variant of the LPC2000 flash driver
+# (same cmd51 destination boundary alignment, and all three support 256 byte \
transfers), +# but have a fixed sector size of 4kB, as opposed to the LPC1700 parts \
which have a mix +# of 4 kB and 32 kB sectors. A new type called lpc1100 has been \
created. #
# flash bank <name> lpc2000 <base> <size> 0 0 <target#> <variant> <clock> [calc \
checksum] set _FLASHNAME $_CHIPNAME.flash
+if { $_CHIPSERIES == "lpc1100" || $_CHIPSERIES == "lpc1300" } {
+ set FLASH_VARIANT "lpc1100"
+} else {
+ set FLASH_VARIANT "lpc1700"
+}
flash bank $_FLASHNAME lpc2000 0x0 $_CPUROMSIZE 0 0 $_TARGETNAME \
- lpc1700 $_CCLK calc_checksum
+ $FLASH_VARIANT $_CCLK calc_checksum
if { $_CHIPSERIES == "lpc1100" || $_CHIPSERIES == "lpc1200" || $_CHIPSERIES == \
"lpc1300" } { # Do not remap 0x0000-0x0200 to anything but the flash (i.e. select
--
------------------------------------------------------------------------------
_______________________________________________
OpenOCD-devel mailing list
OpenOCD-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/openocd-devel
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic