[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