From d7a6f0165e7d26a82d6b8bb3797bb7cc8c6e44f3 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Wed, 27 Mar 2013 11:24:43 -0700 Subject: Accept new chip ID for stm32f4 and include flash layout for 2MiB parts. Thanks to Mike Smith. --- src/stm32f4.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src') diff --git a/src/stm32f4.c b/src/stm32f4.c index 364fef8..724e8d0 100644 --- a/src/stm32f4.c +++ b/src/stm32f4.c @@ -66,6 +66,15 @@ static const char stm32f4_xml_memory_map[] = "" " " " 0x20000" " " + " " + " 0x4000" + " " + " " + " 0x10000" + " " + " " + " 0x20000" + " " " " " " ""; @@ -157,6 +166,7 @@ bool stm32f4_probe(struct target_s *target) switch(idcode & 0xFFF) { case 0x411: /* Documented to be 0x413! This is what I read... */ case 0x413: + case 0x419: /* 427/437 */ target->driver = stm32f4_driver_str; target->xml_mem_map = stm32f4_xml_memory_map; target->flash_erase = stm32f4_flash_erase; -- cgit v1.2.3 From 3a70b81cce8f1e571b324453bc1e109010684647 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Wed, 27 Mar 2013 14:10:07 -0700 Subject: Add erase_mass command for stm32f4 devices. --- src/stm32f4.c | 48 +++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 45 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/stm32f4.c b/src/stm32f4.c index 724e8d0..09c7965 100644 --- a/src/stm32f4.c +++ b/src/stm32f4.c @@ -38,9 +38,11 @@ #include "target.h" #include "command.h" +static bool stm32f4_cmd_erase_mass(target *t); static bool stm32f4_cmd_option(target *t, int argc, char *argv[]); const struct command_s stm32f4_cmd_list[] = { + {"erase_mass", (cmd_handler)stm32f4_cmd_erase_mass, "Erase entire flash memory"}, {"option", (cmd_handler)stm32f4_cmd_option, "Manipulate option bytes"}, {NULL, NULL, NULL} }; @@ -100,6 +102,7 @@ static const char stm32f4_xml_memory_map[] = "" #define FLASH_CR_EOPIE (1 << 24) #define FLASH_CR_ERRIE (1 << 25) #define FLASH_CR_STRT (1 << 16) +#define FLASH_CR_LOCK (1 << 31) #define FLASH_SR_BSY (1 << 16) @@ -177,6 +180,14 @@ bool stm32f4_probe(struct target_s *target) return false; } +static void stm32f4_flash_unlock(ADIv5_AP_t *ap) +{ + if (adiv5_ap_mem_read(ap, FLASH_CR) & FLASH_CR_LOCK) { + /* Enable FPEC controller access */ + adiv5_ap_mem_write(ap, FLASH_KEYR, KEY1); + adiv5_ap_mem_write(ap, FLASH_KEYR, KEY2); + } +} static int stm32f4_flash_erase(struct target_s *target, uint32_t addr, int len) { @@ -187,9 +198,8 @@ static int stm32f4_flash_erase(struct target_s *target, uint32_t addr, int len) addr &= 0x07FFC000; - /* Enable FPEC controller access */ - adiv5_ap_mem_write(ap, FLASH_KEYR, KEY1); - adiv5_ap_mem_write(ap, FLASH_KEYR, KEY2); + stm32f4_flash_unlock(ap); + while(len) { if (addr < 0x10000) { /* Sector 0..3 */ cr = (addr >> 11); @@ -261,6 +271,38 @@ static int stm32f4_flash_write(struct target_s *target, uint32_t dest, return 0; } +static bool stm32f4_cmd_erase_mass(target *t) +{ + const char spinner[] = "|/-\\"; + int spinindex = 0; + + ADIv5_AP_t *ap = adiv5_target_ap(t); + + gdb_out("Erasing flash... This may take a few seconds. "); + stm32f4_flash_unlock(ap); + + /* Flash mass erase start instruction */ + adiv5_ap_mem_write(ap, FLASH_CR, FLASH_CR_MER); + adiv5_ap_mem_write(ap, FLASH_CR, FLASH_CR_STRT | FLASH_CR_MER); + + /* Read FLASH_SR to poll for BSY bit */ + while(adiv5_ap_mem_read(ap, FLASH_SR) & FLASH_SR_BSY) { + gdb_outf("\b%c", spinner[spinindex++ % 4]); + if(target_check_error(t)) { + gdb_out("\n"); + return false; + } + } + gdb_out("\n"); + + /* Check for error */ + uint16_t sr = adiv5_ap_mem_read(ap, FLASH_SR); + if ((sr & SR_ERROR_MASK) || !(sr & SR_EOP)) + return false; + + return true; +} + static bool stm32f4_option_write(target *t, uint32_t value) { ADIv5_AP_t *ap = adiv5_target_ap(t); -- cgit v1.2.3 From d4411fc51f15125cb35bda4d163673177ae0a3d2 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sun, 31 Mar 2013 12:18:11 -0700 Subject: Removed verison info from USB strings on native platform. --- src/platforms/native/platform.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/platforms/native/platform.h b/src/platforms/native/platform.h index fbd048a..a1471dc 100644 --- a/src/platforms/native/platform.h +++ b/src/platforms/native/platform.h @@ -35,8 +35,8 @@ #define INLINE_GPIO #define CDCACM_PACKET_SIZE 64 #define PLATFORM_HAS_TRACESWO -#define BOARD_IDENT "Black Magic Probe, (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" -#define BOARD_IDENT_DFU "Black Magic Probe (Upgrade), (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" +#define BOARD_IDENT "Black Magic Probe" +#define BOARD_IDENT_DFU "Black Magic Probe (Upgrade)" #define DFU_IDENT "Black Magic Firmware Upgrade" #define DFU_IFACE_STRING "@Internal Flash /0x08000000/8*001Ka,120*001Kg" -- cgit v1.2.3 From 61d464bf098c07ed395ae89d3bed6ae2fe2f2085 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Thu, 4 Apr 2013 20:16:13 -0700 Subject: dfu: Fix warnings. --- src/platforms/stm32/dfucore.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/platforms/stm32/dfucore.c b/src/platforms/stm32/dfucore.c index c1d5cfd..2786e9a 100644 --- a/src/platforms/stm32/dfucore.c +++ b/src/platforms/stm32/dfucore.c @@ -121,13 +121,19 @@ static const char *usb_strings[] = { DFU_IFACE_STRING, }; +static u32 get_le32(const void *vp) +{ + const u8 *p = vp; + return ((u32)p[3] << 24) + ((u32)p[2] << 16) + (p[1] << 8) + p[0]; +} + static u8 usbdfu_getstatus(u32 *bwPollTimeout) { switch(usbdfu_state) { case STATE_DFU_DNLOAD_SYNC: usbdfu_state = STATE_DFU_DNBUSY; *bwPollTimeout = dfu_poll_timeout(prog.buf[0], - *(u32 *)(prog.buf + 1), + get_le32(prog.buf + 1), prog.blocknum); return DFU_STATUS_OK; @@ -151,7 +157,7 @@ usbdfu_getstatus_complete(usbd_device *dev, struct usb_setup_data *req) flash_unlock(); if(prog.blocknum == 0) { - u32 addr = *(u32 *)(prog.buf + 1); + u32 addr = get_le32(prog.buf + 1); if (addr < APP_ADDRESS || (addr >= max_address)) { flash_lock(); -- cgit v1.2.3 From 58abbf7fc7686a16ee5bdfacb1241a5adf2921ea Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Thu, 4 Apr 2013 21:37:51 -0700 Subject: Revert "STM32: Use hardware CRC unit" This reverts commit 32b909067b2a34f475a52585b965c195de87c172. This CRC routine doesn't work. The bit order used by the STM32 CRC unit is reveresed from what GDB uses. --- src/crc32.c | 28 ---------------------------- 1 file changed, 28 deletions(-) (limited to 'src') diff --git a/src/crc32.c b/src/crc32.c index d5c8732..25cd53b 100644 --- a/src/crc32.c +++ b/src/crc32.c @@ -21,7 +21,6 @@ #include "platform.h" #include "target.h" -#if !defined(STM32F1) && !defined(STM32F4) static const uint32_t crc32_table[] = { 0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005, @@ -108,31 +107,4 @@ uint32_t generic_crc32(struct target_s *target, uint32_t base, int len) } return crc; } -#else -#include -uint32_t generic_crc32(struct target_s *target, uint32_t base, int len) -{ - uint32_t data; - uint8_t byte; - - CRC_CR |= CRC_CR_RESET; - - while (len >3) { - if (target_mem_read_words(target, &data, base, 1) != 0) - return -1; - - CRC_DR = data; - base+=4; - len -= 4; - } - while (len--) { - if (target_mem_read_bytes(target, &byte, base, 1) != 0) - return -1; - - CRC_DR = byte; - base++; - } - return CRC_DR; -} -#endif -- cgit v1.2.3 From 7db6e3e00c1419fd9c470dc743bdfaf20b197f91 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sun, 14 Apr 2013 11:28:46 -0700 Subject: Revert "Revert "STM32: Use hardware CRC unit"" This reverts commit 58abbf7fc7686a16ee5bdfacb1241a5adf2921ea. --- src/crc32.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'src') diff --git a/src/crc32.c b/src/crc32.c index 25cd53b..d5c8732 100644 --- a/src/crc32.c +++ b/src/crc32.c @@ -21,6 +21,7 @@ #include "platform.h" #include "target.h" +#if !defined(STM32F1) && !defined(STM32F4) static const uint32_t crc32_table[] = { 0x00000000, 0x04C11DB7, 0x09823B6E, 0x0D4326D9, 0x130476DC, 0x17C56B6B, 0x1A864DB2, 0x1E475005, @@ -107,4 +108,31 @@ uint32_t generic_crc32(struct target_s *target, uint32_t base, int len) } return crc; } +#else +#include +uint32_t generic_crc32(struct target_s *target, uint32_t base, int len) +{ + uint32_t data; + uint8_t byte; + + CRC_CR |= CRC_CR_RESET; + + while (len >3) { + if (target_mem_read_words(target, &data, base, 1) != 0) + return -1; + + CRC_DR = data; + base+=4; + len -= 4; + } + while (len--) { + if (target_mem_read_bytes(target, &byte, base, 1) != 0) + return -1; + + CRC_DR = byte; + base++; + } + return CRC_DR; +} +#endif -- cgit v1.2.3 From 91b481731d14789a87b9e5db29e7b715bcbc618b Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Sun, 14 Apr 2013 21:55:32 +0400 Subject: stm32f1/stm32f4: fix hardware CRC calculation This was real-life tested on stm32f1 hardware including computation for odd-sized ranges. Signed-off-by: Paul Fertser --- src/crc32.c | 31 ++++++++++++++++++++----------- src/platforms/f4discovery/platform.c | 1 + src/platforms/native/platform.c | 1 + src/platforms/stlink/platform.c | 1 + src/platforms/swlink/platform.c | 1 + 5 files changed, 24 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/crc32.c b/src/crc32.c index d5c8732..810a9dd 100644 --- a/src/crc32.c +++ b/src/crc32.c @@ -113,26 +113,35 @@ uint32_t generic_crc32(struct target_s *target, uint32_t base, int len) uint32_t generic_crc32(struct target_s *target, uint32_t base, int len) { uint32_t data; - uint8_t byte; + uint32_t crc; + size_t i; - CRC_CR |= CRC_CR_RESET; + CRC_CR |= CRC_CR_RESET; - while (len >3) { - if (target_mem_read_words(target, &data, base, 1) != 0) + while (len > 3) { + if (target_mem_read_words(target, &data, base, 4) != 0) return -1; - CRC_DR = data; - base+=4; - len -= 4; + CRC_DR = __builtin_bswap32(data); + base += 4; + len -= 4; } + + crc = CRC_DR; + while (len--) { - if (target_mem_read_bytes(target, &byte, base, 1) != 0) + if (target_mem_read_bytes(target, (uint8_t *)&data, base++, 1) != 0) return -1; - CRC_DR = byte; - base++; + crc ^= data << 24; + for (i = 0; i < 8; i++) { + if (crc & 0x80000000) + crc = (crc << 1) ^ 0x4C11DB7; + else + crc <<= 1; + } } - return CRC_DR; + return crc; } #endif diff --git a/src/platforms/f4discovery/platform.c b/src/platforms/f4discovery/platform.c index 4aa14a6..de39ab7 100644 --- a/src/platforms/f4discovery/platform.c +++ b/src/platforms/f4discovery/platform.c @@ -53,6 +53,7 @@ int platform_init(void) rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPAEN); rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPBEN); rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPDEN); + rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_CRCEN); /* Set up USB Pins and alternate function*/ diff --git a/src/platforms/native/platform.c b/src/platforms/native/platform.c index 8ded81a..0c13047 100644 --- a/src/platforms/native/platform.c +++ b/src/platforms/native/platform.c @@ -72,6 +72,7 @@ int platform_init(void) rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPBEN); rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_AFIOEN); + rcc_peripheral_enable_clock(&RCC_AHBENR, RCC_AHBENR_CRCEN); /* Setup GPIO ports */ gpio_clear(USB_PU_PORT, USB_PU_PIN); diff --git a/src/platforms/stlink/platform.c b/src/platforms/stlink/platform.c index 5eaf5fc..e8435b9 100644 --- a/src/platforms/stlink/platform.c +++ b/src/platforms/stlink/platform.c @@ -79,6 +79,7 @@ int platform_init(void) rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPBEN); rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN); rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_AFIOEN); + rcc_peripheral_enable_clock(&RCC_AHBENR, RCC_AHBENR_CRCEN); /* On Rev 1 unconditionally activate MCO on PORTA8 with HSE * platform_hwversion() also needed to initialize led_idle_run! diff --git a/src/platforms/swlink/platform.c b/src/platforms/swlink/platform.c index 33d4f12..1aa45b1 100644 --- a/src/platforms/swlink/platform.c +++ b/src/platforms/swlink/platform.c @@ -51,6 +51,7 @@ int platform_init(void) rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPBEN); rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_AFIOEN); + rcc_peripheral_enable_clock(&RCC_AHBENR, RCC_AHBENR_CRCEN); /* Unmap JTAG Pins so we can reuse as GPIO */ data = AFIO_MAPR; -- cgit v1.2.3 From 9c95f039cfb45619d1b9c5bc17d47984bea81029 Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Sun, 14 Apr 2013 21:56:17 +0400 Subject: Make code compatible with newlib-nano and use it for stlink With gcc-arm-none-eabi-4_7-2013q1-20130313 and -O2 I get text data bss dec hex filename 45744 304 2376 48424 bd28 blackmagic With -Os the results are even more impressive: text data bss dec hex filename 37900 304 2376 40580 9e84 blackmagic Since -Os might lower the debugging speed, do not enable it yet in the absence of real measurements. Signed-off-by: Paul Fertser --- src/gdb_main.c | 18 +++++++++--------- src/platforms/stlink/Makefile.inc | 2 +- 2 files changed, 10 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/gdb_main.c b/src/gdb_main.c index d93a8ce..6be6d0f 100644 --- a/src/gdb_main.c +++ b/src/gdb_main.c @@ -94,7 +94,7 @@ gdb_main(void) case 'm': { /* 'm addr,len': Read len bytes from addr */ uint32_t addr, len; ERROR_IF_NO_TARGET(); - sscanf(pbuf, "m%08lX,%08lX", &addr, &len); + sscanf(pbuf, "m%08lx,%08lx", &addr, &len); DEBUG("m packet: addr = %08lX, len = %08lX\n", addr, len); uint8_t mem[len]; if(((addr & 3) == 0) && ((len & 3) == 0)) @@ -119,7 +119,7 @@ gdb_main(void) uint32_t addr, len; int hex; ERROR_IF_NO_TARGET(); - sscanf(pbuf, "M%08lX,%08lX:%n", &addr, &len, &hex); + sscanf(pbuf, "M%08lx,%08lx:%n", &addr, &len, &hex); DEBUG("M packet: addr = %08lX, len = %08lX\n", addr, len); uint8_t mem[len]; unhexify(mem, pbuf + hex, len); @@ -218,7 +218,7 @@ gdb_main(void) uint32_t addr, len; int bin; ERROR_IF_NO_TARGET(); - sscanf(pbuf, "X%08lX,%08lX:%n", &addr, &len, &bin); + sscanf(pbuf, "X%08lx,%08lx:%n", &addr, &len, &bin); DEBUG("X packet: addr = %08lX, len = %08lX\n", addr, len); if(((addr & 3) == 0) && ((len & 3) == 0)) target_mem_write_words(cur_target, addr, (void*)pbuf+bin, len); @@ -258,7 +258,7 @@ handle_q_string_reply(const char *str, const char *param) { unsigned long addr, len; - if (sscanf(param, "%08lX,%08lX", &addr, &len) != 2) { + if (sscanf(param, "%08lx,%08lx", &addr, &len) != 2) { gdb_putpacketz("E01"); return; } @@ -328,7 +328,7 @@ handle_q_packet(char *packet, int len) return; } handle_q_string_reply(cur_target->tdesc, packet + 31); - } else if (sscanf(packet, "qCRC:%08lX,%08lX", &addr, &alen) == 2) { + } else if (sscanf(packet, "qCRC:%08lx,%08lx", &addr, &alen) == 2) { if(!cur_target) { gdb_putpacketz("E01"); return; @@ -348,7 +348,7 @@ handle_v_packet(char *packet, int plen) int bin; static uint8_t flash_mode = 0; - if (sscanf(packet, "vAttach;%08lX", &addr) == 1) { + if (sscanf(packet, "vAttach;%08lx", &addr) == 1) { /* Attach to remote target processor */ target *t; uint32_t i; @@ -375,7 +375,7 @@ handle_v_packet(char *packet, int plen) gdb_putpacketz("T05"); } else gdb_putpacketz("E01"); - } else if (sscanf(packet, "vFlashErase:%08lX,%08lX", &addr, &len) == 2) { + } else if (sscanf(packet, "vFlashErase:%08lx,%08lx", &addr, &len) == 2) { /* Erase Flash Memory */ DEBUG("Flash Erase %08lX %08lX\n", addr, len); if(!cur_target) { gdb_putpacketz("EFF"); return; } @@ -391,7 +391,7 @@ handle_v_packet(char *packet, int plen) else gdb_putpacketz("EFF"); - } else if (sscanf(packet, "vFlashWrite:%08lX:%n", &addr, &bin) == 1) { + } else if (sscanf(packet, "vFlashWrite:%08lx:%n", &addr, &bin) == 1) { /* Write Flash Memory */ len = plen - bin; DEBUG("Flash Write %08lX %08lX\n", addr, len); @@ -425,7 +425,7 @@ handle_z_packet(char *packet, int plen) * with real sscanf() though... */ //sscanf(packet, "%*[zZ]%hhd,%08lX,%hhd", &type, &addr, &len); type = packet[1] - '0'; - sscanf(packet + 2, ",%08lX,%d", &addr, &len); + sscanf(packet + 2, ",%08lx,%d", &addr, &len); switch(type) { case 1: /* Hardware breakpoint */ if(!cur_target->set_hw_bp) { /* Not supported */ diff --git a/src/platforms/stlink/Makefile.inc b/src/platforms/stlink/Makefile.inc index 627b14b..62760d5 100644 --- a/src/platforms/stlink/Makefile.inc +++ b/src/platforms/stlink/Makefile.inc @@ -5,7 +5,7 @@ OBJCOPY = $(CROSS_COMPILE)objcopy CFLAGS += -mcpu=cortex-m3 -mthumb \ -DSTM32F1 -DDISCOVERY_STLINK -I../libopencm3/include \ -I platforms/stm32 -LDFLAGS_BOOT = -lopencm3_stm32f1 -Wl,--defsym,_stack=0x20005000 \ +LDFLAGS_BOOT = --specs=nano.specs -lopencm3_stm32f1 -Wl,--defsym,_stack=0x20005000 \ -Wl,-T,platforms/stm32/stlink.ld -nostartfiles -lc -lnosys \ -Wl,-Map=mapfile -mthumb -mcpu=cortex-m3 -Wl,-gc-sections \ -L../libopencm3/lib -- cgit v1.2.3 From 6b7babf624c48c711c35627d84351c1b32b52d78 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Mon, 15 Apr 2013 15:28:02 +0200 Subject: stm32f4: Add option erase command -- Uwe Bonnes bon@elektron.ikp.physik.tu-darmstadt.de Institut fuer Kernphysik Schlossgartenstrasse 9 64289 Darmstadt --------- Tel. 06151 162516 -------- Fax. 06151 164321 ---------- >From d488dffe4dab4e5188c750489006260745a9e25a Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Mon, 15 Apr 2013 15:26:58 +0200 Subject: stm32f4: Add option erase command --- src/stm32f4.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/stm32f4.c b/src/stm32f4.c index 09c7965..67c44b8 100644 --- a/src/stm32f4.c +++ b/src/stm32f4.c @@ -331,10 +331,14 @@ static bool stm32f4_cmd_option(target *t, int argc, char *argv[]) ADIv5_AP_t *ap = adiv5_target_ap(t); - if ((argc == 3) && !strcmp(argv[1], "write")) { + if ((argc == 2) && !strcmp(argv[1], "erase")) { + stm32f4_option_write(t, 0x0fffaaed); + } + else if ((argc == 3) && !strcmp(argv[1], "write")) { val = strtoul(argv[2], NULL, 0); stm32f4_option_write(t, val); } else { + gdb_out("usage: monitor option erase\n"); gdb_out("usage: monitor option write \n"); } -- cgit v1.2.3 From da448ec1a6b9562b5e91a5a09037ad903cbb56fb Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Tue, 16 Apr 2013 12:14:37 -0700 Subject: libftdi: Add 'flossjtag' cable. --- src/platforms/libftdi/platform.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'src') diff --git a/src/platforms/libftdi/platform.c b/src/platforms/libftdi/platform.c index d7f11dd..e3cad35 100644 --- a/src/platforms/libftdi/platform.c +++ b/src/platforms/libftdi/platform.c @@ -43,6 +43,15 @@ static struct cable_desc_s { char *description; char * name; } cable_desc[] = { + { + .vendor = 0x0403, + .product = 0x6010, + .interface = INTERFACE_A, + .dbus_data = 0x08, + .dbus_ddr = 0x1B, + .description = "FLOSS-JTAG", + .name = "flossjtag" + }, { .vendor = 0x0403, .product = 0x6010, -- cgit v1.2.3 From 67a96410e39933bb6c5293444bd69df57af6be9a Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Tue, 16 Apr 2013 12:28:06 -0700 Subject: libftdi: Clean up warnings. --- src/platforms/libftdi/Makefile.inc | 2 +- src/platforms/libftdi/gdb_if.c | 4 +++- src/platforms/libftdi/jtagtap.c | 5 ++--- src/platforms/libftdi/platform.c | 8 ++++++++ src/platforms/libftdi/platform.h | 2 +- 5 files changed, 15 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/platforms/libftdi/Makefile.inc b/src/platforms/libftdi/Makefile.inc index fa6292b..f7cc9c5 100644 --- a/src/platforms/libftdi/Makefile.inc +++ b/src/platforms/libftdi/Makefile.inc @@ -1,2 +1,2 @@ -CFLAGS += -DLIBFTDI +CFLAGS += -DLIBFTDI -Wno-format LDFLAGS += -lftdi -lusb diff --git a/src/platforms/libftdi/gdb_if.c b/src/platforms/libftdi/gdb_if.c index 4b4f4a5..ff49b57 100644 --- a/src/platforms/libftdi/gdb_if.c +++ b/src/platforms/libftdi/gdb_if.c @@ -108,7 +108,9 @@ unsigned char gdb_if_getchar_to(int timeout) void gdb_if_putchar(unsigned char c, int flush) { - if(gdb_if_conn > 0) + (void)flush; + + if (gdb_if_conn > 0) send(gdb_if_conn, &c, 1, 0); } diff --git a/src/platforms/libftdi/jtagtap.c b/src/platforms/libftdi/jtagtap.c index cd58707..c914646 100644 --- a/src/platforms/libftdi/jtagtap.c +++ b/src/platforms/libftdi/jtagtap.c @@ -51,12 +51,11 @@ int jtagtap_init(void) { - int err; - assert(ftdic != NULL); /* Go to JTAG mode for SWJ-DP */ - for(int i = 0; i <= 50; i++) jtagtap_next(1, 0); /* Reset SW-DP */ + for (int i = 0; i <= 50; i++) + jtagtap_next(1, 0); /* Reset SW-DP */ jtagtap_tms_seq(0xE73C, 16); /* SWD to JTAG sequence */ jtagtap_soft_reset(); diff --git a/src/platforms/libftdi/platform.c b/src/platforms/libftdi/platform.c index e3cad35..ec2a8f1 100644 --- a/src/platforms/libftdi/platform.c +++ b/src/platforms/libftdi/platform.c @@ -267,3 +267,11 @@ void platform_delay(uint32_t delay) usleep(delay * 100000); } +void morse(const char *msg, char repeat) +{ + (void)repeat; + + if (msg != NULL) + fprintf(stderr,"%s\n", msg); +} + diff --git a/src/platforms/libftdi/platform.h b/src/platforms/libftdi/platform.h index e23bf96..5ce45fd 100644 --- a/src/platforms/libftdi/platform.h +++ b/src/platforms/libftdi/platform.h @@ -40,12 +40,12 @@ #define PLATFORM_FATAL_ERROR(error) abort() #define PLATFORM_SET_FATAL_ERROR_RECOVERY() -#define morse(x, y) fprintf(stderr,"%s\n", x) #define morse_msg 0 extern struct ftdi_context *ftdic; int platform_init(int argc, char **argv); +void morse(const char *msg, char repeat); const char *platform_target_voltage(void); void platform_delay(uint32_t delay); -- cgit v1.2.3 From 89b908337dd785f888646aa7036c708d763f7df7 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Tue, 16 Apr 2013 12:36:19 -0700 Subject: Add missing #includes --- src/command.c | 4 ++++ src/stm32f4.c | 1 + 2 files changed, 5 insertions(+) (limited to 'src') diff --git a/src/command.c b/src/command.c index 46163fd..e1ed837 100644 --- a/src/command.c +++ b/src/command.c @@ -35,6 +35,10 @@ #include "adiv5.h" +#ifdef PLATFORM_HAS_TRACESWO +# include "traceswo.h" +#endif + static bool cmd_version(void); static bool cmd_help(target *t); diff --git a/src/stm32f4.c b/src/stm32f4.c index 67c44b8..b9764cc 100644 --- a/src/stm32f4.c +++ b/src/stm32f4.c @@ -37,6 +37,7 @@ #include "adiv5.h" #include "target.h" #include "command.h" +#include "gdb_packet.h" static bool stm32f4_cmd_erase_mass(target *t); static bool stm32f4_cmd_option(target *t, int argc, char *argv[]); -- cgit v1.2.3 From 45e02360b78cf4f564b9a81afb07742c9f579143 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Tue, 16 Apr 2013 12:47:29 -0700 Subject: native: Fix up deprecated warnings. --- src/platforms/native/platform.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/platforms/native/platform.c b/src/platforms/native/platform.c index 0c13047..24eb79b 100644 --- a/src/platforms/native/platform.c +++ b/src/platforms/native/platform.c @@ -232,7 +232,7 @@ static void adc_init(void) adc_set_single_conversion_mode(ADC1); adc_disable_external_trigger_regular(ADC1); adc_set_right_aligned(ADC1); - adc_set_conversion_time_on_all_channels(ADC1, ADC_SMPR_SMP_28DOT5CYC); + adc_set_sample_time_on_all_channels(ADC1, ADC_SMPR_SMP_28DOT5CYC); adc_power_on(ADC1); @@ -253,12 +253,12 @@ const char *platform_target_voltage(void) const u8 channel = 8; adc_set_regular_sequence(ADC1, 1, (u8*)&channel); - adc_on(ADC1); + adc_start_conversion_direct(ADC1); /* Wait for end of conversion. */ - while (!(ADC_SR(ADC1) & ADC_SR_EOC)); + while (!adc_eoc(ADC1)); - u32 val = ADC_DR(ADC1) * 99; /* 0-4095 */ + u32 val = adc_read_regular(ADC1) * 99; /* 0-4095 */ ret[0] = '0' + val / 81910; ret[2] = '0' + (val / 8191) % 10; -- cgit v1.2.3 From 126df7bb35b35de546ab94b9189553f11af553c0 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Tue, 16 Apr 2013 16:47:38 -0700 Subject: Allow extra LDFLAGS on command line. Use nano.specs for swlink. --- src/platforms/f4discovery/Makefile.inc | 2 +- src/platforms/native/Makefile.inc | 2 +- src/platforms/stlink/Makefile.inc | 3 ++- src/platforms/swlink/Makefile.inc | 3 ++- 4 files changed, 6 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/platforms/f4discovery/Makefile.inc b/src/platforms/f4discovery/Makefile.inc index 5470d65..ed4bde7 100644 --- a/src/platforms/f4discovery/Makefile.inc +++ b/src/platforms/f4discovery/Makefile.inc @@ -7,7 +7,7 @@ CFLAGS += -Istm32/include -mcpu=cortex-m4 -mthumb \ -DSTM32F4 -DF4DISCOVERY -I../libopencm3/include \ -Iplatforms/stm32 -LDFLAGS_BOOT = -lopencm3_stm32f4 -Wl,--defsym,_stack=0x20020000 \ +LDFLAGS_BOOT := $(LDFLAGS) -lopencm3_stm32f4 -Wl,--defsym,_stack=0x20020000 \ -Wl,-T,platforms/stm32/f4discovery.ld -nostartfiles -lc -lnosys \ -Wl,-Map=mapfile -mthumb -mcpu=cortex-m4 -Wl,-gc-sections \ -mfloat-abi=hard -mfpu=fpv4-sp-d16 \ diff --git a/src/platforms/native/Makefile.inc b/src/platforms/native/Makefile.inc index 77c07e9..cc4da0b 100644 --- a/src/platforms/native/Makefile.inc +++ b/src/platforms/native/Makefile.inc @@ -6,7 +6,7 @@ CFLAGS += -Istm32/include -mcpu=cortex-m3 -mthumb \ -DSTM32F1 -DBLACKMAGIC -I../libopencm3/include \ -Iplatforms/stm32 -LDFLAGS_BOOT = -lopencm3_stm32f1 -Wl,--defsym,_stack=0x20005000 \ +LDFLAGS_BOOT := $(LDFLAGS) -lopencm3_stm32f1 -Wl,--defsym,_stack=0x20005000 \ -Wl,-T,platforms/stm32/blackmagic.ld -nostartfiles -lc -lnosys \ -Wl,-Map=mapfile -mthumb -mcpu=cortex-m3 -Wl,-gc-sections \ -L../libopencm3/lib diff --git a/src/platforms/stlink/Makefile.inc b/src/platforms/stlink/Makefile.inc index 62760d5..1f46588 100644 --- a/src/platforms/stlink/Makefile.inc +++ b/src/platforms/stlink/Makefile.inc @@ -5,7 +5,8 @@ OBJCOPY = $(CROSS_COMPILE)objcopy CFLAGS += -mcpu=cortex-m3 -mthumb \ -DSTM32F1 -DDISCOVERY_STLINK -I../libopencm3/include \ -I platforms/stm32 -LDFLAGS_BOOT = --specs=nano.specs -lopencm3_stm32f1 -Wl,--defsym,_stack=0x20005000 \ +LDFLAGS_BOOT := $(LDFLAGS) --specs=nano.specs \ + -lopencm3_stm32f1 -Wl,--defsym,_stack=0x20005000 \ -Wl,-T,platforms/stm32/stlink.ld -nostartfiles -lc -lnosys \ -Wl,-Map=mapfile -mthumb -mcpu=cortex-m3 -Wl,-gc-sections \ -L../libopencm3/lib diff --git a/src/platforms/swlink/Makefile.inc b/src/platforms/swlink/Makefile.inc index df0b648..ff349db 100644 --- a/src/platforms/swlink/Makefile.inc +++ b/src/platforms/swlink/Makefile.inc @@ -5,7 +5,8 @@ OBJCOPY = $(CROSS_COMPILE)objcopy CFLAGS += -mcpu=cortex-m3 -mthumb \ -DSTM32F1 -DDISCOVERY_SWLINK -I../libopencm3/include \ -I platforms/stm32 -LDFLAGS_BOOT = -lopencm3_stm32f1 -Wl,--defsym,_stack=0x20005000 \ +LDFLAGS_BOOT := $(LDFLAGS) --specs=nano.specs \ + -lopencm3_stm32f1 -Wl,--defsym,_stack=0x20005000 \ -Wl,-T,platforms/stm32/stlink.ld -nostartfiles -lc -lnosys \ -Wl,-Map=mapfile -mthumb -mcpu=cortex-m3 -Wl,-gc-sections \ -L../libopencm3/lib -- cgit v1.2.3 From 6659d87e9b2daa98b468d9f2648daf37d04bbf4d Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Tue, 16 Apr 2013 16:51:59 -0700 Subject: Remove DFU bootloader self protection. It can still be enabled by building with -DDFU_SELF_PROTECT --- src/platforms/stm32/dfu_f1.c | 2 ++ src/platforms/stm32/dfu_f4.c | 2 ++ 2 files changed, 4 insertions(+) (limited to 'src') diff --git a/src/platforms/stm32/dfu_f1.c b/src/platforms/stm32/dfu_f1.c index 9d82bec..827712d 100644 --- a/src/platforms/stm32/dfu_f1.c +++ b/src/platforms/stm32/dfu_f1.c @@ -61,6 +61,7 @@ uint32_t dfu_poll_timeout(uint8_t cmd, uint32_t addr, uint16_t blocknum) void dfu_protect_enable(void) { +#ifdef DFU_SELF_PROTECT if ((FLASH_WRPR & 0x03) != 0x00) { flash_unlock(); FLASH_CR = 0; @@ -70,6 +71,7 @@ void dfu_protect_enable(void) /* MD Device: Protect 2 bits with (4 * 1k pages each)*/ flash_program_option_bytes(FLASH_OBP_WRP10, 0x03FC); } +#endif } void dfu_jump_app_if_valid(void) diff --git a/src/platforms/stm32/dfu_f4.c b/src/platforms/stm32/dfu_f4.c index 4f47c99..960ec23 100644 --- a/src/platforms/stm32/dfu_f4.c +++ b/src/platforms/stm32/dfu_f4.c @@ -80,10 +80,12 @@ uint32_t dfu_poll_timeout(uint8_t cmd, uint32_t addr, uint16_t blocknum) void dfu_protect_enable(void) { +#ifdef DFU_SELF_PROTECT if ((FLASH_OPTCR & 0x10000) != 0) { flash_program_option_bytes(FLASH_OPTCR & ~0x10000); flash_lock_option_bytes(); } +#endif } void dfu_jump_app_if_valid(void) -- cgit v1.2.3 From ad151fdca83aa2ea4dfd4f77a27507c9fc53f5d6 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Mon, 15 Apr 2013 16:21:58 +0200 Subject: F4 Discovery: - Unconditionally use the System Bootloader - Use PC2/4/5/6 Pins for JTAG/SWD to avoid collision with eventual STLink Uart connection - Indicate Bootloader with blue LED --- src/platforms/f4discovery/Makefile.inc | 16 +++---------- src/platforms/f4discovery/Readme | 35 +++++++++++++++++++---------- src/platforms/f4discovery/platform.c | 41 +++++++++++++++++----------------- src/platforms/f4discovery/platform.h | 37 +++++++++++++++--------------- 4 files changed, 66 insertions(+), 63 deletions(-) (limited to 'src') diff --git a/src/platforms/f4discovery/Makefile.inc b/src/platforms/f4discovery/Makefile.inc index ed4bde7..f67b278 100644 --- a/src/platforms/f4discovery/Makefile.inc +++ b/src/platforms/f4discovery/Makefile.inc @@ -7,12 +7,11 @@ CFLAGS += -Istm32/include -mcpu=cortex-m4 -mthumb \ -DSTM32F4 -DF4DISCOVERY -I../libopencm3/include \ -Iplatforms/stm32 -LDFLAGS_BOOT := $(LDFLAGS) -lopencm3_stm32f4 -Wl,--defsym,_stack=0x20020000 \ +LDFLAGS = -lopencm3_stm32f4 -Wl,--defsym,_stack=0x20020000 \ -Wl,-T,platforms/stm32/f4discovery.ld -nostartfiles -lc -lnosys \ -Wl,-Map=mapfile -mthumb -mcpu=cortex-m4 -Wl,-gc-sections \ -mfloat-abi=hard -mfpu=fpv4-sp-d16 \ -L../libopencm3/lib -LDFLAGS = $(LDFLAGS_BOOT) -Wl,-Ttext=0x8010000 VPATH += platforms/stm32 @@ -21,19 +20,10 @@ SRC += cdcacm.c \ traceswo.c \ usbuart.c \ -all: blackmagic.bin blackmagic_dfu.bin blackmagic_dfu.hex +all: blackmagic.bin blackmagic.bin: blackmagic $(OBJCOPY) -O binary $^ $@ -blackmagic_dfu: usbdfu.o dfucore.o dfu_f4.o - $(CC) $^ -o $@ $(LDFLAGS_BOOT) - -blackmagic_dfu.bin: blackmagic_dfu - $(OBJCOPY) -O binary $^ $@ - -blackmagic_dfu.hex: blackmagic_dfu - $(OBJCOPY) -O ihex $^ $@ - host_clean: - -rm blackmagic.bin blackmagic_dfu blackmagic_dfu.bin blackmagic_dfu.hex + -rm blackmagic.bin diff --git a/src/platforms/f4discovery/Readme b/src/platforms/f4discovery/Readme index 6035917..9bc1557 100644 --- a/src/platforms/f4discovery/Readme +++ b/src/platforms/f4discovery/Readme @@ -1,17 +1,28 @@ -Application start address: -========================= +System vs BMP Bootloader +======================== +For the BMP bootloader, flashing qas not reliable. So we use the system +bootloder unconditional. -Use 0x8010000 -- lower 3 16 k pages may be used for parameter storage -- Erasing a single 64 k Page is faster then erasing 2 16 k Pages - eventual the 64 k page +Connections: +==================== +PA0: User button to force system bootloader entry with reset +PA2/PA3 eventual connected to the STLINK/ STM32F103C8 -Internal boot loader: -==================== +PC2: TDI +PC4: TMS/SWDIO +PC5: TCK/SWCLK +PC6: TDO/TRACESWO + +PC1: TRST +PC8: SRST -When we request invokation of a bootloader from inside the application, -we boot the device internal bootloader with the blue botton pressed. +Blue Led: Indicator that system bootloader is entered via BMP -That way, we can easy exchange the custom bootloader via the device -internale bootloader \ No newline at end of file +Bootstrapping the F4Discovery on-board ST-Link +============================================== +http://embdev.net/articles/STM_Discovery_as_Black_Magic_Probe has some hints +how to modify the F4Discovery on-board ST-Link. If you try to do so and hit +a problem that stands some test like that you load the right firmware to the +right device via the right BMP probe, explain, report and ask on the +blackmagic mailing list http://sourceforge.net/mail/?group_id=407419. diff --git a/src/platforms/f4discovery/platform.c b/src/platforms/f4discovery/platform.c index de39ab7..645a3c5 100644 --- a/src/platforms/f4discovery/platform.c +++ b/src/platforms/f4discovery/platform.c @@ -46,23 +46,28 @@ static void morse_update(void); int platform_init(void) { + /* Check the USER button*/ + rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPAEN); + if(gpio_get(GPIOA, GPIO0)) { + assert_boot_pin(); + scb_reset_core(); + } + rcc_clock_setup_hse_3v3(&hse_8mhz_3v3[CLOCK_3V3_168MHZ]); /* Enable peripherals */ rcc_peripheral_enable_clock(&RCC_AHB2ENR, RCC_AHB2ENR_OTGFSEN); - rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPAEN); - rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPBEN); + rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPCEN); rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPDEN); rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_CRCEN); - /* Set up USB Pins and alternate function*/ gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO9 | GPIO11 | GPIO12); gpio_set_af(GPIOA, GPIO_AF10, GPIO9 | GPIO11 | GPIO12); - GPIOA_OSPEEDR &=~0xfc; - GPIOA_OSPEEDR |= 0xa8; + GPIOC_OSPEEDR &=~0xF30; + GPIOC_OSPEEDR |= 0xA20; gpio_mode_setup(JTAG_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, TMS_PIN | TCK_PIN | TDI_PIN); @@ -73,7 +78,7 @@ int platform_init(void) gpio_mode_setup(LED_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, - LED_UART | LED_IDLE_RUN | LED_ERROR | LED_SPARE1); + LED_UART | LED_IDLE_RUN | LED_ERROR | LED_BOOTLOADER); /* Setup heartbeat timer */ systick_set_clocksource(STK_CTRL_CLKSOURCE_AHB_DIV8); @@ -85,8 +90,6 @@ int platform_init(void) usbuart_init(); - SCB_VTOR = 0x10000; // Relocate interrupt vector table here - cdcacm_init(); jtag_scan(NULL); @@ -194,16 +197,14 @@ const char *platform_target_voltage(void) void assert_boot_pin(void) { - if (gpio_get(GPIOA, GPIO0)) { - /* Jump to the built in bootloader by mapping System flash */ - rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_SYSCFGEN); - SYSCFG_MEMRM &= ~3; - SYSCFG_MEMRM |= 1; - } - else { - /* Flag Bootloader Request by mimicing a pushed USER button*/ - gpio_mode_setup(GPIOA, GPIO_MODE_OUTPUT, - GPIO_PUPD_NONE, GPIO0); - gpio_set(GPIOA, GPIO0); - } + /* Assert blue LED as indicator we are in the bootloader */ + rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPDEN); + gpio_mode_setup(LED_PORT, GPIO_MODE_OUTPUT, + GPIO_PUPD_NONE, LED_BOOTLOADER); + gpio_set(LED_PORT, LED_BOOTLOADER); + + /* Jump to the built in bootloader by mapping System flash */ + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_SYSCFGEN); + SYSCFG_MEMRM &= ~3; + SYSCFG_MEMRM |= 1; } diff --git a/src/platforms/f4discovery/platform.h b/src/platforms/f4discovery/platform.h index a1deb48..c5aac17 100644 --- a/src/platforms/f4discovery/platform.h +++ b/src/platforms/f4discovery/platform.h @@ -49,15 +49,16 @@ extern usbd_device *usbdev; * LED0 = PD12 (Green LED : Running) * LED1 = PD13 (Orange LED : Idle) * LED2 = PD12 (Red LED : Error) + * LED3 = PD15 (Blue LED : Bootloader active) * * TPWR = XXX (input) -- analogue on mini design ADC1, ch8 - * nTRST = PD0 - * SRST_OUT = PD1 - * TDI = PA1 - * TMS = PA3 (input for SWDP) - * TCK = PA8 - * TDO = PB4 (input) - * nSRST = PD2 (input) + * nTRST = PC1 + * SRST_OUT = PC8 + * TDI = PC2 + * TMS = PC4 (input for SWDP) + * TCK = PC5/SWCLK + * TDO = PC6 (input for TRACESWO + * nSRST = * * USB cable pull-up: PA8 * USB VBUS detect: PB13 -- New on mini design. @@ -66,32 +67,32 @@ extern usbd_device *usbdev; */ /* Hardware definitions... */ -#define JTAG_PORT GPIOA +#define JTAG_PORT GPIOC #define TDI_PORT JTAG_PORT #define TMS_PORT JTAG_PORT #define TCK_PORT JTAG_PORT -#define TDO_PORT GPIOB -#define TDI_PIN GPIO1 -#define TMS_PIN GPIO3 -#define TCK_PIN GPIO2 -#define TDO_PIN GPIO4 +#define TDO_PORT GPIOC +#define TDI_PIN GPIO2 +#define TMS_PIN GPIO4 +#define TCK_PIN GPIO5 +#define TDO_PIN GPIO6 #define SWDIO_PORT JTAG_PORT #define SWCLK_PORT JTAG_PORT #define SWDIO_PIN TMS_PIN #define SWCLK_PIN TCK_PIN -#define TRST_PORT GPIOD -#define TRST_PIN GPIO0 -#define SRST_PORT GPIOD -#define SRST_PIN GPIO1 +#define TRST_PORT GPIOC +#define TRST_PIN GPIO1 +#define SRST_PORT GPIOC +#define SRST_PIN GPIO8 #define LED_PORT GPIOD #define LED_PORT_UART GPIOD #define LED_UART GPIO12 #define LED_IDLE_RUN GPIO13 #define LED_ERROR GPIO14 -#define LED_SPARE1 GPIO15 +#define LED_BOOTLOADER GPIO15 #define TMS_SET_MODE() gpio_mode_setup(TMS_PORT, GPIO_MODE_OUTPUT, \ GPIO_PUPD_NONE, TMS_PIN); -- cgit v1.2.3 From f1ea5ed8f9f6dc1f006185d051da682bed63c6ac Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sun, 21 Apr 2013 14:55:10 +0200 Subject: F4Discovery: Slow Down GPIO access a little, as off-board SWD otherwise needs _very_ good ground connection. --- src/platforms/f4discovery/platform.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/platforms/f4discovery/platform.h b/src/platforms/f4discovery/platform.h index c5aac17..0010ec4 100644 --- a/src/platforms/f4discovery/platform.h +++ b/src/platforms/f4discovery/platform.h @@ -193,12 +193,14 @@ void uart_usb_buf_drain(uint8_t ep); static inline void _gpio_set(u32 gpioport, u16 gpios) { GPIO_BSRR(gpioport) = gpios; + GPIO_BSRR(gpioport) = gpios; } #define gpio_set _gpio_set static inline void _gpio_clear(u32 gpioport, u16 gpios) { GPIO_BSRR(gpioport) = gpios<<16; + GPIO_BSRR(gpioport) = gpios<<16; } #define gpio_clear _gpio_clear -- cgit v1.2.3 From 43f7e7a3cf384e880bfefa6257f15c8915b02e3b Mon Sep 17 00:00:00 2001 From: Allen Ibara Date: Wed, 27 Mar 2013 12:09:49 -0700 Subject: Changes to the USBUART to make it less likely to drop characters at higher baud rates. USB UART seems to work fine at 115.2Kbps or 230.4Kbps, but starts to drop characters as the data rate goes higher. This commit changes the usbuart ISR to fill a software FIFO, and adds a low priority timer interrupt to run deferred processing to drain a FIFO and send USB CDCACM packets, rather than calling the usb send within the UART ISR. Tested on native platform, up to 1.5MBps. --- src/platforms/f4discovery/platform.h | 5 ++ src/platforms/native/platform.c | 3 +- src/platforms/native/platform.h | 5 ++ src/platforms/stlink/platform.h | 5 ++ src/platforms/stm32/usbuart.c | 126 ++++++++++++++++++++++++++++------- src/platforms/swlink/platform.h | 5 ++ 6 files changed, 123 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/platforms/f4discovery/platform.h b/src/platforms/f4discovery/platform.h index 0010ec4..c1423b6 100644 --- a/src/platforms/f4discovery/platform.h +++ b/src/platforms/f4discovery/platform.h @@ -112,6 +112,7 @@ extern usbd_device *usbdev; */ #define IRQ_PRI_USB (2 << 4) #define IRQ_PRI_USBUSART (1 << 4) +#define IRQ_PRI_USBUSART_TIM (3 << 4) #define IRQ_PRI_TRACE (0 << 4) #define USBUSART USART3 @@ -124,6 +125,10 @@ extern usbd_device *usbdev; #define USBUSART_RX_PORT GPIOD #define USBUSART_RX_PIN GPIO9 #define USBUSART_ISR usart3_isr +#define USBUSART_TIM TIM4 +#define USBUSART_TIM_CLK_EN() rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_TIM4EN) +#define USBUSART_TIM_IRQ NVIC_TIM4_IRQ +#define USBUSART_TIM_ISR tim4_isr #define UART_PIN_SETUP() do { \ gpio_mode_setup(USBUSART_TX_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, \ diff --git a/src/platforms/native/platform.c b/src/platforms/native/platform.c index 24eb79b..3bd0816 100644 --- a/src/platforms/native/platform.c +++ b/src/platforms/native/platform.c @@ -108,8 +108,6 @@ int platform_init(void) systick_interrupt_enable(); systick_counter_enable(); - usbuart_init(); - if (platform_hwversion() > 0) { adc_init(); } else { @@ -121,6 +119,7 @@ int platform_init(void) SCB_VTOR = 0x2000; // Relocate interrupt vector table here cdcacm_init(); + usbuart_init(); jtag_scan(NULL); diff --git a/src/platforms/native/platform.h b/src/platforms/native/platform.h index a1471dc..eb91f8b 100644 --- a/src/platforms/native/platform.h +++ b/src/platforms/native/platform.h @@ -122,6 +122,7 @@ extern usbd_device *usbdev; */ #define IRQ_PRI_USB (2 << 4) #define IRQ_PRI_USBUSART (1 << 4) +#define IRQ_PRI_USBUSART_TIM (3 << 4) #define IRQ_PRI_USB_VBUS (14 << 4) #define IRQ_PRI_TRACE (0 << 4) @@ -133,6 +134,10 @@ extern usbd_device *usbdev; #define USBUSART_PORT GPIOA #define USBUSART_TX_PIN GPIO9 #define USBUSART_ISR usart1_isr +#define USBUSART_TIM TIM4 +#define USBUSART_TIM_CLK_EN() rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_TIM4EN) +#define USBUSART_TIM_IRQ NVIC_TIM4_IRQ +#define USBUSART_TIM_ISR tim4_isr #define TRACE_TIM TIM3 #define TRACE_TIM_CLK_EN() rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_TIM3EN) diff --git a/src/platforms/stlink/platform.h b/src/platforms/stlink/platform.h index cbfc0ba..09fab96 100644 --- a/src/platforms/stlink/platform.h +++ b/src/platforms/stlink/platform.h @@ -107,6 +107,7 @@ extern usbd_device *usbdev; */ #define IRQ_PRI_USB (2 << 4) #define IRQ_PRI_USBUSART (1 << 4) +#define IRQ_PRI_USBUSART_TIM (3 << 4) #define IRQ_PRI_USB_VBUS (14 << 4) #define IRQ_PRI_TIM3 (0 << 4) @@ -118,6 +119,10 @@ extern usbd_device *usbdev; #define USBUSART_PORT GPIOA #define USBUSART_TX_PIN GPIO2 #define USBUSART_ISR usart2_isr +#define USBUSART_TIM TIM4 +#define USBUSART_TIM_CLK_EN() rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_TIM4EN) +#define USBUSART_TIM_IRQ NVIC_TIM4_IRQ +#define USBUSART_TIM_ISR tim4_isr #define DEBUG(...) diff --git a/src/platforms/stm32/usbuart.c b/src/platforms/stm32/usbuart.c index 1c71105..6694d90 100644 --- a/src/platforms/stm32/usbuart.c +++ b/src/platforms/stm32/usbuart.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -28,6 +29,20 @@ #include +#define USBUART_TIMER_FREQ_HZ 1000000U /* 1us per tick */ +#define USBUART_RUN_FREQ_HZ 5000U /* 200us (or 100 characters at 2Mbps) */ + +#define FIFO_SIZE 128 + +/* RX Fifo buffer */ +static uint8_t buf_rx[FIFO_SIZE]; +/* Fifo in pointer, writes assumed to be atomic, should be only incremented within RX ISR */ +static uint8_t buf_rx_in; +/* Fifo out pointer, writes assumed to be atomic, should be only incremented outside RX ISR */ +static uint8_t buf_rx_out; + +static void usbuart_run(void); + void usbuart_init(void) { #if defined(BLACKMAGIC) @@ -56,6 +71,62 @@ void usbuart_init(void) USBUSART_CR1 |= USART_CR1_RXNEIE; nvic_set_priority(USBUSART_IRQ, IRQ_PRI_USBUSART); nvic_enable_irq(USBUSART_IRQ); + + /* Setup timer for running deferred FIFO processing */ + USBUSART_TIM_CLK_EN(); + timer_reset(USBUSART_TIM); + timer_set_mode(USBUSART_TIM, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP); + timer_set_prescaler(USBUSART_TIM, rcc_ppre2_frequency/TIMER_FREQ_HZ*2 - 1); + timer_set_period(USBUSART_TIM, TIMER_FREQ_HZ/USBUART_RUN_FREQ_HZ - 1); + + /* Setup update interrupt in NVIC */ + nvic_set_priority(USBUSART_TIM_IRQ, IRQ_PRI_USBUSART_TIM); + nvic_enable_irq(USBUSART_TIM_IRQ); + + /* turn the timer on */ + timer_enable_counter(USBUSART_TIM); +} + +/* + * Runs deferred processing for usb uart rx, draining RX FIFO by sending characters to host PC via CDCACM. + * Allowed to read from FIFO in pointer, but not write to it. Allowed to write to FIFO out pointer. + */ +static void usbuart_run(void) +{ + /* forcibly empty fifo if no USB endpoint */ + if (cdcacm_get_config() != 1) + { + buf_rx_out = buf_rx_in; + } + + /* if fifo empty, nothing further to do */ + if (buf_rx_in == buf_rx_out) { + /* turn off LED, disable IRQ */ + timer_disable_irq(USBUSART_TIM, TIM_DIER_UIE); + gpio_clear(LED_PORT_UART, LED_UART); + } + else + { + uint8_t packet_buf[CDCACM_PACKET_SIZE]; + uint8_t packet_size = 0; + uint8_t buf_out = buf_rx_out; + + /* copy from uart FIFO into local usb packet buffer */ + while (buf_rx_in != buf_out && packet_size < CDCACM_PACKET_SIZE) + { + packet_buf[packet_size++] = buf_rx[buf_out++]; + + /* wrap out pointer */ + if (buf_out >= FIFO_SIZE) + { + buf_out = 0; + } + + } + + /* advance fifo out pointer by amount written */ + buf_rx_out = (buf_rx_out + usbd_ep_write_packet(usbdev, CDCACM_UART_ENDPOINT, packet_buf, packet_size)) % FIFO_SIZE; + } } void usbuart_set_line_coding(struct usb_cdc_line_coding *coding) @@ -108,41 +179,48 @@ void usbuart_usb_out_cb(usbd_device *dev, uint8_t ep) gpio_clear(LED_PORT_UART, LED_UART); } -static uint8_t uart_usb_buf[CDCACM_PACKET_SIZE]; -static uint8_t uart_usb_buf_size; void usbuart_usb_in_cb(usbd_device *dev, uint8_t ep) { - if (!uart_usb_buf_size) { - gpio_clear(LED_PORT_UART, LED_UART); - return; - } - - usbd_ep_write_packet(dev, ep, uart_usb_buf, uart_usb_buf_size); - uart_usb_buf_size = 0; + (void) dev; + (void) ep; } +/* + * Read a character from the UART RX and stuff it in a software FIFO. + * Allowed to read from FIFO out pointer, but not write to it. Allowed to write to FIFO in pointer. + */ void USBUSART_ISR(void) { char c = usart_recv(USBUSART); - /* Don't try to write until we are configured. - * Otherwise enumeration hanged in some cases. - */ - if (cdcacm_get_config() != 1) - return; - + /* Turn on LED */ gpio_set(LED_PORT_UART, LED_UART); - /* Try to send now */ - if (usbd_ep_write_packet(usbdev, CDCACM_UART_ENDPOINT, &c, 1) == 1) - return; - - /* We failed, so queue for later */ - if (uart_usb_buf_size == CDCACM_PACKET_SIZE) { - /* Drop if the buffer's full: we have no flow control */ - return; + /* If the next increment of rx_in would put it at the same point + * as rx_out, the FIFO is considered full. + */ + if (((buf_rx_in + 1) % FIFO_SIZE) != buf_rx_out) + { + /* insert into FIFO */ + buf_rx[buf_rx_in++] = c; + + /* wrap out pointer */ + if (buf_rx_in >= FIFO_SIZE) + { + buf_rx_in = 0; + } + + /* enable deferred processing if we put data in the FIFO */ + timer_enable_irq(USBUSART_TIM, TIM_DIER_UIE); } +} + +void USBUSART_TIM_ISR(void) +{ + /* need to clear timer update event */ + timer_clear_flag(USBUSART_TIM, TIM_SR_UIF); - uart_usb_buf[uart_usb_buf_size++] = c; + /* process FIFO */ + usbuart_run(); } diff --git a/src/platforms/swlink/platform.h b/src/platforms/swlink/platform.h index 469499f..c7eaca5 100644 --- a/src/platforms/swlink/platform.h +++ b/src/platforms/swlink/platform.h @@ -106,6 +106,7 @@ extern usbd_device *usbdev; */ #define IRQ_PRI_USB (2 << 4) #define IRQ_PRI_USBUSART (1 << 4) +#define IRQ_PRI_USBUSART_TIM (3 << 4) #define IRQ_PRI_USB_VBUS (14 << 4) #define IRQ_PRI_TRACE (0 << 4) @@ -117,6 +118,10 @@ extern usbd_device *usbdev; #define USBUSART_PORT GPIOB #define USBUSART_TX_PIN GPIO6 #define USBUSART_ISR usart1_isr +#define USBUSART_TIM TIM4 +#define USBUSART_TIM_CLK_EN() rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_TIM4EN) +#define USBUSART_TIM_IRQ NVIC_TIM4_IRQ +#define USBUSART_TIM_ISR tim4_isr #define TRACE_TIM TIM2 #define TRACE_TIM_CLK_EN() rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_TIM2EN) -- cgit v1.2.3 From e3f3171a33f12064b876b98b537f2c6347761f42 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sat, 27 Apr 2013 13:14:22 -0700 Subject: usbuart: Fix build error and clean up whitespace. --- src/platforms/stm32/usbuart.c | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/platforms/stm32/usbuart.c b/src/platforms/stm32/usbuart.c index 6694d90..7f5ebde 100644 --- a/src/platforms/stm32/usbuart.c +++ b/src/platforms/stm32/usbuart.c @@ -75,9 +75,12 @@ void usbuart_init(void) /* Setup timer for running deferred FIFO processing */ USBUSART_TIM_CLK_EN(); timer_reset(USBUSART_TIM); - timer_set_mode(USBUSART_TIM, TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP); - timer_set_prescaler(USBUSART_TIM, rcc_ppre2_frequency/TIMER_FREQ_HZ*2 - 1); - timer_set_period(USBUSART_TIM, TIMER_FREQ_HZ/USBUART_RUN_FREQ_HZ - 1); + timer_set_mode(USBUSART_TIM, TIM_CR1_CKD_CK_INT, + TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP); + timer_set_prescaler(USBUSART_TIM, + rcc_ppre2_frequency / USBUART_TIMER_FREQ_HZ * 2 - 1); + timer_set_period(USBUSART_TIM, + USBUART_TIMER_FREQ_HZ / USBUART_RUN_FREQ_HZ - 1); /* Setup update interrupt in NVIC */ nvic_set_priority(USBUSART_TIM_IRQ, IRQ_PRI_USBUSART_TIM); @@ -88,8 +91,9 @@ void usbuart_init(void) } /* - * Runs deferred processing for usb uart rx, draining RX FIFO by sending characters to host PC via CDCACM. - * Allowed to read from FIFO in pointer, but not write to it. Allowed to write to FIFO out pointer. + * Runs deferred processing for usb uart rx, draining RX FIFO by sending + * characters to host PC via CDCACM. Allowed to read from FIFO in pointer, + * but not write to it. Allowed to write to FIFO out pointer. */ static void usbuart_run(void) { @@ -125,7 +129,9 @@ static void usbuart_run(void) } /* advance fifo out pointer by amount written */ - buf_rx_out = (buf_rx_out + usbd_ep_write_packet(usbdev, CDCACM_UART_ENDPOINT, packet_buf, packet_size)) % FIFO_SIZE; + buf_rx_out += usbd_ep_write_packet(usbdev, + CDCACM_UART_ENDPOINT, packet_buf, packet_size); + buf_rx_out %= FIFO_SIZE; } } @@ -188,7 +194,8 @@ void usbuart_usb_in_cb(usbd_device *dev, uint8_t ep) /* * Read a character from the UART RX and stuff it in a software FIFO. - * Allowed to read from FIFO out pointer, but not write to it. Allowed to write to FIFO in pointer. + * Allowed to read from FIFO out pointer, but not write to it. + * Allowed to write to FIFO in pointer. */ void USBUSART_ISR(void) { @@ -224,3 +231,4 @@ void USBUSART_TIM_ISR(void) /* process FIFO */ usbuart_run(); } + -- cgit v1.2.3 From 56f44c39d9b97aed908128c43c6c08a4b3dfbf72 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sat, 27 Apr 2013 20:57:20 -0700 Subject: nxp: support the lpc1114dip28 by Rickta59 --- src/nxp_tgt.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/nxp_tgt.c b/src/nxp_tgt.c index a22eda8..f8ddf2a 100644 --- a/src/nxp_tgt.c +++ b/src/nxp_tgt.c @@ -98,6 +98,8 @@ lpc11xx_probe(struct target_s *target) case 0x0444102B: case 0x2540102B: case 0x1440102B: /* lpc1114 */ + case 0x0A40902B: + case 0x1A40902B: case 0x1431102B: /* lpc11c22 */ case 0x1430102B: /* lpc11c24 */ target->driver = "lpc11xx"; -- cgit v1.2.3 From 510d1c0dc845f860ff953168e3ae12528036070e Mon Sep 17 00:00:00 2001 From: Allen Ibara Date: Tue, 30 Apr 2013 09:42:01 -0700 Subject: Add support for burning flash on lpc4337. --- src/lpc43xx.c | 460 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 446 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/lpc43xx.c b/src/lpc43xx.c index ca1b351..fc843c6 100644 --- a/src/lpc43xx.c +++ b/src/lpc43xx.c @@ -17,12 +17,138 @@ * along with this program. If not, see . */ +#include +#include "command.h" #include "general.h" #include "adiv5.h" #include "target.h" #define LPC43XX_CHIPID 0x40043200 #define ARM_CPUID 0xE000ED00 +#define ARM_THUMB_BREAKPOINT 0xBE00 + +#define R_MSP 17 // Main stack pointer register number +#define R_PC 15 // Program counter register number +#define R_LR 14 // Link register number + +#define IAP_ENTRYPOINT_LOCATION 0x10400100 + +#define LPC43XX_ETBAHB_SRAM_BASE 0x2000C000 +#define LPC43XX_ETBAHB_SRAM_SIZE (16*1024) + +#define IAP_RAM_SIZE LPC43XX_ETBAHB_SRAM_SIZE +#define IAP_RAM_BASE LPC43XX_ETBAHB_SRAM_BASE + +#define IAP_PGM_CHUNKSIZE 4096 + +#define IAP_CMD_INIT 49 +#define IAP_CMD_PREPARE 50 +#define IAP_CMD_PROGRAM 51 +#define IAP_CMD_ERASE 52 +#define IAP_CMD_BLANKCHECK 53 +#define IAP_CMD_SET_ACTIVE_BANK 60 + +#define IAP_STATUS_CMD_SUCCESS 0 +#define IAP_STATUS_INVALID_COMMAND 1 +#define IAP_STATUS_SRC_ADDR_ERROR 2 +#define IAP_STATUS_DST_ADDR_ERROR 3 +#define IAP_STATUS_SRC_ADDR_NOT_MAPPED 4 +#define IAP_STATUS_DST_ADDR_NOT_MAPPED 5 +#define IAP_STATUS_COUNT_ERROR 6 +#define IAP_STATUS_INVALID_SECTOR 7 +#define IAP_STATUS_SECTOR_NOT_BLANK 8 +#define IAP_STATUS_SECTOR_NOT_PREPARED 9 +#define IAP_STATUS_COMPARE_ERROR 10 +#define IAP_STATUS_BUSY 11 + +#define FLASH_BANK_A_BASE 0x1A000000 +#define FLASH_BANK_A_SIZE 0x80000 +#define FLASH_BANK_B_BASE 0x1B000000 +#define FLASH_BANK_B_SIZE 0x80000 +#define FLASH_NUM_BANK 2 +#define FLASH_NUM_SECTOR 15 +#define FLASH_LARGE_SECTOR_OFFSET 0x00010000 + +/* CPU Frequency */ +#define CPU_CLK_KHZ 12000 + +struct flash_param { + uint16_t opcode; /* opcode to return to after calling the ROM */ + uint16_t pad0; + uint32_t command; /* IAP command */ + union { + uint32_t words[5]; /* command parameters */ + struct { + uint32_t start_sector; + uint32_t end_sector; + uint32_t flash_bank; + } prepare; + struct { + uint32_t start_sector; + uint32_t end_sector; + uint32_t cpu_clk_khz; + uint32_t flash_bank; + } erase; + struct { + uint32_t dest; + uint32_t source; + uint32_t byte_count; + uint32_t cpu_clk_khz; + } program; + struct { + uint32_t start_sector; + uint32_t end_sector; + uint32_t flash_bank; + } blank_check; + struct { + uint32_t flash_bank; + uint32_t cpu_clk_khz; + } make_active; + } params; + uint32_t result[5]; /* result data */ +}; + +struct flash_program { + struct flash_param p; + uint8_t data[IAP_PGM_CHUNKSIZE]; +}; + +static bool lpc43xx_cmd_erase(target *t); +static int lpc43xx_flash_init(struct target_s *target); +static void lpc43xx_iap_call(struct target_s *target, struct flash_param *param, unsigned param_len); +static int lpc43xx_flash_prepare(struct target_s *target, uint32_t addr, int len); +static int lpc43xx_flash_erase(struct target_s *target, uint32_t addr, int len); +static int lpc43xx_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, int len); + +const struct command_s lpc43xx_cmd_list[] = { + {"erase_mass", (cmd_handler)lpc43xx_cmd_erase, "Erase entire flash memory"}, + {NULL, NULL, NULL} +}; + +/* blocksize is the erasure block size */ +static const char lpc4337_xml_memory_map[] = "" +/* + "" +*/ +"" +" " +" " +" 0x2000" +" " +" " +" 0x10000" +" " +" " +" " +" 0x2000" +" " +" " +" 0x10000" +" " +" " +""; bool lpc43xx_probe(struct target_s *target) { @@ -32,22 +158,328 @@ bool lpc43xx_probe(struct target_s *target) cpuid = adiv5_ap_mem_read(adiv5_target_ap(target), ARM_CPUID); switch(chipid) { - case 0x4906002B: /* Parts with on-chip flash */ - case 0x5906002B: /* Flashless parts */ - case 0x6906002B: - switch (cpuid & 0xFF00FFF0) { - case 0x4100C240: - target->driver = "LPC43xx Cortex-M4"; - break; - case 0x4100C200: - target->driver = "LPC43xx Cortex-M0"; - break; - default: - target->driver = "LPC43xx "; - } - return true; + case 0x4906002B: /* Parts with on-chip flash */ + switch (cpuid & 0xFF00FFF0) { + case 0x4100C240: + target->driver = "LPC43xx Cortex-M4"; + if (cpuid == 0x410FC241) + { + /* LPC4337 */ + target->xml_mem_map = lpc4337_xml_memory_map; + target->flash_erase = lpc43xx_flash_erase; + target->flash_write = lpc43xx_flash_write; + target_add_commands(target, lpc43xx_cmd_list, "LPC43xx"); + } + break; + case 0x4100C200: + target->driver = "LPC43xx Cortex-M0"; + break; + default: + target->driver = "LPC43xx "; + } + return true; + case 0x5906002B: /* Flashless parts */ + case 0x6906002B: + switch (cpuid & 0xFF00FFF0) { + case 0x4100C240: + target->driver = "LPC43xx Cortex-M4"; + break; + case 0x4100C200: + target->driver = "LPC43xx Cortex-M0"; + break; + default: + target->driver = "LPC43xx "; + } + return true; } return false; } +static bool lpc43xx_cmd_erase(target *target) +{ + uint32_t bank = 0; + struct flash_program flash_pgm; + + lpc43xx_flash_init(target); + + for (bank = 0; bank < FLASH_NUM_BANK; bank++) + { + flash_pgm.p.command = IAP_CMD_PREPARE; + flash_pgm.p.params.prepare.start_sector = 0; + flash_pgm.p.params.prepare.end_sector = FLASH_NUM_SECTOR-1; + flash_pgm.p.params.prepare.flash_bank = bank; + flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS; + lpc43xx_iap_call(target, &flash_pgm.p, sizeof(flash_pgm.p)); + if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { + return false; + } + + flash_pgm.p.command = IAP_CMD_ERASE; + flash_pgm.p.params.erase.start_sector = 0; + flash_pgm.p.params.prepare.end_sector = FLASH_NUM_SECTOR-1; + flash_pgm.p.params.erase.cpu_clk_khz = CPU_CLK_KHZ; + flash_pgm.p.params.erase.flash_bank = bank; + flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS; + lpc43xx_iap_call(target, &flash_pgm.p, sizeof(flash_pgm.p)); + if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) + { + return false; + } + } + + gdb_outf("Erase OK.\n"); + + return true; +} + +static int lpc43xx_flash_init(struct target_s *target) +{ + struct flash_program flash_pgm; + + /* Initialize flash IAP */ + flash_pgm.p.command = IAP_CMD_INIT; + flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS; + lpc43xx_iap_call(target, &flash_pgm.p, sizeof(flash_pgm.p)); + if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) + { + return -1; + } + + return 0; +} + + + +/** + * @brief find a sector number given linear offset + */ +static int32_t flash_bank(uint32_t addr) +{ + int32_t retVal; + + if (addr >= FLASH_BANK_A_BASE && addr < (FLASH_BANK_A_BASE+FLASH_BANK_A_SIZE)) + { + retVal = 0; + } + else if (addr >= FLASH_BANK_B_BASE && addr < (FLASH_BANK_B_BASE+FLASH_BANK_B_SIZE)) + { + retVal = 1; + } + else + { + retVal = -1; + } + + return retVal; +} + +/** + * @brief find a sector number given linear offset + */ +static int32_t sector_number(uint32_t addr) +{ + int32_t retVal = 0; + int32_t bank = flash_bank(addr); + + if (bank == 0) + { + addr = addr - FLASH_BANK_A_BASE; + } + else if (bank == 1) + { + addr = addr - FLASH_BANK_B_BASE; + } + else + { + retVal = -1; + } + + if (retVal != -1) + { + /* from 47.5 "Sector numbers" (page 1218) UM10503.pdf (Rev 1.6) */ + if (addr < FLASH_LARGE_SECTOR_OFFSET) + { + retVal = addr >> 13; + } + else + { + retVal = 8 + ((addr - FLASH_LARGE_SECTOR_OFFSET) >> 16); + } + } + + return retVal; +} + +static void lpc43xx_iap_call(struct target_s *target, struct flash_param *param, unsigned param_len) +{ + uint32_t regs[target->regs_size]; + uint32_t iap_entry; + + target_mem_read_words(target, &iap_entry, IAP_ENTRYPOINT_LOCATION, sizeof(iap_entry)); + + /* fill out the remainder of the parameters and copy the structure to RAM */ + param->opcode = ARM_THUMB_BREAKPOINT; /* breakpoint */ + param->pad0 = 0x0000; /* pad */ + target_mem_write_words(target, IAP_RAM_BASE, (void *)param, param_len); + + /* set up for the call to the IAP ROM */ + target_regs_read(target, regs); + regs[0] = IAP_RAM_BASE + offsetof(struct flash_param, command); + regs[1] = IAP_RAM_BASE + offsetof(struct flash_param, result); + + regs[R_MSP] = IAP_RAM_BASE + IAP_RAM_SIZE; + regs[R_LR] = IAP_RAM_BASE | 1; + regs[R_PC] = iap_entry; + target_regs_write(target, regs); + + /* start the target and wait for it to halt again */ + target_halt_resume(target, 0); + while (!target_halt_wait(target)); + + /* copy back just the parameters structure */ + target_mem_read_words(target, (void *)param, IAP_RAM_BASE, sizeof(struct flash_param)); +} + +static int lpc43xx_flash_prepare(struct target_s *target, uint32_t addr, int len) +{ + struct flash_program flash_pgm; + + /* prepare the sector(s) to be erased */ + flash_pgm.p.command = IAP_CMD_PREPARE; + flash_pgm.p.params.prepare.start_sector = sector_number(addr); + flash_pgm.p.params.prepare.end_sector = sector_number(addr+len); + flash_pgm.p.params.prepare.flash_bank = flash_bank(addr); + flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS; + + lpc43xx_iap_call(target, &flash_pgm.p, sizeof(flash_pgm.p)); + if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { + return -1; + } + + return 0; +} + + static int +lpc43xx_flash_erase(struct target_s *target, uint32_t addr, int len) +{ + struct flash_program flash_pgm; + + /* min block size */ + if (addr % 8192) + { + return -1; + } + + /* init */ + if (lpc43xx_flash_init(target)) + { + return -1; + } + + /* prepare... */ + if (lpc43xx_flash_prepare(target, addr, len)) + { + return -1; + } + + /* and now erase them */ + flash_pgm.p.command = IAP_CMD_ERASE; + flash_pgm.p.params.erase.start_sector = sector_number(addr); + flash_pgm.p.params.erase.end_sector = sector_number(addr+len); + flash_pgm.p.params.erase.cpu_clk_khz = CPU_CLK_KHZ; + flash_pgm.p.params.erase.flash_bank = flash_bank(addr); + flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS; + lpc43xx_iap_call(target, &flash_pgm.p, sizeof(flash_pgm.p)); + if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { + return -1; + } + + /* check erase ok */ + flash_pgm.p.command = IAP_CMD_BLANKCHECK; + flash_pgm.p.params.blank_check.start_sector = sector_number(addr); + flash_pgm.p.params.blank_check.end_sector = sector_number(addr+len); + flash_pgm.p.params.blank_check.flash_bank = flash_bank(addr); + flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS; + lpc43xx_iap_call(target, &flash_pgm.p, sizeof(flash_pgm.p)); + if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { + return -1; + } + + return 0; +} + +static int lpc43xx_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, int len) +{ + unsigned first_chunk = dest / IAP_PGM_CHUNKSIZE; + unsigned last_chunk = (dest + len - 1) / IAP_PGM_CHUNKSIZE; + unsigned chunk_offset = dest % IAP_PGM_CHUNKSIZE; + unsigned chunk; + struct flash_program flash_pgm; + + for (chunk = first_chunk; chunk <= last_chunk; chunk++) + { + + /* first and last chunk may require special handling */ + if ((chunk == first_chunk) || (chunk == last_chunk)) { + + /* fill with all ff to avoid sector rewrite corrupting other writes */ + memset(flash_pgm.data, 0xff, sizeof(flash_pgm.data)); + + /* copy as much as fits */ + int copylen = IAP_PGM_CHUNKSIZE - chunk_offset; + if (copylen > len) + copylen = len; + + memcpy(flash_pgm.data + chunk_offset, src, copylen); + + /* update to suit */ + len -= copylen; + src += copylen; + chunk_offset = 0; + } else { + + /* interior chunk, must be aligned and full-sized */ + memcpy(flash_pgm.data, src, IAP_PGM_CHUNKSIZE); + len -= IAP_PGM_CHUNKSIZE; + src += IAP_PGM_CHUNKSIZE; + } + + /* prepare... */ + if (lpc43xx_flash_prepare(target, chunk * IAP_PGM_CHUNKSIZE, IAP_PGM_CHUNKSIZE)) + { + return -1; + } + + /* copy buffer into target memory */ + target_mem_write_words(target, IAP_RAM_BASE + offsetof(struct flash_program, data), flash_pgm.data, sizeof(flash_pgm.data)); + + /* set the destination address and program */ + flash_pgm.p.command = IAP_CMD_PROGRAM; + flash_pgm.p.params.program.dest = chunk * IAP_PGM_CHUNKSIZE; + flash_pgm.p.params.program.source = IAP_RAM_BASE + offsetof(struct flash_program, data); + flash_pgm.p.params.program.byte_count = IAP_PGM_CHUNKSIZE; + flash_pgm.p.params.program.cpu_clk_khz = CPU_CLK_KHZ; + flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS; + lpc43xx_iap_call(target, &flash_pgm.p, sizeof(flash_pgm)); + if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { + return -1; + } + + /* special command to compute/write magic vector for signature */ + if (chunk == first_chunk) + { + flash_pgm.p.command = IAP_CMD_SET_ACTIVE_BANK; + flash_pgm.p.params.make_active.flash_bank = flash_bank(dest); + flash_pgm.p.params.make_active.cpu_clk_khz = CPU_CLK_KHZ; + flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS; + lpc43xx_iap_call(target, &flash_pgm.p, sizeof(flash_pgm)); + if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { + return -1; + } + } + + } + + return 0; +} -- cgit v1.2.3 From e0fc21a2a715893331f49d9d838bc0d4a69cf84c Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Sun, 5 May 2013 00:46:47 +0400 Subject: adiv5_swdp: allow to connect to a sleeping target by pulling SRST This patch introduces a new command, "connect_srst [enable|disable]" which allows to enable special mode in which SRST would be pulled low before the SWD scan till attaching to a target. Since on Cortex-Mx the SRST signal doesn't gate JTAG and SWD, it's possible to connect to a target while holding reset, ask it to stop at reset vector and only then deassert reset, thus allowing to attach to the kind of firmware that goes immediately to sleep or disables debugging by other means early on start. Tested on an STM32VLDiscovery board with STM32F100 configured to go to STOP mode and executing WFI in the very beginning of main(). Signed-off-by: Paul Fertser --- src/adiv5_swdp.c | 3 +++ src/command.c | 13 +++++++++++++ src/cortexm.c | 8 ++++++-- src/include/jtagtap.h | 2 +- src/include/target.h | 1 + src/platforms/libftdi/jtagtap.c | 2 +- src/platforms/stm32/jtagtap.c | 15 +++++++++------ src/target.c | 1 + 8 files changed, 35 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/adiv5_swdp.c b/src/adiv5_swdp.c index 06d5446..669bf42 100644 --- a/src/adiv5_swdp.c +++ b/src/adiv5_swdp.c @@ -27,6 +27,7 @@ #include "adiv5.h" #include "swdptap.h" +#include "jtagtap.h" #include "command.h" @@ -53,6 +54,8 @@ int adiv5_swdp_scan(void) ADIv5_DP_t *dp = (void*)calloc(1, sizeof(*dp)); swdptap_init(); + if(connect_assert_srst) + jtagtap_srst(true); /* will be deasserted after attach */ /* Read the SW-DP IDCODE register to syncronise */ /* This could be done with adiv_swdp_low_access(), but this doesn't * allow the ack to be checked here. */ diff --git a/src/command.c b/src/command.c index e1ed837..e9f7096 100644 --- a/src/command.c +++ b/src/command.c @@ -46,6 +46,7 @@ static bool cmd_jtag_scan(target *t, int argc, char **argv); static bool cmd_swdp_scan(void); static bool cmd_targets(target *t); static bool cmd_morse(void); +static bool cmd_connect_srst(target *t, int argc, const char **argv); #ifdef PLATFORM_HAS_TRACESWO static bool cmd_traceswo(void); #endif @@ -57,6 +58,7 @@ const struct command_s cmd_list[] = { {"swdp_scan", (cmd_handler)cmd_swdp_scan, "Scan SW-DP for devices" }, {"targets", (cmd_handler)cmd_targets, "Display list of available targets" }, {"morse", (cmd_handler)cmd_morse, "Display morse error message" }, + {"connect_srst", (cmd_handler)cmd_connect_srst, "Configure connect under SRST: (enable|disable)" }, #ifdef PLATFORM_HAS_TRACESWO {"traceswo", (cmd_handler)cmd_traceswo, "Start trace capture" }, #endif @@ -209,6 +211,17 @@ bool cmd_morse(void) return true; } +static bool cmd_connect_srst(target *t, int argc, const char **argv) +{ + (void)t; + if (argc == 1) + gdb_outf("Assert SRST during connect: %s\n", + connect_assert_srst ? "enabled" : "disabled"); + else + connect_assert_srst = !strcmp(argv[1], "enable"); + return true; +} + #ifdef PLATFORM_HAS_TRACESWO static bool cmd_traceswo(void) { diff --git a/src/cortexm.c b/src/cortexm.c index 9ec96d6..36319ee 100644 --- a/src/cortexm.c +++ b/src/cortexm.c @@ -385,7 +385,7 @@ cortexm_attach(struct target_s *target) target_halt_request(target); tries = 10; - while(!target_halt_wait(target) && --tries) + while(!connect_assert_srst && !target_halt_wait(target) && --tries) platform_delay(2); if(!tries) return false; @@ -429,6 +429,9 @@ cortexm_attach(struct target_s *target) target->clear_hw_wp = cortexm_clear_hw_wp; target->check_hw_wp = cortexm_check_hw_wp; + if(connect_assert_srst) + jtagtap_srst(false); + return true; } @@ -546,7 +549,8 @@ cortexm_reset(struct target_s *target) { ADIv5_AP_t *ap = adiv5_target_ap(target); - jtagtap_srst(); + jtagtap_srst(true); + jtagtap_srst(false); /* Read DHCSR here to clear S_RESET_ST bit before reset */ adiv5_ap_mem_read(ap, CORTEXM_DHCSR); diff --git a/src/include/jtagtap.h b/src/include/jtagtap.h index 9fe3e0d..f0588a0 100644 --- a/src/include/jtagtap.h +++ b/src/include/jtagtap.h @@ -29,7 +29,7 @@ int jtagtap_init(void); void jtagtap_reset(void); -void jtagtap_srst(void); +void jtagtap_srst(bool assert); uint8_t jtagtap_next(const uint8_t TMS, const uint8_t TDI); /* tap_next executes one state transision in the JTAG TAP state machine: diff --git a/src/include/target.h b/src/include/target.h index 31501f6..cd3079c 100644 --- a/src/include/target.h +++ b/src/include/target.h @@ -188,6 +188,7 @@ struct target_command_s { }; extern target *target_list; +extern bool connect_assert_srst; target *target_new(unsigned size); void target_list_free(void); diff --git a/src/platforms/libftdi/jtagtap.c b/src/platforms/libftdi/jtagtap.c index c914646..77e1867 100644 --- a/src/platforms/libftdi/jtagtap.c +++ b/src/platforms/libftdi/jtagtap.c @@ -67,7 +67,7 @@ void jtagtap_reset(void) jtagtap_soft_reset(); } -void jtagtap_srst(void) +void jtagtap_srst(bool assert) { platform_buffer_flush(); //ftdi_write_data(ftdic, "\x80\x88\xAB", 3); diff --git a/src/platforms/stm32/jtagtap.c b/src/platforms/stm32/jtagtap.c index d6e298b..78dd300 100644 --- a/src/platforms/stm32/jtagtap.c +++ b/src/platforms/stm32/jtagtap.c @@ -50,13 +50,16 @@ void jtagtap_reset(void) jtagtap_soft_reset(); } -void jtagtap_srst(void) +void jtagtap_srst(bool assert) { -#ifdef SRST_PORT - volatile int i; - gpio_set(SRST_PORT, SRST_PIN); - for(i = 0; i < 10000; i++) asm("nop"); - gpio_clear(SRST_PORT, SRST_PIN); + (void)assert; +#ifdef SRST_SET_VAL + SRST_SET_VAL(assert); + if(assert) { + int i; + for(i = 0; i < 10000; i++) + asm volatile("nop"); + } #endif } diff --git a/src/target.c b/src/target.c index b46f9e3..2a68f23 100644 --- a/src/target.c +++ b/src/target.c @@ -24,6 +24,7 @@ #include target *target_list = NULL; +bool connect_assert_srst; target *target_new(unsigned size) { -- cgit v1.2.3 From cdaed128c1f2a53c195d3958427122296b37a570 Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Sun, 5 May 2013 00:46:48 +0400 Subject: stlink: add support for SRST handling This enables SRST signals in open drain mode for both stlinkv1 and stlinkv2 hardware platforms. Signed-off-by: Paul Fertser --- src/platforms/stlink/platform.c | 15 +++++++++++++++ src/platforms/stlink/platform.h | 8 ++++++++ 2 files changed, 23 insertions(+) (limited to 'src') diff --git a/src/platforms/stlink/platform.c b/src/platforms/stlink/platform.c index e8435b9..08fcd32 100644 --- a/src/platforms/stlink/platform.c +++ b/src/platforms/stlink/platform.c @@ -98,6 +98,11 @@ int platform_init(void) GPIO_CNF_OUTPUT_PUSHPULL, TCK_PIN); gpio_set_mode(TDI_PORT, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, TDI_PIN); + uint16_t srst_pin = platform_hwversion() == 0 ? + SRST_PIN_V1 : SRST_PIN_V2; + gpio_set(SRST_PORT, srst_pin); + gpio_set_mode(SRST_PORT, GPIO_MODE_OUTPUT_50_MHZ, + GPIO_CNF_OUTPUT_OPENDRAIN, srst_pin); gpio_set_mode(LED_PORT, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, led_idle_run); @@ -127,6 +132,16 @@ void platform_delay(uint32_t delay) while(timeout_counter); } +void platform_srst_set_val(bool assert) +{ + uint16_t pin; + pin = platform_hwversion() == 0 ? SRST_PIN_V1 : SRST_PIN_V2; + if (assert) + gpio_clear(SRST_PORT, pin); + else + gpio_set(SRST_PORT, pin); +} + void sys_tick_handler(void) { if(running_status) diff --git a/src/platforms/stlink/platform.h b/src/platforms/stlink/platform.h index cbfc0ba..1ee944c 100644 --- a/src/platforms/stlink/platform.h +++ b/src/platforms/stlink/platform.h @@ -79,6 +79,10 @@ extern usbd_device *usbdev; #define SWDIO_PIN TMS_PIN #define SWCLK_PIN TCK_PIN +#define SRST_PORT GPIOB +#define SRST_PIN_V1 GPIO1 +#define SRST_PIN_V2 GPIO0 + #define LED_PORT GPIOA /* Use PC14 for a "dummy" uart led. So we can observere at least with scope*/ #define LED_PORT_UART GPIOC @@ -98,6 +102,9 @@ extern usbd_device *usbdev; gpio_set_mode(USBUSART_PORT, GPIO_MODE_OUTPUT_2_MHZ, \ GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, USBUSART_TX_PIN); +#define SRST_SET_VAL(x) \ + platform_srst_set_val(x) + #define USB_DRIVER stm32f103_usb_driver #define USB_IRQ NVIC_USB_LP_CAN_RX0_IRQ #define USB_ISR usb_lp_can_rx0_isr @@ -152,6 +159,7 @@ int platform_init(void); void morse(const char *msg, char repeat); const char *platform_target_voltage(void); void platform_delay(uint32_t delay); +void platform_srst_set_val(bool assert); /* */ void cdcacm_init(void); -- cgit v1.2.3 From feaf62667388ed0bb5e4d87ad4be58442a53e7ce Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sat, 18 May 2013 15:32:06 +1200 Subject: Add support for Atmel SAM3N devices. --- src/sam3x.c | 142 ++++++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 90 insertions(+), 52 deletions(-) (limited to 'src') diff --git a/src/sam3x.c b/src/sam3x.c index d348701..3c5cc2e 100644 --- a/src/sam3x.c +++ b/src/sam3x.c @@ -38,8 +38,6 @@ static int sam3x_flash_write(struct target_s *target, uint32_t dest, static bool sam3x_cmd_gpnvm_get(target *t); static bool sam3x_cmd_gpnvm_set(target *t, int argc, char *argv[]); -static const char sam3x_driver_str[] = "Atmel SAM3X"; - const struct command_s sam3x_cmd_list[] = { {"gpnvm_get", (cmd_handler)sam3x_cmd_gpnvm_get, "Get GPVNM value"}, {"gpnvm_set", (cmd_handler)sam3x_cmd_gpnvm_set, "Set GPVNM bit"}, @@ -58,13 +56,25 @@ static const char sam3x_xml_memory_map[] = "" " " ""; +static const char sam3n_xml_memory_map[] = "" +/* ""*/ + "" + " " + " 0x100" + " " + " " + " " + ""; /* Enhanced Embedded Flash Controller (EEFC) Register Map */ -#define EEFC_BASE(x) (0x400E0A00+((x)*0x400)) -#define EEFC_FMR(x) (EEFC_BASE(x)+0x00) -#define EEFC_FCR(x) (EEFC_BASE(x)+0x04) -#define EEFC_FSR(x) (EEFC_BASE(x)+0x08) -#define EEFC_FRR(x) (EEFC_BASE(x)+0x0C) +#define SAM3N_EEFC_BASE 0x400E0A00 +#define SAM3X_EEFC_BASE(x) (0x400E0A00+((x)*0x400)) +#define EEFC_FMR(base) ((base)+0x00) +#define EEFC_FCR(base) ((base)+0x04) +#define EEFC_FSR(base) ((base)+0x08) +#define EEFC_FRR(base) ((base)+0x0C) #define EEFC_FCR_FKEY (0x5A << 24) #define EEFC_FCR_FCMD_GETD 0x00 @@ -87,7 +97,8 @@ static const char sam3x_xml_memory_map[] = "" #define EEFC_FSR_FLOCKE (1 << 2) #define EEFC_FSR_ERROR (EEFC_FSR_FCMDE | EEFC_FSR_FLOCKE) -#define CHIPID_CIDR 0x400E0940 +#define SAM3X_CHIPID_CIDR 0x400E0940 +#define SAM3N_CHIPID_CIDR 0x400E0740 #define CHIPID_CIDR_VERSION_MASK (0x1F << 0) #define CHIPID_CIDR_EPROC_CM3 (0x03 << 5) @@ -102,6 +113,9 @@ static const char sam3x_xml_memory_map[] = "" #define CHIPID_CIDR_ARCH_SAM3XxC (0x84 << 20) #define CHIPID_CIDR_ARCH_SAM3XxE (0x85 << 20) #define CHIPID_CIDR_ARCH_SAM3XxG (0x86 << 20) +#define CHIPID_CIDR_ARCH_SAM3NxA (0x93 << 20) +#define CHIPID_CIDR_ARCH_SAM3NxB (0x94 << 20) +#define CHIPID_CIDR_ARCH_SAM3NxC (0x95 << 20) #define CHIPID_CIDR_NVPTYP_MASK (0x07 << 28) #define CHIPID_CIDR_NVPTYP_FLASH (0x02 << 28) #define CHIPID_CIDR_NVPTYP_ROM_FLASH (0x03 << 28) @@ -113,70 +127,92 @@ bool sam3x_probe(struct target_s *target) { ADIv5_AP_t *ap = adiv5_target_ap(target); - target->idcode = adiv5_ap_mem_read(ap, CHIPID_CIDR); + target->idcode = adiv5_ap_mem_read(ap, SAM3X_CHIPID_CIDR); /* FIXME: Check for all variants with similar flash interface */ switch (target->idcode & (CHIPID_CIDR_ARCH_MASK | CHIPID_CIDR_EPROC_MASK)) { case CHIPID_CIDR_ARCH_SAM3XxC | CHIPID_CIDR_EPROC_CM3: case CHIPID_CIDR_ARCH_SAM3XxE | CHIPID_CIDR_EPROC_CM3: case CHIPID_CIDR_ARCH_SAM3XxG | CHIPID_CIDR_EPROC_CM3: - target->driver = sam3x_driver_str; + target->driver = "Atmel SAM3X"; target->xml_mem_map = sam3x_xml_memory_map; target->flash_erase = sam3x_flash_erase; target->flash_write = sam3x_flash_write; - target_add_commands(target, sam3x_cmd_list, sam3x_driver_str); + target_add_commands(target, sam3x_cmd_list, "SAM3X"); + return true; + } + + target->idcode = adiv5_ap_mem_read(ap, SAM3N_CHIPID_CIDR); + switch (target->idcode & (CHIPID_CIDR_ARCH_MASK | CHIPID_CIDR_EPROC_MASK)) { + case CHIPID_CIDR_ARCH_SAM3NxA | CHIPID_CIDR_EPROC_CM3: + case CHIPID_CIDR_ARCH_SAM3NxB | CHIPID_CIDR_EPROC_CM3: + case CHIPID_CIDR_ARCH_SAM3NxC | CHIPID_CIDR_EPROC_CM3: + target->driver = "Atmel SAM3N"; + target->xml_mem_map = sam3n_xml_memory_map; + target->flash_erase = sam3x_flash_erase; + target->flash_write = sam3x_flash_write; + target_add_commands(target, sam3x_cmd_list, "SAM3N"); return true; } + return false; } static int -sam3x_flash_cmd(struct target_s *target, int bank, uint8_t cmd, uint16_t arg) +sam3x_flash_cmd(struct target_s *target, uint32_t base, uint8_t cmd, uint16_t arg) { ADIv5_AP_t *ap = adiv5_target_ap(target); - adiv5_ap_mem_write(ap, EEFC_FCR(bank), + DEBUG("%s: base = 0x%08x cmd = 0x%02X, arg = 0x%06X\n", + __func__, base, cmd, arg); + adiv5_ap_mem_write(ap, EEFC_FCR(base), EEFC_FCR_FKEY | cmd | ((uint32_t)arg << 8)); - while(!(adiv5_ap_mem_read(ap, EEFC_FSR(bank)) & EEFC_FSR_FRDY)) - if(target_check_error(target)) + while(!(adiv5_ap_mem_read(ap, EEFC_FSR(base)) & EEFC_FSR_FRDY)) + if(target_check_error(target)) return -1; - uint32_t sr = adiv5_ap_mem_read(ap, EEFC_FSR(bank)); + uint32_t sr = adiv5_ap_mem_read(ap, EEFC_FSR(base)); return sr & EEFC_FSR_ERROR; } -static int -sam3x_flash_bank(struct target_s *target, uint32_t addr, uint32_t *offset) +static uint32_t +sam3x_flash_base(struct target_s *target, uint32_t addr, uint32_t *offset) { - uint32_t half = -1; - switch (target->idcode & CHIPID_CIDR_NVPSIZ_MASK) { - case CHIPID_CIDR_NVPSIZ_128K: - half = 0x00090000; - break; - case CHIPID_CIDR_NVPSIZ_256K: - half = 0x000A0000; - break; - case CHIPID_CIDR_NVPSIZ_512K: - half = 0x000C0000; - break; - } - - if (addr > half) { - if (offset) - *offset = addr - half; - return 1; + if (strcmp(target->driver, "Atmel SAM3X") == 0) { + uint32_t half = -1; + switch (target->idcode & CHIPID_CIDR_NVPSIZ_MASK) { + case CHIPID_CIDR_NVPSIZ_128K: + half = 0x00090000; + break; + case CHIPID_CIDR_NVPSIZ_256K: + half = 0x000A0000; + break; + case CHIPID_CIDR_NVPSIZ_512K: + half = 0x000C0000; + break; + } + if (addr > half) { + if (offset) + *offset = addr - half; + return SAM3X_EEFC_BASE(1); + } else { + if (offset) + *offset = addr - 0x80000; + return SAM3X_EEFC_BASE(0); + } } + /* SAM3N device */ if (offset) - *offset = addr - 0x80000; - return 0; + *offset = addr - 0x400000; + return SAM3N_EEFC_BASE; } static int sam3x_flash_erase(struct target_s *target, uint32_t addr, int len) { uint32_t offset; - uint8_t bank = sam3x_flash_bank(target, addr, &offset); + uint32_t base = sam3x_flash_base(target, addr, &offset); unsigned chunk = offset / PAGE_SIZE; uint8_t buf[PAGE_SIZE]; @@ -187,10 +223,10 @@ static int sam3x_flash_erase(struct target_s *target, uint32_t addr, int len) memset(buf, 0xff, sizeof(buf)); /* Only do this once, since it doesn't change. */ - target_mem_write_words(target, addr, (void*)buf, PAGE_SIZE); + target_mem_write_words(target, addr, (void*)buf, PAGE_SIZE); while (len) { - if(sam3x_flash_cmd(target, bank, EEFC_FCR_FCMD_EWP, chunk)) + if(sam3x_flash_cmd(target, base, EEFC_FCR_FCMD_EWP, chunk)) return -1; len -= PAGE_SIZE; @@ -201,11 +237,11 @@ static int sam3x_flash_erase(struct target_s *target, uint32_t addr, int len) return 0; } -static int sam3x_flash_write(struct target_s *target, uint32_t dest, +static int sam3x_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, int len) { uint32_t offset; - uint8_t bank = sam3x_flash_bank(target, dest, &offset); + uint32_t base = sam3x_flash_base(target, dest, &offset); uint8_t buf[PAGE_SIZE]; unsigned first_chunk = offset / PAGE_SIZE; unsigned last_chunk = (offset + len - 1) / PAGE_SIZE; @@ -213,15 +249,15 @@ static int sam3x_flash_write(struct target_s *target, uint32_t dest, dest -= offset; for (unsigned chunk = first_chunk; chunk <= last_chunk; chunk++) { - + DEBUG("chunk %u len %d\n", chunk, len); /* first and last chunk may require special handling */ if ((chunk == first_chunk) || (chunk == last_chunk)) { /* fill with all ff to avoid sector rewrite corrupting other writes */ memset(buf, 0xff, sizeof(buf)); - - /* copy as much as fits */ + + /* copy as much as fits */ int copylen = PAGE_SIZE - offset; if (copylen > len) copylen = len; @@ -239,8 +275,8 @@ static int sam3x_flash_write(struct target_s *target, uint32_t dest, src += PAGE_SIZE; } - target_mem_write_words(target, dest, (void*)buf, PAGE_SIZE); - if(sam3x_flash_cmd(target, bank, EEFC_FCR_FCMD_WP, chunk)) + target_mem_write_words(target, dest, (void*)buf, PAGE_SIZE); + if(sam3x_flash_cmd(target, base, EEFC_FCR_FCMD_WP, chunk)) return -1; } @@ -250,9 +286,10 @@ static int sam3x_flash_write(struct target_s *target, uint32_t dest, static bool sam3x_cmd_gpnvm_get(target *t) { ADIv5_AP_t *ap = adiv5_target_ap(t); - - sam3x_flash_cmd(t, 0, EEFC_FCR_FCMD_GGPB, 0); - gdb_outf("GPNVM: 0x%08X\n", adiv5_ap_mem_read(ap, EEFC_FRR(0))); + uint32_t base = sam3x_flash_base(t, 0, NULL); + + sam3x_flash_cmd(t, base, EEFC_FCR_FCMD_GGPB, 0); + gdb_outf("GPNVM: 0x%08X\n", adiv5_ap_mem_read(ap, EEFC_FRR(base))); return true; } @@ -260,7 +297,8 @@ static bool sam3x_cmd_gpnvm_get(target *t) static bool sam3x_cmd_gpnvm_set(target *t, int argc, char *argv[]) { uint32_t bit, cmd; - + uint32_t base = sam3x_flash_base(t, 0, NULL); + if (argc != 3) { gdb_out("usage: monitor gpnvm_set \n"); return false; @@ -268,7 +306,7 @@ static bool sam3x_cmd_gpnvm_set(target *t, int argc, char *argv[]) bit = atol(argv[1]); cmd = atol(argv[2]) ? EEFC_FCR_FCMD_SGPB : EEFC_FCR_FCMD_CGPB; - sam3x_flash_cmd(t, 0, cmd, bit); + sam3x_flash_cmd(t, base, cmd, bit); sam3x_cmd_gpnvm_get(t); return true; -- cgit v1.2.3 From aca421d0bbd021c4b0e320195692d9760d9ecdcd Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Sun, 14 Apr 2013 21:58:49 +0400 Subject: Basic semihosting support Implement bare minimum necessary to support console IO. This works with standard newlib builds and is based on the reference documentation: http://infocenter.arm.com/help/topic/com.arm.doc.dui0471c/CHDJHHDI.html Tested using gcc-arm-none-eabi-4_7-2013q1-20130313 for both stm32f1-based BMP and stm32f0 target. Signed-off-by: Paul Fertser --- README | 12 ++++++++++ src/gdb_main.c | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 82 insertions(+) (limited to 'src') diff --git a/README b/README index 52835f9..b47e22b 100644 --- a/README +++ b/README @@ -45,6 +45,18 @@ your '.gdbinit'. That will allow you to access addresses outside of the memory map. It will treat anything outside of the memory map as RAM. +Semihosting support +=================== +Basic armv6m/armv7m semihosting is supported, i.e. you can build your +application in a special way to use host's stdin and stdout right +inside gdb simply by calling printf(), scanf() and other input-output +functions. To make use of it, add --specs=rdimon.specs and -lrdimon to +the linker flags for your firmware. + +All writes are treated as writes to the stdout, all reads are done +from stdin; SYS_ISTTY always returns true, SYS_ERRNO -- EINTR; +SYS_OPEN and SYS_FLEN return dummy non-zero values. + Project layout ============== driver/ - Windows drivers for the Black Magic probe hardware. diff --git a/src/gdb_main.c b/src/gdb_main.c index 6be6d0f..887b9ac 100644 --- a/src/gdb_main.c +++ b/src/gdb_main.c @@ -75,6 +75,8 @@ gdb_main(void) { int size; bool single_step = false; + char last_activity = 0; + uint32_t semihost_read_bytes = 0; DEBUG("Entring GDB protocol main loop\n"); /* GDB protocol main loop */ @@ -82,6 +84,7 @@ gdb_main(void) SET_IDLE_STATE(1); size = gdb_getpacket(pbuf, BUF_SIZE); SET_IDLE_STATE(0); + continue_activity: switch(pbuf[0]) { /* Implementation of these is mandatory! */ case 'g': { /* 'g': Read general registers */ @@ -163,9 +166,48 @@ gdb_main(void) unsigned char c = gdb_if_getchar_to(0); if((c == '\x03') || (c == '\x04')) { target_halt_request(cur_target); + last_activity = 's'; } } SET_RUN_STATE(0); + + uint32_t arm_regs[cur_target->regs_size]; + uint32_t semihost_buf[4]; + target_regs_read(cur_target, arm_regs); + target_mem_read_bytes(cur_target, (uint8_t *)semihost_buf, arm_regs[15], 2); + /* Is this a semihosting breakpoint? */ + if ((semihost_buf[0] & 0xFFFF) == 0xBEAB) { + last_activity = pbuf[0]; + semihost_read_bytes = 0; + target_mem_read_words(cur_target, semihost_buf, arm_regs[1], sizeof(semihost_buf)); + + switch (arm_regs[0]) { + case 0x09: /* SYS_ISTTY */ + arm_regs[0] = 1; /* it's a tty */ + target_regs_write(cur_target, arm_regs); + /* fall-through */ + case 0x01: /* SYS_OPEN */ + case 0x0C: /* SYS_FLEN */ + /* pretend it's successful, r0 is non-zero already */ + goto continue_activity; + case 0x13: /* SYS_ERRNO */ + arm_regs[0] = 4; /* EINTR */ + target_regs_write(cur_target, arm_regs); + goto continue_activity; + case 0x05: /* SYS_WRITE */ + gdb_putpacket_f("Fwrite,1,%08X,%08X", + semihost_buf[1], semihost_buf[2]); + arm_regs[0] = 0; /* pretend it's always successful */ + target_regs_write(cur_target, arm_regs); + continue; + case 0x06: /* SYS_READ */ + gdb_putpacket_f("Fread,0,%08X,%08X", + semihost_buf[1], semihost_buf[2]); + semihost_read_bytes = semihost_buf[2]; + continue; + } + } + /* Report reason for halt */ if(target_check_hw_wp(cur_target, &watch_addr)) { /* Watchpoint hit */ @@ -175,6 +217,34 @@ gdb_main(void) } break; } + case 'F': { /* Semihosting call finished */ + int bytes, errcode, items; + char c, *p; + if (pbuf[1] == '-') + p = &pbuf[2]; + else + p = &pbuf[1]; + items = sscanf(p, "%x,%x,%c", &bytes, &errcode, &c); + + if (semihost_read_bytes) { + uint32_t arm_regs[cur_target->regs_size]; + target_regs_read(cur_target, arm_regs); + if (items == 3 && c == 'C') + arm_regs[0] = -1; + else + arm_regs[0] = semihost_read_bytes - bytes; + target_regs_write(cur_target, arm_regs); + } + + /* if break is requested */ + if (items == 3 && c == 'C') { + gdb_putpacketz("T02"); + break; + } + + pbuf[0] = last_activity; + goto continue_activity; + } /* Optional GDB packet support */ case '!': /* Enable Extended GDB Protocol. */ -- cgit v1.2.3 From 5020d1f05db920cd0633982016c0b1978a310d20 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sun, 14 Apr 2013 19:47:11 -0700 Subject: Move semihosting support to cortexm.c. Try to implement more syscalls. --- src/cortexm.c | 159 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/gdb_main.c | 59 ++++--------------- src/include/target.h | 7 +++ 3 files changed, 176 insertions(+), 49 deletions(-) (limited to 'src') diff --git a/src/cortexm.c b/src/cortexm.c index 36319ee..179fb36 100644 --- a/src/cortexm.c +++ b/src/cortexm.c @@ -204,6 +204,9 @@ static int cortexm_check_hw_wp(struct target_s *target, uint32_t *addr); #define CORTEXM_MAX_WATCHPOINTS 4 /* architecture says up to 15, no implementation has > 4 */ #define CORTEXM_MAX_BREAKPOINTS 6 /* architecture says up to 127, no implementation has > 6 */ +static int cortexm_hostio_request(target *t); +static void cortexm_hostio_reply(target *t, int32_t retcode, uint32_t errcode); + struct cortexm_priv { bool stepping; bool on_bkpt; @@ -219,6 +222,10 @@ struct cortexm_priv { unsigned hw_breakpoint_max; /* Copy of DEMCR for vector-catch */ uint32_t demcr; + /* Semihosting state */ + uint32_t syscall; + uint32_t errno; + uint32_t byte_count; }; /* Register number tables */ @@ -335,6 +342,8 @@ cortexm_probe(struct target_s *target) target->halt_resume = cortexm_halt_resume; target->regs_size = sizeof(regnum_cortex_m); + target->hostio_reply = cortexm_hostio_reply; + target_add_commands(target, cortexm_cmd_list, cortexm_driver_str); /* Probe for FP extension */ @@ -595,6 +604,23 @@ cortexm_halt_wait(struct target_s *target) /* Remember if we stopped on a breakpoint */ priv->on_bkpt = dfsr & (CORTEXM_DFSR_BKPT); + if (priv->on_bkpt) { + /* If we've hit a programmed breakpoint, check for semihosting + * call. */ + uint32_t pc = cortexm_pc_read(target); + uint16_t bkpt_instr; + target_mem_read_bytes(target, (uint8_t *)&bkpt_instr, pc, 2); + if (bkpt_instr == 0xBEAB) { + int n = cortexm_hostio_request(target); + if (n > 0) { + target_halt_resume(target, priv->stepping); + return 0; + } else if (n < 0) { + return -1; + } + } + } + if (dfsr & (CORTEXM_DFSR_BKPT | CORTEXM_DFSR_DWTTRAP)) return SIGTRAP; @@ -861,3 +887,136 @@ static bool cortexm_vector_catch(target *t, int argc, char *argv[]) return true; } + +/* Semihosting support */ +/* ARM Semihosting syscall numbers, from ARM doc DUI0471C, Chapter 8 */ +#define SYS_CLOSE 0x02 +#define SYS_CLOCK 0x10 +#define SYS_ELAPSED 0x30 +#define SYS_ERRNO 0x13 +#define SYS_FLEN 0x0C +#define SYS_GET_CMDLINE 0x15 +#define SYS_HEAPINFO 0x16 +#define SYS_ISERROR 0x08 +#define SYS_ISTTY 0x09 +#define SYS_OPEN 0x01 +#define SYS_READ 0x06 +#define SYS_READC 0x07 +#define SYS_REMOVE 0x0E +#define SYS_RENAME 0x0F +#define SYS_SEEK 0x0A +#define SYS_SYSTEM 0x12 +#define SYS_TICKFREQ 0x31 +#define SYS_TIME 0x11 +#define SYS_TMPNAM 0x0D +#define SYS_WRITE 0x05 +#define SYS_WRITEC 0x03 +#define SYS_WRITE0 0x04 + +#define FILEIO_O_RDONLY 0 +#define FILEIO_O_WRONLY 1 +#define FILEIO_O_RDWR 2 +#define FILEIO_O_APPEND 0x008 +#define FILEIO_O_CREAT 0x200 +#define FILEIO_O_TRUNC 0x400 + +#define FILEIO_SEEK_SET 0 +#define FILEIO_SEEK_CUR 1 +#define FILEIO_SEEK_END 2 + +static int cortexm_hostio_request(target *t) +{ + ADIv5_AP_t *ap = adiv5_target_ap(t); + struct cortexm_priv *priv = ap->priv; + uint32_t arm_regs[t->regs_size]; + uint32_t params[4]; + + target_regs_read(t, arm_regs); + target_mem_read_words(t, params, arm_regs[1], sizeof(params)); + priv->syscall = arm_regs[0]; + + DEBUG("syscall 0x%x (%x %x %x %x)\n", priv->syscall, + params[0], params[1], params[2], params[3]); + switch (priv->syscall) { + case SYS_OPEN:{ /* open */ + /* Translate stupid fopen modes to open flags. + * See DUI0471C, Table 8-3 */ + const uint32_t flags[] = { + FILEIO_O_RDONLY, /* r, rb */ + FILEIO_O_RDWR, /* r+, r+b */ + FILEIO_O_WRONLY | FILEIO_O_CREAT | FILEIO_O_TRUNC,/*w*/ + FILEIO_O_RDWR | FILEIO_O_CREAT | FILEIO_O_TRUNC,/*w+*/ + FILEIO_O_WRONLY | FILEIO_O_CREAT | FILEIO_O_APPEND,/*a*/ + FILEIO_O_RDWR | FILEIO_O_CREAT | FILEIO_O_APPEND,/*a+*/ + }; + gdb_putpacket_f("Fopen,%08X/%X,%08X,%08X", + params[0], params[2] + 1, + flags[params[1] >> 1], 0644); + break; + } + case SYS_CLOSE: /* close */ + gdb_putpacket_f("Fclose,%08X", params[0]); + break; + case SYS_READ: /* read */ + priv->byte_count = params[2]; + gdb_putpacket_f("Fread,%08X,%08X,%08X", + params[0], params[1], params[2]); + break; + case SYS_WRITE: /* write */ + priv->byte_count = params[2]; + gdb_putpacket_f("Fwrite,%08X,%08X,%08X", + params[0], params[1], params[2]); + break; + case SYS_ISTTY: /* isatty */ + gdb_putpacket_f("Fisatty,%08X", params[0]); + break; + case SYS_SEEK: /* lseek */ + gdb_putpacket_f("Flseek,%08X,%08X,%08X", + params[0], params[1], FILEIO_SEEK_SET); + break; + case SYS_RENAME:/* rename */ + gdb_putpacket_f("Frename,%08X/%X,%08X/%X", + params[0], params[1] + 1, + params[2], params[3] + 1); + break; + case SYS_REMOVE:/* unlink */ + gdb_putpacket_f("Funlink,%08X/%X", params[0], params[1] + 1); + break; + case SYS_SYSTEM:/* system */ + gdb_putpacket_f("Fsystem,%08X/%X", params[0], params[1] + 1); + break; + + case SYS_FLEN: /* Not supported, fake success */ + priv->errno = 0; + return 1; + + case SYS_ERRNO: /* Return last errno from GDB */ + arm_regs[0] = priv->errno; + target_regs_write(t, arm_regs); + return 1; + + case SYS_TIME: /* gettimeofday */ + /* FIXME How do we use gdb's gettimeofday? */ + default: + return 0; + } + + return -1; +} + +static void cortexm_hostio_reply(target *t, int32_t retcode, uint32_t errcode) +{ + ADIv5_AP_t *ap = adiv5_target_ap(t); + struct cortexm_priv *priv = ap->priv; + uint32_t arm_regs[t->regs_size]; + + DEBUG("syscall return ret=%d errno=%d\n", retcode, errcode); + target_regs_read(t, arm_regs); + if (((priv->syscall == SYS_READ) || (priv->syscall == SYS_WRITE)) && + (retcode > 0)) + retcode = priv->byte_count - retcode; + arm_regs[0] = retcode; + target_regs_write(t, arm_regs); + priv->errno = errcode; +} + diff --git a/src/gdb_main.c b/src/gdb_main.c index 887b9ac..69d5ed1 100644 --- a/src/gdb_main.c +++ b/src/gdb_main.c @@ -76,7 +76,6 @@ gdb_main(void) int size; bool single_step = false; char last_activity = 0; - uint32_t semihost_read_bytes = 0; DEBUG("Entring GDB protocol main loop\n"); /* GDB protocol main loop */ @@ -161,6 +160,7 @@ gdb_main(void) break; } + last_activity = pbuf[0]; /* Wait for target halt */ while(!(sig = target_halt_wait(cur_target))) { unsigned char c = gdb_if_getchar_to(0); @@ -171,42 +171,9 @@ gdb_main(void) } SET_RUN_STATE(0); - uint32_t arm_regs[cur_target->regs_size]; - uint32_t semihost_buf[4]; - target_regs_read(cur_target, arm_regs); - target_mem_read_bytes(cur_target, (uint8_t *)semihost_buf, arm_regs[15], 2); - /* Is this a semihosting breakpoint? */ - if ((semihost_buf[0] & 0xFFFF) == 0xBEAB) { - last_activity = pbuf[0]; - semihost_read_bytes = 0; - target_mem_read_words(cur_target, semihost_buf, arm_regs[1], sizeof(semihost_buf)); - - switch (arm_regs[0]) { - case 0x09: /* SYS_ISTTY */ - arm_regs[0] = 1; /* it's a tty */ - target_regs_write(cur_target, arm_regs); - /* fall-through */ - case 0x01: /* SYS_OPEN */ - case 0x0C: /* SYS_FLEN */ - /* pretend it's successful, r0 is non-zero already */ - goto continue_activity; - case 0x13: /* SYS_ERRNO */ - arm_regs[0] = 4; /* EINTR */ - target_regs_write(cur_target, arm_regs); - goto continue_activity; - case 0x05: /* SYS_WRITE */ - gdb_putpacket_f("Fwrite,1,%08X,%08X", - semihost_buf[1], semihost_buf[2]); - arm_regs[0] = 0; /* pretend it's always successful */ - target_regs_write(cur_target, arm_regs); - continue; - case 0x06: /* SYS_READ */ - gdb_putpacket_f("Fread,0,%08X,%08X", - semihost_buf[1], semihost_buf[2]); - semihost_read_bytes = semihost_buf[2]; - continue; - } - } + /* Negative signal indicates we're in a syscall */ + if (sig < 0) + break; /* Report reason for halt */ if(target_check_hw_wp(cur_target, &watch_addr)) { @@ -218,23 +185,17 @@ gdb_main(void) break; } case 'F': { /* Semihosting call finished */ - int bytes, errcode, items; + int retcode, errcode, items; char c, *p; if (pbuf[1] == '-') p = &pbuf[2]; else p = &pbuf[1]; - items = sscanf(p, "%x,%x,%c", &bytes, &errcode, &c); - - if (semihost_read_bytes) { - uint32_t arm_regs[cur_target->regs_size]; - target_regs_read(cur_target, arm_regs); - if (items == 3 && c == 'C') - arm_regs[0] = -1; - else - arm_regs[0] = semihost_read_bytes - bytes; - target_regs_write(cur_target, arm_regs); - } + items = sscanf(p, "%x,%x,%c", &retcode, &errcode, &c); + if (pbuf[1] == '-') + retcode = -retcode; + + target_hostio_reply(cur_target, retcode, errcode); /* if break is requested */ if (items == 3 && c == 'C') { diff --git a/src/include/target.h b/src/include/target.h index cd3079c..b83a2e9 100644 --- a/src/include/target.h +++ b/src/include/target.h @@ -116,6 +116,10 @@ target *target_attach(target *t, target_destroy_callback destroy_cb); #define target_flash_write(target, dest, src, len) \ (target)->flash_write((target), (dest), (src), (len)) +/* Host I/O */ +#define target_hostio_reply(target, recode, errcode) \ + (target)->hostio_reply((target), (retcode), (errcode)) + struct target_s { /* Notify controlling debugger if target is lost */ @@ -171,6 +175,9 @@ struct target_s { int (*flash_write)(struct target_s *target, uint32_t dest, const uint8_t *src, int len); + /* Host I/O support */ + void (*hostio_reply)(target *t, int32_t retcode, uint32_t errcode); + const char *driver; struct target_command_s *commands; -- cgit v1.2.3 From df32aad757935c8953c844ffaa455fa940b4b405 Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Mon, 15 Apr 2013 21:42:46 +0400 Subject: semihosting: improve handling of console I/O This implements special handling for SYS_OPEN to catch requests for ":tt" which is reserved by ARM for console input/output. They're mapped to the appropriate GDB file descriptors automatically. An additional file handle offset is introduced because ARM doesn't consider zero handle to be valid. Signed-off-by: Paul Fertser --- README | 18 +++++++++++------- src/cortexm.c | 40 +++++++++++++++++++++++++++++++--------- 2 files changed, 42 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/README b/README index b47e22b..9c10013 100644 --- a/README +++ b/README @@ -47,15 +47,19 @@ RAM. Semihosting support =================== -Basic armv6m/armv7m semihosting is supported, i.e. you can build your -application in a special way to use host's stdin and stdout right -inside gdb simply by calling printf(), scanf() and other input-output -functions. To make use of it, add --specs=rdimon.specs and -lrdimon to +Standard ARMv6-M/ARMv7-M semihosting is supported, i.e. you can build +your application in a special way to have calls to certain functions +(open(), close(), read(), write(), lseek(), rename(), unlink(), +stat(), isatty(), system()) executed on the debugging host itself. To +make use of these facilities, add --specs=rdimon.specs and -lrdimon to the linker flags for your firmware. -All writes are treated as writes to the stdout, all reads are done -from stdin; SYS_ISTTY always returns true, SYS_ERRNO -- EINTR; -SYS_OPEN and SYS_FLEN return dummy non-zero values. +If you're going to use stdin, stdout or stderr (e.g. via +printf()/scanf()) and you're not using newlib's crt0 (by specifying +-nostartfiles), you need to add this to your initialisation: + +void initialise_monitor_handles(void); +initialise_monitor_handles(); Project layout ============== diff --git a/src/cortexm.c b/src/cortexm.c index 179fb36..130f683 100644 --- a/src/cortexm.c +++ b/src/cortexm.c @@ -28,6 +28,7 @@ * Issues: * There are way too many magic numbers used here. */ +#include #include #include #include @@ -949,41 +950,60 @@ static int cortexm_hostio_request(target *t) FILEIO_O_WRONLY | FILEIO_O_CREAT | FILEIO_O_APPEND,/*a*/ FILEIO_O_RDWR | FILEIO_O_CREAT | FILEIO_O_APPEND,/*a+*/ }; + uint32_t pflag = flags[params[1] >> 1]; + char filename[4]; + + target_mem_read_bytes(t, filename, params[0], sizeof(filename)); + /* handle requests for console i/o */ + if (!strcmp(filename, ":tt")) { + if (pflag == FILEIO_O_RDONLY) + arm_regs[0] = STDIN_FILENO; + else if (pflag & FILEIO_O_TRUNC) + arm_regs[0] = STDOUT_FILENO; + else + arm_regs[0] = STDERR_FILENO; + arm_regs[0]++; + target_regs_write(t, arm_regs); + return 1; + } + gdb_putpacket_f("Fopen,%08X/%X,%08X,%08X", params[0], params[2] + 1, - flags[params[1] >> 1], 0644); + pflag, 0644); break; } case SYS_CLOSE: /* close */ - gdb_putpacket_f("Fclose,%08X", params[0]); + gdb_putpacket_f("Fclose,%08X", params[0] - 1); break; case SYS_READ: /* read */ priv->byte_count = params[2]; gdb_putpacket_f("Fread,%08X,%08X,%08X", - params[0], params[1], params[2]); + params[0] - 1, params[1], params[2]); break; case SYS_WRITE: /* write */ priv->byte_count = params[2]; gdb_putpacket_f("Fwrite,%08X,%08X,%08X", - params[0], params[1], params[2]); + params[0] - 1, params[1], params[2]); break; case SYS_ISTTY: /* isatty */ - gdb_putpacket_f("Fisatty,%08X", params[0]); + gdb_putpacket_f("Fisatty,%08X", params[0] - 1); break; case SYS_SEEK: /* lseek */ gdb_putpacket_f("Flseek,%08X,%08X,%08X", - params[0], params[1], FILEIO_SEEK_SET); + params[0] - 1, params[1], FILEIO_SEEK_SET); break; case SYS_RENAME:/* rename */ gdb_putpacket_f("Frename,%08X/%X,%08X/%X", - params[0], params[1] + 1, + params[0] - 1, params[1] + 1, params[2], params[3] + 1); break; case SYS_REMOVE:/* unlink */ - gdb_putpacket_f("Funlink,%08X/%X", params[0], params[1] + 1); + gdb_putpacket_f("Funlink,%08X/%X", params[0] - 1, + params[1] + 1); break; case SYS_SYSTEM:/* system */ - gdb_putpacket_f("Fsystem,%08X/%X", params[0], params[1] + 1); + gdb_putpacket_f("Fsystem,%08X/%X", params[0] - 1, + params[1] + 1); break; case SYS_FLEN: /* Not supported, fake success */ @@ -1015,6 +1035,8 @@ static void cortexm_hostio_reply(target *t, int32_t retcode, uint32_t errcode) if (((priv->syscall == SYS_READ) || (priv->syscall == SYS_WRITE)) && (retcode > 0)) retcode = priv->byte_count - retcode; + if ((priv->syscall == SYS_OPEN) && (retcode != -1)) + retcode++; arm_regs[0] = retcode; target_regs_write(t, arm_regs); priv->errno = errcode; -- cgit v1.2.3 From 2d63dd4b5b01df2406cda71ee1fb08968b14fd0a Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Mon, 17 Jun 2013 15:46:26 +1200 Subject: Fix register array sizes. --- src/cortexm.c | 2 +- src/gdb_main.c | 8 ++++---- src/lpc43xx.c | 2 +- src/nxp_tgt.c | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/cortexm.c b/src/cortexm.c index 130f683..7819598 100644 --- a/src/cortexm.c +++ b/src/cortexm.c @@ -667,7 +667,7 @@ static int cortexm_fault_unwind(struct target_s *target) * for a configurable fault to avoid catching core resets */ if((hfsr & CORTEXM_HFSR_FORCED) || cfsr) { /* Unwind exception */ - uint32_t regs[target->regs_size]; + uint32_t regs[target->regs_size / 4]; uint32_t stack[8]; uint32_t retcode, framesize; /* Read registers for post-exception stack pointer */ diff --git a/src/gdb_main.c b/src/gdb_main.c index 69d5ed1..bd27d48 100644 --- a/src/gdb_main.c +++ b/src/gdb_main.c @@ -88,8 +88,8 @@ gdb_main(void) /* Implementation of these is mandatory! */ case 'g': { /* 'g': Read general registers */ ERROR_IF_NO_TARGET(); - uint32_t arm_regs[cur_target->regs_size]; - target_regs_read(cur_target, (void*)arm_regs); + uint8_t arm_regs[cur_target->regs_size]; + target_regs_read(cur_target, arm_regs); gdb_putpacket(hexify(pbuf, (void*)arm_regs, cur_target->regs_size), cur_target->regs_size * 2); break; } @@ -111,8 +111,8 @@ gdb_main(void) } case 'G': { /* 'G XX': Write general registers */ ERROR_IF_NO_TARGET(); - uint32_t arm_regs[cur_target->regs_size]; - unhexify((void*)arm_regs, &pbuf[1], cur_target->regs_size); + uint8_t arm_regs[cur_target->regs_size]; + unhexify(arm_regs, &pbuf[1], cur_target->regs_size); target_regs_write(cur_target, arm_regs); gdb_putpacketz("OK"); break; diff --git a/src/lpc43xx.c b/src/lpc43xx.c index fc843c6..200a8a4 100644 --- a/src/lpc43xx.c +++ b/src/lpc43xx.c @@ -313,7 +313,7 @@ static int32_t sector_number(uint32_t addr) static void lpc43xx_iap_call(struct target_s *target, struct flash_param *param, unsigned param_len) { - uint32_t regs[target->regs_size]; + uint32_t regs[target->regs_size / 4]; uint32_t iap_entry; target_mem_read_words(target, &iap_entry, IAP_ENTRYPOINT_LOCATION, sizeof(iap_entry)); diff --git a/src/nxp_tgt.c b/src/nxp_tgt.c index f8ddf2a..ccb2cc6 100644 --- a/src/nxp_tgt.c +++ b/src/nxp_tgt.c @@ -116,7 +116,7 @@ lpc11xx_probe(struct target_s *target) static void lpc11x_iap_call(struct target_s *target, struct flash_param *param, unsigned param_len) { - uint32_t regs[target->regs_size]; + uint32_t regs[target->regs_size / 4]; /* fill out the remainder of the parameters and copy the structure to RAM */ param->opcodes[0] = 0xbe00; -- cgit v1.2.3 From 8c877d6dfa5aff2b70ce2c96ef6314bcae7a25c2 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Mon, 17 Jun 2013 15:53:32 +1200 Subject: Fix trailing whitespace everywhere. --- src/adiv5_jtagdp.c | 12 ++++++------ src/adiv5_swdp.c | 14 +++++++------- src/arm7tdmi.c | 6 +++--- src/command.c | 30 +++++++++++++++--------------- src/gdb_packet.c | 16 ++++++++-------- src/hex_utils.c | 6 +++--- src/include/adiv5.h | 4 ++-- src/include/jtagtap.h | 6 +++--- src/include/target.h | 12 ++++++------ src/jtagtap_generic.c | 8 ++++---- src/lmi.c | 6 +++--- src/main.c | 2 +- src/nxp_tgt.c | 12 ++++++------ src/platforms/libftdi/jtagtap.c | 12 ++++++------ src/platforms/libftdi/platform.c | 24 ++++++++++++------------ src/platforms/libftdi/swdptap.c | 10 +++++----- src/platforms/native/platform.c | 2 +- src/platforms/native/platform.h | 4 ++-- src/platforms/stlink/platform.c | 20 ++++++++++---------- src/platforms/stlink/platform.h | 2 +- src/platforms/stm32/swdptap.c | 8 ++++---- src/platforms/swlink/platform.c | 6 +++--- src/platforms/swlink/platform.h | 2 +- src/sam3x.c | 2 +- src/stm32f1.c | 14 +++++++------- src/stm32f4.c | 10 +++++----- src/stm32l1.c | 4 ++-- 27 files changed, 127 insertions(+), 127 deletions(-) (limited to 'src') diff --git a/src/adiv5_jtagdp.c b/src/adiv5_jtagdp.c index 68bcddd..693b94e 100644 --- a/src/adiv5_jtagdp.c +++ b/src/adiv5_jtagdp.c @@ -18,7 +18,7 @@ * along with this program. If not, see . */ -/* This file implements the JTAG-DP specific functions of the +/* This file implements the JTAG-DP specific functions of the * ARM Debug Interface v5 Architecure Specification, ARM doc IHI0031A. */ @@ -43,7 +43,7 @@ static uint32_t adiv5_jtagdp_read(ADIv5_DP_t *dp, uint8_t addr); static uint32_t adiv5_jtagdp_error(ADIv5_DP_t *dp); -static uint32_t adiv5_jtagdp_low_access(ADIv5_DP_t *dp, uint8_t APnDP, uint8_t RnW, +static uint32_t adiv5_jtagdp_low_access(ADIv5_DP_t *dp, uint8_t APnDP, uint8_t RnW, uint8_t addr, uint32_t value); @@ -70,19 +70,19 @@ static void adiv5_jtagdp_write(ADIv5_DP_t *dp, uint8_t addr, uint32_t value) static uint32_t adiv5_jtagdp_read(ADIv5_DP_t *dp, uint8_t addr) { adiv5_jtagdp_low_access(dp, ADIV5_LOW_DP, ADIV5_LOW_READ, addr, 0); - return adiv5_jtagdp_low_access(dp, ADIV5_LOW_DP, ADIV5_LOW_READ, + return adiv5_jtagdp_low_access(dp, ADIV5_LOW_DP, ADIV5_LOW_READ, ADIV5_DP_RDBUFF, 0); } static uint32_t adiv5_jtagdp_error(ADIv5_DP_t *dp) { - adiv5_jtagdp_low_access(dp, ADIV5_LOW_DP, ADIV5_LOW_READ, + adiv5_jtagdp_low_access(dp, ADIV5_LOW_DP, ADIV5_LOW_READ, ADIV5_DP_CTRLSTAT, 0); - return adiv5_jtagdp_low_access(dp, ADIV5_LOW_DP, ADIV5_LOW_WRITE, + return adiv5_jtagdp_low_access(dp, ADIV5_LOW_DP, ADIV5_LOW_WRITE, ADIV5_DP_CTRLSTAT, 0xF0000032) & 0x32; } -static uint32_t adiv5_jtagdp_low_access(ADIv5_DP_t *dp, uint8_t APnDP, uint8_t RnW, +static uint32_t adiv5_jtagdp_low_access(ADIv5_DP_t *dp, uint8_t APnDP, uint8_t RnW, uint8_t addr, uint32_t value) { uint64_t request, response; diff --git a/src/adiv5_swdp.c b/src/adiv5_swdp.c index 669bf42..8a38330 100644 --- a/src/adiv5_swdp.c +++ b/src/adiv5_swdp.c @@ -18,7 +18,7 @@ * along with this program. If not, see . */ -/* This file implements the SW-DP specific functions of the +/* This file implements the SW-DP specific functions of the * ARM Debug Interface v5 Architecure Specification, ARM doc IHI0031A. */ @@ -42,7 +42,7 @@ static uint32_t adiv5_swdp_read(ADIv5_DP_t *dp, uint8_t addr); static uint32_t adiv5_swdp_error(ADIv5_DP_t *dp); -static uint32_t adiv5_swdp_low_access(ADIv5_DP_t *dp, uint8_t APnDP, uint8_t RnW, +static uint32_t adiv5_swdp_low_access(ADIv5_DP_t *dp, uint8_t APnDP, uint8_t RnW, uint8_t addr, uint32_t value); @@ -95,15 +95,15 @@ static uint32_t adiv5_swdp_error(ADIv5_DP_t *dp) { uint32_t err, clr = 0; - err = adiv5_swdp_read(dp, ADIV5_DP_CTRLSTAT) & + err = adiv5_swdp_read(dp, ADIV5_DP_CTRLSTAT) & (ADIV5_DP_CTRLSTAT_STICKYORUN | ADIV5_DP_CTRLSTAT_STICKYCMP | ADIV5_DP_CTRLSTAT_STICKYERR); - if(err & ADIV5_DP_CTRLSTAT_STICKYORUN) + if(err & ADIV5_DP_CTRLSTAT_STICKYORUN) clr |= ADIV5_DP_ABORT_ORUNERRCLR; - if(err & ADIV5_DP_CTRLSTAT_STICKYCMP) + if(err & ADIV5_DP_CTRLSTAT_STICKYCMP) clr |= ADIV5_DP_ABORT_STKCMPCLR; - if(err & ADIV5_DP_CTRLSTAT_STICKYERR) + if(err & ADIV5_DP_CTRLSTAT_STICKYERR) clr |= ADIV5_DP_ABORT_STKERRCLR; adiv5_swdp_write(dp, ADIV5_DP_ABORT, clr); @@ -112,7 +112,7 @@ static uint32_t adiv5_swdp_error(ADIv5_DP_t *dp) return err; } -static uint32_t adiv5_swdp_low_access(ADIv5_DP_t *dp, uint8_t APnDP, uint8_t RnW, +static uint32_t adiv5_swdp_low_access(ADIv5_DP_t *dp, uint8_t APnDP, uint8_t RnW, uint8_t addr, uint32_t value) { uint8_t request = 0x81; diff --git a/src/arm7tdmi.c b/src/arm7tdmi.c index 805f995..ad38ab3 100644 --- a/src/arm7tdmi.c +++ b/src/arm7tdmi.c @@ -139,7 +139,7 @@ void arm7tdmi_jtag_handler(jtag_dev_t *dev) t->halt_request = arm7_halt_request; t->halt_wait = arm7_halt_wait; t->halt_resume = arm7_halt_resume; - + /* TODO: Breakpoint and watchpoint functions. */ /* TODO: Fault unwinder. */ /* TODO: Memory map / Flash programming. */ @@ -152,7 +152,7 @@ static void arm7_select_scanchain(struct target_arm7_s *target, uint8_t chain) jtag_dev_write_ir(target->jtag, ARM7_IR_INTEST); } -static void arm7_eice_write(struct target_arm7_s *target, +static void arm7_eice_write(struct target_arm7_s *target, uint8_t addr, uint32_t value) { uint64_t val = ((uint64_t)addr << 32) | value | ARM7_EICE_WRITE; @@ -256,7 +256,7 @@ static void arm7_halt_resume(struct target_s *target, bool step) /* Release DBGRQ */ arm7_eice_write(t, ARM7_EICE_DEBUG_CTRL, 0); - /* This sequence restores PC if no other instructions issued in + /* This sequence restores PC if no other instructions issued in * debug mode... * 0 E1A00000; MOV R0, R0 * 1 E1A00000; MOV R0, R0 diff --git a/src/command.c b/src/command.c index e9f7096..8378576 100644 --- a/src/command.c +++ b/src/command.c @@ -74,19 +74,19 @@ int command_process(target *t, char *cmd) const char **argv; /* Initial estimate for argc */ - for(char *s = cmd; *s; s++) + for(char *s = cmd; *s; s++) if((*s == ' ') || (*s == '\t')) argc++; argv = alloca(sizeof(const char *) * argc); /* Tokenize cmd to find argv */ - for(argc = 0, argv[argc] = strtok(cmd, " \t"); + for(argc = 0, argv[argc] = strtok(cmd, " \t"); argv[argc]; argv[++argc] = strtok(NULL, " \t")); /* Look for match and call handler */ for(c = cmd_list; c->cmd; c++) { /* Accept a partial match as GDB does. - * So 'mon ver' will match 'monitor version' + * So 'mon ver' will match 'monitor version' */ if(!strncmp(argv[0], c->cmd, strlen(argv[0]))) return !c->handler(t, argc, argv); @@ -96,7 +96,7 @@ int command_process(target *t, char *cmd) return -1; for (tc = t->commands; tc; tc = tc->next) - for(c = tc->cmds; c->cmd; c++) + for(c = tc->cmds; c->cmd; c++) if(!strncmp(argv[0], c->cmd, strlen(argv[0]))) return !c->handler(t, argc, argv); @@ -119,7 +119,7 @@ bool cmd_help(target *t) const struct command_s *c; gdb_out("General commands:\n"); - for(c = cmd_list; c->cmd; c++) + for(c = cmd_list; c->cmd; c++) gdb_outf("\t%s -- %s\n", c->cmd, c->help); if (!t) @@ -127,7 +127,7 @@ bool cmd_help(target *t) for (tc = t->commands; tc; tc = tc->next) { gdb_outf("%s specific commands:\n", tc->specific_name); - for(c = tc->cmds; c->cmd; c++) + for(c = tc->cmds; c->cmd; c++) gdb_outf("\t%s -- %s\n", c->cmd, c->help); } @@ -154,15 +154,15 @@ static bool cmd_jtag_scan(target *t, int argc, char **argv) if(devs < 0) { gdb_out("JTAG device scan failed!\n"); return false; - } + } if(devs == 0) { gdb_out("JTAG scan found no devices!\n"); return false; - } + } gdb_outf("Device IR Len IDCODE Description\n"); for(int i = 0; i < jtag_dev_count; i++) - gdb_outf("%d\t%d\t0x%08lX %s\n", i, - jtag_devs[i].ir_len, jtag_devs[i].idcode, + gdb_outf("%d\t%d\t0x%08lX %s\n", i, + jtag_devs[i].ir_len, jtag_devs[i].idcode, jtag_devs[i].descr); gdb_out("\n"); cmd_targets(NULL); @@ -176,13 +176,13 @@ bool cmd_swdp_scan(void) if(adiv5_swdp_scan() < 0) { gdb_out("SW-DP scan failed!\n"); return false; - } + } //gdb_outf("SW-DP detected IDCODE: 0x%08X\n", adiv5_dp_list->idcode); cmd_targets(NULL); return true; - + } bool cmd_targets(target *cur_target) @@ -194,11 +194,11 @@ bool cmd_targets(target *cur_target) gdb_out("No usable targets found.\n"); return false; } - + gdb_out("Available Targets:\n"); gdb_out("No. Att Driver\n"); for(t = target_list, i = 1; t; t = t->next, i++) - gdb_outf("%2d %c %s\n", i, t==cur_target?'*':' ', + gdb_outf("%2d %c %s\n", i, t==cur_target?'*':' ', t->driver); return true; @@ -206,7 +206,7 @@ bool cmd_targets(target *cur_target) bool cmd_morse(void) { - if(morse_msg) + if(morse_msg) gdb_outf("%s\n", morse_msg); return true; } diff --git a/src/gdb_packet.c b/src/gdb_packet.c index 958572c..d43be42 100644 --- a/src/gdb_packet.c +++ b/src/gdb_packet.c @@ -34,7 +34,7 @@ #include "gdb_packet.h" #include "hex_utils.h" -int +int gdb_getpacket(unsigned char *packet, int size) { unsigned char c; @@ -54,9 +54,9 @@ gdb_getpacket(unsigned char *packet, int size) if(i == size) break; /* Oh shit */ if(c == '$') { /* Restart capture */ - i = 0; - csum = 0; - continue; + i = 0; + csum = 0; + continue; } if(c == '}') { /* escaped char */ c = gdb_if_getchar(); @@ -70,7 +70,7 @@ gdb_getpacket(unsigned char *packet, int size) recv_csum[0] = gdb_if_getchar(); recv_csum[1] = gdb_if_getchar(); recv_csum[2] = 0; - + /* return packet if checksum matches */ if(csum == strtol(recv_csum, NULL, 16)) break; @@ -84,7 +84,7 @@ gdb_getpacket(unsigned char *packet, int size) DEBUG("%s : ", __func__); for(int j = 0; j < i; j++) { c = packet[j]; - if ((c >= 32) && (c < 127)) + if ((c >= 32) && (c < 127)) DEBUG("%c", c); else DEBUG("\\x%02X", c); @@ -101,7 +101,7 @@ void gdb_putpacket(unsigned char *packet, int size) unsigned char c; char xmit_csum[3]; int tries = 0; - + do { #ifdef DEBUG_GDBPACKET DEBUG("%s : ", __func__); @@ -111,7 +111,7 @@ void gdb_putpacket(unsigned char *packet, int size) for(i = 0; i < size; i++) { c = packet[i]; #ifdef DEBUG_GDBPACKET - if ((c >= 32) && (c < 127)) + if ((c >= 32) && (c < 127)) DEBUG("%c", c); else DEBUG("\\x%02X", c); diff --git a/src/hex_utils.c b/src/hex_utils.c index 6629f10..e477281 100644 --- a/src/hex_utils.c +++ b/src/hex_utils.c @@ -18,7 +18,7 @@ * along with this program. If not, see . */ -/* Convenience function to convert to/from ascii strings of hex digits. +/* Convenience function to convert to/from ascii strings of hex digits. */ #include @@ -44,9 +44,9 @@ char * hexify(char *hex, const unsigned char *buf, int size) static uint8_t unhex_digit(char hex) { uint8_t tmp = hex - '0'; - if(tmp > 9) + if(tmp > 9) tmp -= 'A' - '0' - 10; - if(tmp > 16) + if(tmp > 16) tmp -= 'a' - 'A'; return tmp; } diff --git a/src/include/adiv5.h b/src/include/adiv5.h index d2d4be0..1bfb5a1 100644 --- a/src/include/adiv5.h +++ b/src/include/adiv5.h @@ -111,7 +111,7 @@ typedef struct ADIv5_DP_s { uint32_t (*error)(struct ADIv5_DP_s *dp); - uint32_t (*low_access)(struct ADIv5_DP_s *dp, uint8_t APnDP, uint8_t RnW, + uint32_t (*low_access)(struct ADIv5_DP_s *dp, uint8_t APnDP, uint8_t RnW, uint8_t addr, uint32_t value); union { @@ -135,7 +135,7 @@ static inline uint32_t adiv5_dp_error(ADIv5_DP_t *dp) return dp->error(dp); } -static inline uint32_t adiv5_dp_low_access(struct ADIv5_DP_s *dp, uint8_t APnDP, +static inline uint32_t adiv5_dp_low_access(struct ADIv5_DP_s *dp, uint8_t APnDP, uint8_t RnW, uint8_t addr, uint32_t value) { return dp->low_access(dp, APnDP, RnW, addr, value); diff --git a/src/include/jtagtap.h b/src/include/jtagtap.h index f0588a0..fd13f2b 100644 --- a/src/include/jtagtap.h +++ b/src/include/jtagtap.h @@ -44,9 +44,9 @@ void jtagtap_tms_seq(uint32_t MS, int ticks); void jtagtap_tdi_tdo_seq(uint8_t *DO, const uint8_t final_tms, const uint8_t *DI, int ticks); void jtagtap_tdi_seq(const uint8_t final_tms, const uint8_t *DI, int ticks); /* Shift out a sequence on MS and DI, capture data to DO. - * - This is not endian safe: First byte will always be first shifted out. - * - DO may be NULL to ignore captured data. - * - DO may be point to the same address as DI. + * - This is not endian safe: First byte will always be first shifted out. + * - DO may be NULL to ignore captured data. + * - DO may be point to the same address as DI. */ /* generic soft reset: 1, 1, 1, 1, 1, 0 */ diff --git a/src/include/target.h b/src/include/target.h index b83a2e9..574a0eb 100644 --- a/src/include/target.h +++ b/src/include/target.h @@ -34,7 +34,7 @@ typedef struct target_s target; * targets, or because of a communication failure. The target data may * be assumed to be intact, but the communication medium may not be available, * so access methods shouldn't be called. - * + * * The callback is installed by target_attach() and only removed by attaching * with a different callback. It remains intact after target_detach(). */ @@ -131,14 +131,14 @@ struct target_s { int (*check_error)(struct target_s *target); /* Memory access functions */ - int (*mem_read_words)(struct target_s *target, uint32_t *dest, uint32_t src, + int (*mem_read_words)(struct target_s *target, uint32_t *dest, uint32_t src, int len); - int (*mem_write_words)(struct target_s *target, uint32_t dest, + int (*mem_write_words)(struct target_s *target, uint32_t dest, const uint32_t *src, int len); - int (*mem_read_bytes)(struct target_s *target, uint8_t *dest, uint32_t src, + int (*mem_read_bytes)(struct target_s *target, uint8_t *dest, uint32_t src, int len); - int (*mem_write_bytes)(struct target_s *target, uint32_t dest, + int (*mem_write_bytes)(struct target_s *target, uint32_t dest, const uint8_t *src, int len); /* Register access functions */ @@ -172,7 +172,7 @@ struct target_s { /* Flash memory access functions */ const char *xml_mem_map; int (*flash_erase)(struct target_s *target, uint32_t addr, int len); - int (*flash_write)(struct target_s *target, uint32_t dest, + int (*flash_write)(struct target_s *target, uint32_t dest, const uint8_t *src, int len); /* Host I/O support */ diff --git a/src/jtagtap_generic.c b/src/jtagtap_generic.c index a2e723b..63c8e44 100644 --- a/src/jtagtap_generic.c +++ b/src/jtagtap_generic.c @@ -28,14 +28,14 @@ jtagtap_tms_seq(uint32_t MS, int ticks) { while(ticks--) { jtagtap_next(MS & 1, 1); - MS >>= 1; + MS >>= 1; } } #endif #ifdef PROVIDE_GENERIC_JTAGTAP_TDI_TDO_SEQ -void +void jtagtap_tdi_tdo_seq(uint8_t *DO, const uint8_t final_tms, const uint8_t *DI, int ticks) { uint8_t index = 1; @@ -55,7 +55,7 @@ jtagtap_tdi_tdo_seq(uint8_t *DO, const uint8_t final_tms, const uint8_t *DI, int #ifdef PROVIDE_GENERIC_JTAGTAP_TDI_SEQ -void +void jtagtap_tdi_seq(const uint8_t final_tms, const uint8_t *DI, int ticks) { uint8_t index = 1; @@ -63,7 +63,7 @@ jtagtap_tdi_seq(const uint8_t final_tms, const uint8_t *DI, int ticks) jtagtap_next(ticks?0:final_tms, *DI & index); if(!(index <<= 1)) { index = 1; - DI++; + DI++; } } } diff --git a/src/lmi.c b/src/lmi.c index 09a9dd5..cb620c0 100644 --- a/src/lmi.c +++ b/src/lmi.c @@ -18,7 +18,7 @@ * along with this program. If not, see . */ -/* This file implements TI/LMI LM3S target specific functions providing +/* This file implements TI/LMI LM3S target specific functions providing * the XML memory map and Flash memory programming. * * Issues: @@ -35,7 +35,7 @@ #include "target.h" static int lmi_flash_erase(struct target_s *target, uint32_t addr, int len); -static int lmi_flash_write(struct target_s *target, uint32_t dest, +static int lmi_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, int len); static const char lmi_driver_str[] = "LuminaryMicro Stellaris"; @@ -135,7 +135,7 @@ int lmi_flash_erase(struct target_s *target, uint32_t addr, int len) return 0; } -int lmi_flash_write(struct target_s *target, uint32_t dest, +int lmi_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, int len) { uint32_t data[(len>>2)+2]; diff --git a/src/main.c b/src/main.c index 4921aed..809d4bf 100644 --- a/src/main.c +++ b/src/main.c @@ -18,7 +18,7 @@ * along with this program. If not, see . */ -/* Provides main entry point. Initialise subsystems and enter GDB +/* Provides main entry point. Initialise subsystems and enter GDB * protocol loop. */ diff --git a/src/nxp_tgt.c b/src/nxp_tgt.c index ccb2cc6..83f37ba 100644 --- a/src/nxp_tgt.c +++ b/src/nxp_tgt.c @@ -51,10 +51,10 @@ static struct flash_program flash_pgm; static void lpc11x_iap_call(struct target_s *target, struct flash_param *param, unsigned param_len); static int lpc11xx_flash_prepare(struct target_s *target, uint32_t addr, int len); static int lpc11xx_flash_erase(struct target_s *target, uint32_t addr, int len); -static int lpc11xx_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, +static int lpc11xx_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, int len); -/* +/* * Note that this memory map is actually for the largest of the lpc11xx devices; * There seems to be no good way to decode the part number to determine the RAM * and flash sizes. @@ -143,7 +143,7 @@ lpc11x_iap_call(struct target_s *target, struct flash_param *param, unsigned par static int lpc11xx_flash_prepare(struct target_s *target, uint32_t addr, int len) -{ +{ /* prepare the sector(s) to be erased */ memset(&flash_pgm.p, 0, sizeof(flash_pgm.p)); flash_pgm.p.command[0] = IAP_CMD_PREPARE; @@ -196,15 +196,15 @@ lpc11xx_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, unsigned chunk; for (chunk = first_chunk; chunk <= last_chunk; chunk++) { - + DEBUG("chunk %u len %d\n", chunk, len); /* first and last chunk may require special handling */ if ((chunk == first_chunk) || (chunk == last_chunk)) { /* fill with all ff to avoid sector rewrite corrupting other writes */ memset(flash_pgm.data, 0xff, sizeof(flash_pgm.data)); - - /* copy as much as fits */ + + /* copy as much as fits */ int copylen = IAP_PGM_CHUNKSIZE - chunk_offset; if (copylen > len) copylen = len; diff --git a/src/platforms/libftdi/jtagtap.c b/src/platforms/libftdi/jtagtap.c index 77e1867..91f6ae2 100644 --- a/src/platforms/libftdi/jtagtap.c +++ b/src/platforms/libftdi/jtagtap.c @@ -84,7 +84,7 @@ jtagtap_tms_seq(uint32_t MS, int ticks) //jtagtap_next(MS & 1, 1); tmp[1] = ticks<7?ticks-1:6; tmp[2] = 0x80 | (MS & 0x7F); - + // assert(ftdi_write_data(ftdic, tmp, 3) == 3); platform_buffer_write(tmp, 3); MS >>= 7; ticks -= 7; @@ -93,7 +93,7 @@ jtagtap_tms_seq(uint32_t MS, int ticks) #endif #ifndef PROVIDE_GENERIC_TAP_TDI_SEQ -void +void jtagtap_tdi_seq(const uint8_t final_tms, const uint8_t *DI, int ticks) { char *tmp; @@ -119,7 +119,7 @@ jtagtap_tdi_seq(const uint8_t final_tms, const uint8_t *DI, int ticks) tmp[index++] = rticks - 1; tmp[index++] = *DI; } - + if(final_tms) { tmp[index++] = 0x4B; tmp[index++] = 0; @@ -131,7 +131,7 @@ jtagtap_tdi_seq(const uint8_t final_tms, const uint8_t *DI, int ticks) #endif #ifndef PROVIDE_GENERIC_TAP_TDI_TDO_SEQ -void +void jtagtap_tdi_tdo_seq(uint8_t *DO, const uint8_t final_tms, const uint8_t *DI, int ticks) { uint8_t *tmp; @@ -159,7 +159,7 @@ jtagtap_tdi_tdo_seq(uint8_t *DO, const uint8_t final_tms, const uint8_t *DI, int tmp[index++] = rticks - 1; tmp[index++] = *DI; } - + if(final_tms) { rsize++; tmp[index++] = 0x6B; @@ -176,7 +176,7 @@ jtagtap_tdi_tdo_seq(uint8_t *DO, const uint8_t final_tms, const uint8_t *DI, int printf("\n");*/ index = 0; if(final_tms) rsize--; - + while(rsize--) { /*if(rsize) printf("%02X ", tmp[index]);*/ *DO++ = tmp[index++]; diff --git a/src/platforms/libftdi/platform.c b/src/platforms/libftdi/platform.c index ec2a8f1..dc57a45 100644 --- a/src/platforms/libftdi/platform.c +++ b/src/platforms/libftdi/platform.c @@ -122,7 +122,7 @@ static struct cable_desc_s { }; int platform_init(int argc, char **argv) -{ +{ int err; int c; int index = 0; @@ -167,40 +167,40 @@ int platform_init(int argc, char **argv) ftdic = NULL; } if((ftdic = ftdi_new()) == NULL) { - fprintf(stderr, "ftdi_new: %s\n", + fprintf(stderr, "ftdi_new: %s\n", ftdi_get_error_string(ftdic)); abort(); } if((err = ftdi_set_interface(ftdic, cable_desc[index].interface)) != 0) { - fprintf(stderr, "ftdi_set_interface: %d: %s\n", + fprintf(stderr, "ftdi_set_interface: %d: %s\n", err, ftdi_get_error_string(ftdic)); abort(); } if((err = ftdi_usb_open_desc( ftdic, cable_desc[index].vendor, cable_desc[index].product, cable_desc[index].description, serial)) != 0) { - fprintf(stderr, "unable to open ftdi device: %d (%s)\n", + fprintf(stderr, "unable to open ftdi device: %d (%s)\n", err, ftdi_get_error_string(ftdic)); abort(); } if((err = ftdi_set_latency_timer(ftdic, 1)) != 0) { - fprintf(stderr, "ftdi_set_latency_timer: %d: %s\n", + fprintf(stderr, "ftdi_set_latency_timer: %d: %s\n", err, ftdi_get_error_string(ftdic)); abort(); } if((err = ftdi_set_baudrate(ftdic, 1000000)) != 0) { - fprintf(stderr, "ftdi_set_baudrate: %d: %s\n", + fprintf(stderr, "ftdi_set_baudrate: %d: %s\n", err, ftdi_get_error_string(ftdic)); abort(); } if((err = ftdi_usb_purge_buffers(ftdic)) != 0) { - fprintf(stderr, "ftdi_set_baudrate: %d: %s\n", + fprintf(stderr, "ftdi_set_baudrate: %d: %s\n", err, ftdi_get_error_string(ftdic)); abort(); } if((err = ftdi_write_data_set_chunksize(ftdic, BUF_SIZE)) != 0) { - fprintf(stderr, "ftdi_write_data_set_chunksize: %d: %s\n", + fprintf(stderr, "ftdi_write_data_set_chunksize: %d: %s\n", err, ftdi_get_error_string(ftdic)); abort(); } @@ -216,8 +216,8 @@ int platform_init(int argc, char **argv) assert(gdb_if_init() == 0); jtag_scan(NULL); - - return 0; + + return 0; } void platform_buffer_flush(void) @@ -250,9 +250,9 @@ int vasprintf(char **strp, const char *fmt, va_list ap) int size = 128, ret = 0; *strp = malloc(size); - while(*strp && ((ret = vsnprintf(*strp, size, fmt, ap)) == size)) + while(*strp && ((ret = vsnprintf(*strp, size, fmt, ap)) == size)) *strp = realloc(*strp, size <<= 1); - + return ret; } #endif diff --git a/src/platforms/libftdi/swdptap.c b/src/platforms/libftdi/swdptap.c index be329d8..cd3582b 100644 --- a/src/platforms/libftdi/swdptap.c +++ b/src/platforms/libftdi/swdptap.c @@ -40,7 +40,7 @@ int swdptap_init(void) assert(ftdic != NULL); if((err = ftdi_set_bitmode(ftdic, 0xAB, BITMODE_BITBANG)) != 0) { - fprintf(stderr, "ftdi_set_bitmode: %d: %s\n", + fprintf(stderr, "ftdi_set_bitmode: %d: %s\n", err, ftdi_get_error_string(ftdic)); abort(); } @@ -49,11 +49,11 @@ int swdptap_init(void) /* This must be investigated in more detail. * As described in STM32 Reference Manual... */ - swdptap_seq_out(0xFFFF, 16); + swdptap_seq_out(0xFFFF, 16); swdptap_reset(); - swdptap_seq_out(0xE79E, 16); /* 0b0111100111100111 */ + swdptap_seq_out(0xE79E, 16); /* 0b0111100111100111 */ swdptap_reset(); - swdptap_seq_out(0, 16); + swdptap_seq_out(0, 16); return 0; } @@ -85,7 +85,7 @@ static void swdptap_turnaround(uint8_t dir) assert(ftdi_set_bitmode(ftdic, 0xAB, BITMODE_BITBANG) == 0); } -static uint8_t swdptap_bit_in(void) +static uint8_t swdptap_bit_in(void) { uint8_t ret; diff --git a/src/platforms/native/platform.c b/src/platforms/native/platform.c index 24eb79b..d6eb50c 100644 --- a/src/platforms/native/platform.c +++ b/src/platforms/native/platform.c @@ -123,7 +123,7 @@ int platform_init(void) cdcacm_init(); jtag_scan(NULL); - + return 0; } diff --git a/src/platforms/native/platform.h b/src/platforms/native/platform.h index a1471dc..fa9fc79 100644 --- a/src/platforms/native/platform.h +++ b/src/platforms/native/platform.h @@ -60,7 +60,7 @@ extern usbd_device *usbdev; * nSRST = PA7 (input) * * USB cable pull-up: PA8 - * USB VBUS detect: PB13 -- New on mini design. + * USB VBUS detect: PB13 -- New on mini design. * Enable pull up for compatibility. * Force DFU mode button: PB12 */ @@ -118,7 +118,7 @@ extern usbd_device *usbdev; #define USB_ISR usb_lp_can_rx0_isr /* Interrupt priorities. Low numbers are high priority. * For now USART1 preempts USB which may spin while buffer is drained. - * TIM3 is used for traceswo capture and must be highest priority. + * TIM3 is used for traceswo capture and must be highest priority. */ #define IRQ_PRI_USB (2 << 4) #define IRQ_PRI_USBUSART (1 << 4) diff --git a/src/platforms/stlink/platform.c b/src/platforms/stlink/platform.c index 08fcd32..03509ea 100644 --- a/src/platforms/stlink/platform.c +++ b/src/platforms/stlink/platform.c @@ -92,23 +92,23 @@ int platform_init(void) GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO8); } /* Setup GPIO ports */ - gpio_set_mode(TMS_PORT, GPIO_MODE_OUTPUT_50_MHZ, + gpio_set_mode(TMS_PORT, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, TMS_PIN); - gpio_set_mode(TCK_PORT, GPIO_MODE_OUTPUT_50_MHZ, + gpio_set_mode(TCK_PORT, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, TCK_PIN); - gpio_set_mode(TDI_PORT, GPIO_MODE_OUTPUT_50_MHZ, + gpio_set_mode(TDI_PORT, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, TDI_PIN); uint16_t srst_pin = platform_hwversion() == 0 ? SRST_PIN_V1 : SRST_PIN_V2; gpio_set(SRST_PORT, srst_pin); - gpio_set_mode(SRST_PORT, GPIO_MODE_OUTPUT_50_MHZ, + gpio_set_mode(SRST_PORT, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, srst_pin); - - gpio_set_mode(LED_PORT, GPIO_MODE_OUTPUT_2_MHZ, + + gpio_set_mode(LED_PORT, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, led_idle_run); /* Setup heartbeat timer */ - systick_set_clocksource(STK_CTRL_CLKSOURCE_AHB_DIV8); + systick_set_clocksource(STK_CTRL_CLKSOURCE_AHB_DIV8); systick_set_reload(900000); /* Interrupt us at 10 Hz */ SCB_SHPR(11) &= ~((15 << 4) & 0xff); SCB_SHPR(11) |= ((14 << 4) & 0xff); @@ -122,7 +122,7 @@ int platform_init(void) cdcacm_init(); jtag_scan(NULL); - + return 0; } @@ -144,10 +144,10 @@ void platform_srst_set_val(bool assert) void sys_tick_handler(void) { - if(running_status) + if(running_status) gpio_toggle(LED_PORT, led_idle_run); - if(timeout_counter) + if(timeout_counter) timeout_counter--; } diff --git a/src/platforms/stlink/platform.h b/src/platforms/stlink/platform.h index 1ee944c..029eb0a 100644 --- a/src/platforms/stlink/platform.h +++ b/src/platforms/stlink/platform.h @@ -59,7 +59,7 @@ extern usbd_device *usbdev; * nSRST = PA7 (input) * * USB cable pull-up: PA8 - * USB VBUS detect: PB13 -- New on mini design. + * USB VBUS detect: PB13 -- New on mini design. * Enable pull up for compatibility. * Force DFU mode button: PB12 */ diff --git a/src/platforms/stm32/swdptap.c b/src/platforms/stm32/swdptap.c index 72fb0f9..e7049d3 100644 --- a/src/platforms/stm32/swdptap.c +++ b/src/platforms/stm32/swdptap.c @@ -73,9 +73,9 @@ int swdptap_init(void) /* This must be investigated in more detail. * As described in STM32 Reference Manual... */ swdptap_reset(); - swdptap_seq_out(0xE79E, 16); /* 0b0111100111100111 */ + swdptap_seq_out(0xE79E, 16); /* 0b0111100111100111 */ swdptap_reset(); - swdptap_seq_out(0, 16); + swdptap_seq_out(0, 16); return 0; } @@ -132,7 +132,7 @@ void swdptap_seq_out(uint32_t MS, int ticks) while(ticks--) { swdptap_bit_out(MS & 1); - MS >>= 1; + MS >>= 1; } } @@ -146,7 +146,7 @@ void swdptap_seq_out_parity(uint32_t MS, int ticks) while(ticks--) { swdptap_bit_out(MS & 1); parity ^= MS; - MS >>= 1; + MS >>= 1; } swdptap_bit_out(parity & 1); } diff --git a/src/platforms/swlink/platform.c b/src/platforms/swlink/platform.c index 1aa45b1..1b45cfb 100644 --- a/src/platforms/swlink/platform.c +++ b/src/platforms/swlink/platform.c @@ -86,7 +86,7 @@ int platform_init(void) AFIO_MAPR = data; /* Setup heartbeat timer */ - systick_set_clocksource(STK_CTRL_CLKSOURCE_AHB_DIV8); + systick_set_clocksource(STK_CTRL_CLKSOURCE_AHB_DIV8); systick_set_reload(900000); /* Interrupt us at 10 Hz */ SCB_SHPR(11) &= ~((15 << 4) & 0xff); SCB_SHPR(11) |= ((14 << 4) & 0xff); @@ -112,10 +112,10 @@ void platform_delay(uint32_t delay) void sys_tick_handler(void) { - if(running_status) + if(running_status) gpio_toggle(LED_PORT, led_idle_run); - if(timeout_counter) + if(timeout_counter) timeout_counter--; } diff --git a/src/platforms/swlink/platform.h b/src/platforms/swlink/platform.h index 469499f..7d36326 100644 --- a/src/platforms/swlink/platform.h +++ b/src/platforms/swlink/platform.h @@ -53,7 +53,7 @@ extern usbd_device *usbdev; * nSRST = PA7 (input) * * USB cable pull-up: PA8 - * USB VBUS detect: PB13 -- New on mini design. + * USB VBUS detect: PB13 -- New on mini design. * Enable pull up for compatibility. * Force DFU mode button: PB9 Low */ diff --git a/src/sam3x.c b/src/sam3x.c index 3c5cc2e..79dca3d 100644 --- a/src/sam3x.c +++ b/src/sam3x.c @@ -32,7 +32,7 @@ #include "gdb_packet.h" static int sam3x_flash_erase(struct target_s *target, uint32_t addr, int len); -static int sam3x_flash_write(struct target_s *target, uint32_t dest, +static int sam3x_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, int len); static bool sam3x_cmd_gpnvm_get(target *t); diff --git a/src/stm32f1.c b/src/stm32f1.c index 4cc7b2a..03dcc43 100644 --- a/src/stm32f1.c +++ b/src/stm32f1.c @@ -50,9 +50,9 @@ const struct command_s stm32f1_cmd_list[] = { static int stm32md_flash_erase(struct target_s *target, uint32_t addr, int len); static int stm32hd_flash_erase(struct target_s *target, uint32_t addr, int len); -static int stm32f1_flash_erase(struct target_s *target, uint32_t addr, int len, +static int stm32f1_flash_erase(struct target_s *target, uint32_t addr, int len, uint32_t pagesize); -static int stm32f1_flash_write(struct target_s *target, uint32_t dest, +static int stm32f1_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, int len); static const char stm32f1_driver_str[] = "STM32, Medium density."; @@ -103,7 +103,7 @@ static const char stm32hd_xml_memory_map[] = "" #define FLASH_SR_BSY (1 << 0) -#define FLASH_OBP_RDP 0x1FFFF800 +#define FLASH_OBP_RDP 0x1FFFF800 #define FLASH_OBP_RDP_KEY 0x5aa5 #define FLASH_OBP_RDP_KEY_F3 0x55AA @@ -220,7 +220,7 @@ static int stm32f1_flash_erase(struct target_s *target, uint32_t addr, int len, /* Flash page erase instruction */ adiv5_ap_mem_write(ap, FLASH_CR, FLASH_CR_PER); /* write address to FMA */ - adiv5_ap_mem_write(ap, FLASH_AR, addr); + adiv5_ap_mem_write(ap, FLASH_AR, addr); /* Flash page erase start instruction */ adiv5_ap_mem_write(ap, FLASH_CR, FLASH_CR_STRT | FLASH_CR_PER); @@ -251,7 +251,7 @@ static int stm32md_flash_erase(struct target_s *target, uint32_t addr, int len) return stm32f1_flash_erase(target, addr, len, 0x400); } -static int stm32f1_flash_write(struct target_s *target, uint32_t dest, +static int stm32f1_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, int len) { ADIv5_AP_t *ap = adiv5_target_ap(target); @@ -287,7 +287,7 @@ static int stm32f1_flash_write(struct target_s *target, uint32_t dest, static bool stm32f1_cmd_erase_mass(target *t) { ADIv5_AP_t *ap = adiv5_target_ap(t); - + stm32f1_flash_unlock(ap); /* Flash mass erase start instruction */ @@ -313,7 +313,7 @@ static bool stm32f1_option_erase(target *t) /* Erase option bytes instruction */ adiv5_ap_mem_write(ap, FLASH_CR, FLASH_CR_OPTER | FLASH_CR_OPTWRE); - adiv5_ap_mem_write(ap, FLASH_CR, + adiv5_ap_mem_write(ap, FLASH_CR, FLASH_CR_STRT | FLASH_CR_OPTER | FLASH_CR_OPTWRE); /* Read FLASH_SR to poll for BSY bit */ while(adiv5_ap_mem_read(ap, FLASH_SR) & FLASH_SR_BSY) diff --git a/src/stm32f4.c b/src/stm32f4.c index b9764cc..471f167 100644 --- a/src/stm32f4.c +++ b/src/stm32f4.c @@ -50,7 +50,7 @@ const struct command_s stm32f4_cmd_list[] = { static int stm32f4_flash_erase(struct target_s *target, uint32_t addr, int len); -static int stm32f4_flash_write(struct target_s *target, uint32_t dest, +static int stm32f4_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, int len); static const char stm32f4_driver_str[] = "STM32F4xx"; @@ -218,11 +218,11 @@ static int stm32f4_flash_erase(struct target_s *target, uint32_t addr, int len) /* Flash page erase instruction */ adiv5_ap_mem_write(ap, FLASH_CR, cr); /* write address to FMA */ - adiv5_ap_mem_write(ap, FLASH_CR, cr | FLASH_CR_STRT); + adiv5_ap_mem_write(ap, FLASH_CR, cr | FLASH_CR_STRT); /* Read FLASH_SR to poll for BSY bit */ while(adiv5_ap_mem_read(ap, FLASH_SR) & FLASH_SR_BSY) - if(target_check_error(target)) + if(target_check_error(target)) return -1; len -= pagesize; @@ -237,7 +237,7 @@ static int stm32f4_flash_erase(struct target_s *target, uint32_t addr, int len) return 0; } -static int stm32f4_flash_write(struct target_s *target, uint32_t dest, +static int stm32f4_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, int len) { ADIv5_AP_t *ap = adiv5_target_ap(target); @@ -257,7 +257,7 @@ static int stm32f4_flash_write(struct target_s *target, uint32_t dest, target_mem_write_words(target, 0x20000000, (void*)stm32f4_flash_write_stub, 0x30); target_mem_write_words(target, 0x20000030, data, sizeof(data)); target_pc_write(target, 0x20000000); - if(target_check_error(target)) + if(target_check_error(target)) return -1; /* Execute the stub */ diff --git a/src/stm32l1.c b/src/stm32l1.c index 8fd25f7..325b415 100644 --- a/src/stm32l1.c +++ b/src/stm32l1.c @@ -39,7 +39,7 @@ #include "gdb_packet.h" static int stm32l1_flash_erase(struct target_s *target, uint32_t addr, int len); -static int stm32l1_flash_write(struct target_s *target, uint32_t dest, +static int stm32l1_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, int len); static const char stm32l1_driver_str[] = "STM32L1xx"; @@ -148,7 +148,7 @@ static int stm32l1_flash_erase(struct target_s *target, uint32_t addr, int len) return 0; } -static int stm32l1_flash_write(struct target_s *target, uint32_t dest, +static int stm32l1_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, int len) { ADIv5_AP_t *ap = adiv5_target_ap(target); -- cgit v1.2.3 From 3caaa28fa14834044f5c572ae964732df0314582 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Mon, 17 Jun 2013 15:57:13 +1200 Subject: Fix warning about implicit cast. --- src/lpc43xx.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/lpc43xx.c b/src/lpc43xx.c index 200a8a4..0a8745d 100644 --- a/src/lpc43xx.c +++ b/src/lpc43xx.c @@ -452,7 +452,9 @@ static int lpc43xx_flash_write(struct target_s *target, uint32_t dest, const uin } /* copy buffer into target memory */ - target_mem_write_words(target, IAP_RAM_BASE + offsetof(struct flash_program, data), flash_pgm.data, sizeof(flash_pgm.data)); + target_mem_write_words(target, + IAP_RAM_BASE + offsetof(struct flash_program, data), + (uint32_t*)flash_pgm.data, sizeof(flash_pgm.data)); /* set the destination address and program */ flash_pgm.p.command = IAP_CMD_PROGRAM; -- cgit v1.2.3 From c05b7a1f63d91554486cd0385db496cb71781ee8 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Mon, 17 Jun 2013 16:06:03 +1200 Subject: Rename lpc11xx driver. --- src/Makefile | 2 +- src/lpc11xx.c | 254 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/nxp_tgt.c | 254 ---------------------------------------------------------- 3 files changed, 255 insertions(+), 255 deletions(-) create mode 100644 src/lpc11xx.c delete mode 100644 src/nxp_tgt.c (limited to 'src') diff --git a/src/Makefile b/src/Makefile index d9f3e9e..8ec9f13 100644 --- a/src/Makefile +++ b/src/Makefile @@ -25,9 +25,9 @@ SRC = \ jtag_scan.c \ jtagtap.c \ lmi.c \ + lpc11xx.c \ lpc43xx.c \ main.c \ - nxp_tgt.c \ platform.c \ sam3x.c \ stm32f1.c \ diff --git a/src/lpc11xx.c b/src/lpc11xx.c new file mode 100644 index 0000000..83f37ba --- /dev/null +++ b/src/lpc11xx.c @@ -0,0 +1,254 @@ + +#include +#include +#include + +#include "general.h" +#include "adiv5.h" +#include "target.h" + +#define IAP_PGM_CHUNKSIZE 256 /* should fit in RAM on any device */ + +struct flash_param { + uint16_t opcodes[2]; /* two opcodes to return to after calling the ROM */ + uint32_t command[5]; /* command operands */ + uint32_t result[4]; /* result data */ +}; + +struct flash_program { + struct flash_param p; + uint8_t data[IAP_PGM_CHUNKSIZE]; +}; + +static struct flash_program flash_pgm; + +#define MSP 17 // Main stack pointer register number +#define MIN_RAM_SIZE_FOR_LPC1xxx 2048 +#define RAM_USAGE_FOR_IAP_ROUTINES 32 // IAP routines use 32 bytes at top of ram + +#define IAP_ENTRYPOINT 0x1fff1ff1 +#define IAP_RAM_BASE 0x10000000 + + +#define IAP_CMD_PREPARE 50 +#define IAP_CMD_PROGRAM 51 +#define IAP_CMD_ERASE 52 +#define IAP_CMD_BLANKCHECK 53 + +#define IAP_STATUS_CMD_SUCCESS 0 +#define IAP_STATUS_INVALID_COMMAND 1 +#define IAP_STATUS_SRC_ADDR_ERROR 2 +#define IAP_STATUS_DST_ADDR_ERROR 3 +#define IAP_STATUS_SRC_ADDR_NOT_MAPPED 4 +#define IAP_STATUS_DST_ADDR_NOT_MAPPED 5 +#define IAP_STATUS_COUNT_ERROR 6 +#define IAP_STATUS_INVALID_SECTOR 7 +#define IAP_STATUS_SECTOR_NOT_BLANK 8 +#define IAP_STATUS_SECTOR_NOT_PREPARED 9 +#define IAP_STATUS_COMPARE_ERROR 10 +#define IAP_STATUS_BUSY 11 + +static void lpc11x_iap_call(struct target_s *target, struct flash_param *param, unsigned param_len); +static int lpc11xx_flash_prepare(struct target_s *target, uint32_t addr, int len); +static int lpc11xx_flash_erase(struct target_s *target, uint32_t addr, int len); +static int lpc11xx_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, + int len); + +/* + * Note that this memory map is actually for the largest of the lpc11xx devices; + * There seems to be no good way to decode the part number to determine the RAM + * and flash sizes. + */ +static const char lpc11xx_xml_memory_map[] = "" +/* ""*/ + "" + " " + " 0x1000" + " " + " " + ""; + + +bool +lpc11xx_probe(struct target_s *target) +{ + uint32_t idcode; + + /* read the device ID register */ + idcode = adiv5_ap_mem_read(adiv5_target_ap(target), 0x400483F4); + + switch (idcode) { + + case 0x041E502B: + case 0x2516D02B: + case 0x0416502B: + case 0x2516902B: /* lpc1111 */ + case 0x2524D02B: + case 0x0425502B: + case 0x2524902B: + case 0x1421102B: /* lpc1112 */ + case 0x0434502B: + case 0x2532902B: + case 0x0434102B: + case 0x2532102B: /* lpc1113 */ + case 0x0444502B: + case 0x2540902B: + case 0x0444102B: + case 0x2540102B: + case 0x1440102B: /* lpc1114 */ + case 0x0A40902B: + case 0x1A40902B: + case 0x1431102B: /* lpc11c22 */ + case 0x1430102B: /* lpc11c24 */ + target->driver = "lpc11xx"; + target->xml_mem_map = lpc11xx_xml_memory_map; + target->flash_erase = lpc11xx_flash_erase; + target->flash_write = lpc11xx_flash_write; + + return true; + } + + return false; +} + +static void +lpc11x_iap_call(struct target_s *target, struct flash_param *param, unsigned param_len) +{ + uint32_t regs[target->regs_size / 4]; + + /* fill out the remainder of the parameters and copy the structure to RAM */ + param->opcodes[0] = 0xbe00; + param->opcodes[1] = 0x0000; + target_mem_write_words(target, IAP_RAM_BASE, (void *)param, param_len); + + /* set up for the call to the IAP ROM */ + target_regs_read(target, regs); + regs[0] = IAP_RAM_BASE + offsetof(struct flash_param, command); + regs[1] = IAP_RAM_BASE + offsetof(struct flash_param, result); + + regs[MSP] = IAP_RAM_BASE + MIN_RAM_SIZE_FOR_LPC1xxx - RAM_USAGE_FOR_IAP_ROUTINES;// stack pointer - top of the smallest ram less 32 for IAP usage + regs[14] = IAP_RAM_BASE | 1; + regs[15] = IAP_ENTRYPOINT; + target_regs_write(target, regs); + + /* start the target and wait for it to halt again */ + target_halt_resume(target, 0); + while (!target_halt_wait(target)); + + /* copy back just the parameters structure */ + target_mem_read_words(target, (void *)param, IAP_RAM_BASE, sizeof(struct flash_param)); +} + +static int +lpc11xx_flash_prepare(struct target_s *target, uint32_t addr, int len) +{ + /* prepare the sector(s) to be erased */ + memset(&flash_pgm.p, 0, sizeof(flash_pgm.p)); + flash_pgm.p.command[0] = IAP_CMD_PREPARE; + flash_pgm.p.command[1] = addr / 4096; + flash_pgm.p.command[2] = (addr + len - 1) / 4096; + + lpc11x_iap_call(target, &flash_pgm.p, sizeof(flash_pgm.p)); + if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { + return -1; + } + + return 0; +} + +static int +lpc11xx_flash_erase(struct target_s *target, uint32_t addr, int len) +{ + + if (addr % 4096) + return -1; + + /* prepare... */ + if (lpc11xx_flash_prepare(target, addr, len)) + return -1; + + /* and now erase them */ + flash_pgm.p.command[0] = IAP_CMD_ERASE; + flash_pgm.p.command[1] = addr / 4096; + flash_pgm.p.command[2] = (addr + len - 1) / 4096; + flash_pgm.p.command[3] = 12000; /* XXX safe to assume this? */ + lpc11x_iap_call(target, &flash_pgm.p, sizeof(flash_pgm.p)); + if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { + return -1; + } + flash_pgm.p.command[0] = IAP_CMD_BLANKCHECK; + lpc11x_iap_call(target, &flash_pgm.p, sizeof(flash_pgm.p)); + if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { + return -1; + } + + return 0; +} + +static int +lpc11xx_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, int len) +{ + unsigned first_chunk = dest / IAP_PGM_CHUNKSIZE; + unsigned last_chunk = (dest + len - 1) / IAP_PGM_CHUNKSIZE; + unsigned chunk_offset = dest % IAP_PGM_CHUNKSIZE; + unsigned chunk; + + for (chunk = first_chunk; chunk <= last_chunk; chunk++) { + + DEBUG("chunk %u len %d\n", chunk, len); + /* first and last chunk may require special handling */ + if ((chunk == first_chunk) || (chunk == last_chunk)) { + + /* fill with all ff to avoid sector rewrite corrupting other writes */ + memset(flash_pgm.data, 0xff, sizeof(flash_pgm.data)); + + /* copy as much as fits */ + int copylen = IAP_PGM_CHUNKSIZE - chunk_offset; + if (copylen > len) + copylen = len; + memcpy(&flash_pgm.data[chunk_offset], src, copylen); + + /* update to suit */ + len -= copylen; + src += copylen; + chunk_offset = 0; + + /* if we are programming the vectors, calculate the magic number */ + if (chunk == 0) { + uint32_t *w = (uint32_t *)(&flash_pgm.data[0]); + uint32_t sum = 0; + + for (unsigned i = 0; i < 7; i++) + sum += w[i]; + w[7] = 0 - sum; + } + + } else { + + /* interior chunk, must be aligned and full-sized */ + memcpy(flash_pgm.data, src, IAP_PGM_CHUNKSIZE); + len -= IAP_PGM_CHUNKSIZE; + src += IAP_PGM_CHUNKSIZE; + } + + /* prepare... */ + if (lpc11xx_flash_prepare(target, chunk * IAP_PGM_CHUNKSIZE, IAP_PGM_CHUNKSIZE)) + return -1; + + /* set the destination address and program */ + flash_pgm.p.command[0] = IAP_CMD_PROGRAM; + flash_pgm.p.command[1] = chunk * IAP_PGM_CHUNKSIZE; + flash_pgm.p.command[2] = IAP_RAM_BASE + offsetof(struct flash_program, data); + flash_pgm.p.command[3] = IAP_PGM_CHUNKSIZE; + flash_pgm.p.command[4] = 12000; /* XXX safe to presume this? */ + lpc11x_iap_call(target, &flash_pgm.p, sizeof(flash_pgm)); + if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { + return -1; + } + + } + + return 0; +} diff --git a/src/nxp_tgt.c b/src/nxp_tgt.c deleted file mode 100644 index 83f37ba..0000000 --- a/src/nxp_tgt.c +++ /dev/null @@ -1,254 +0,0 @@ - -#include -#include -#include - -#include "general.h" -#include "adiv5.h" -#include "target.h" - -#define IAP_PGM_CHUNKSIZE 256 /* should fit in RAM on any device */ - -struct flash_param { - uint16_t opcodes[2]; /* two opcodes to return to after calling the ROM */ - uint32_t command[5]; /* command operands */ - uint32_t result[4]; /* result data */ -}; - -struct flash_program { - struct flash_param p; - uint8_t data[IAP_PGM_CHUNKSIZE]; -}; - -static struct flash_program flash_pgm; - -#define MSP 17 // Main stack pointer register number -#define MIN_RAM_SIZE_FOR_LPC1xxx 2048 -#define RAM_USAGE_FOR_IAP_ROUTINES 32 // IAP routines use 32 bytes at top of ram - -#define IAP_ENTRYPOINT 0x1fff1ff1 -#define IAP_RAM_BASE 0x10000000 - - -#define IAP_CMD_PREPARE 50 -#define IAP_CMD_PROGRAM 51 -#define IAP_CMD_ERASE 52 -#define IAP_CMD_BLANKCHECK 53 - -#define IAP_STATUS_CMD_SUCCESS 0 -#define IAP_STATUS_INVALID_COMMAND 1 -#define IAP_STATUS_SRC_ADDR_ERROR 2 -#define IAP_STATUS_DST_ADDR_ERROR 3 -#define IAP_STATUS_SRC_ADDR_NOT_MAPPED 4 -#define IAP_STATUS_DST_ADDR_NOT_MAPPED 5 -#define IAP_STATUS_COUNT_ERROR 6 -#define IAP_STATUS_INVALID_SECTOR 7 -#define IAP_STATUS_SECTOR_NOT_BLANK 8 -#define IAP_STATUS_SECTOR_NOT_PREPARED 9 -#define IAP_STATUS_COMPARE_ERROR 10 -#define IAP_STATUS_BUSY 11 - -static void lpc11x_iap_call(struct target_s *target, struct flash_param *param, unsigned param_len); -static int lpc11xx_flash_prepare(struct target_s *target, uint32_t addr, int len); -static int lpc11xx_flash_erase(struct target_s *target, uint32_t addr, int len); -static int lpc11xx_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, - int len); - -/* - * Note that this memory map is actually for the largest of the lpc11xx devices; - * There seems to be no good way to decode the part number to determine the RAM - * and flash sizes. - */ -static const char lpc11xx_xml_memory_map[] = "" -/* ""*/ - "" - " " - " 0x1000" - " " - " " - ""; - - -bool -lpc11xx_probe(struct target_s *target) -{ - uint32_t idcode; - - /* read the device ID register */ - idcode = adiv5_ap_mem_read(adiv5_target_ap(target), 0x400483F4); - - switch (idcode) { - - case 0x041E502B: - case 0x2516D02B: - case 0x0416502B: - case 0x2516902B: /* lpc1111 */ - case 0x2524D02B: - case 0x0425502B: - case 0x2524902B: - case 0x1421102B: /* lpc1112 */ - case 0x0434502B: - case 0x2532902B: - case 0x0434102B: - case 0x2532102B: /* lpc1113 */ - case 0x0444502B: - case 0x2540902B: - case 0x0444102B: - case 0x2540102B: - case 0x1440102B: /* lpc1114 */ - case 0x0A40902B: - case 0x1A40902B: - case 0x1431102B: /* lpc11c22 */ - case 0x1430102B: /* lpc11c24 */ - target->driver = "lpc11xx"; - target->xml_mem_map = lpc11xx_xml_memory_map; - target->flash_erase = lpc11xx_flash_erase; - target->flash_write = lpc11xx_flash_write; - - return true; - } - - return false; -} - -static void -lpc11x_iap_call(struct target_s *target, struct flash_param *param, unsigned param_len) -{ - uint32_t regs[target->regs_size / 4]; - - /* fill out the remainder of the parameters and copy the structure to RAM */ - param->opcodes[0] = 0xbe00; - param->opcodes[1] = 0x0000; - target_mem_write_words(target, IAP_RAM_BASE, (void *)param, param_len); - - /* set up for the call to the IAP ROM */ - target_regs_read(target, regs); - regs[0] = IAP_RAM_BASE + offsetof(struct flash_param, command); - regs[1] = IAP_RAM_BASE + offsetof(struct flash_param, result); - - regs[MSP] = IAP_RAM_BASE + MIN_RAM_SIZE_FOR_LPC1xxx - RAM_USAGE_FOR_IAP_ROUTINES;// stack pointer - top of the smallest ram less 32 for IAP usage - regs[14] = IAP_RAM_BASE | 1; - regs[15] = IAP_ENTRYPOINT; - target_regs_write(target, regs); - - /* start the target and wait for it to halt again */ - target_halt_resume(target, 0); - while (!target_halt_wait(target)); - - /* copy back just the parameters structure */ - target_mem_read_words(target, (void *)param, IAP_RAM_BASE, sizeof(struct flash_param)); -} - -static int -lpc11xx_flash_prepare(struct target_s *target, uint32_t addr, int len) -{ - /* prepare the sector(s) to be erased */ - memset(&flash_pgm.p, 0, sizeof(flash_pgm.p)); - flash_pgm.p.command[0] = IAP_CMD_PREPARE; - flash_pgm.p.command[1] = addr / 4096; - flash_pgm.p.command[2] = (addr + len - 1) / 4096; - - lpc11x_iap_call(target, &flash_pgm.p, sizeof(flash_pgm.p)); - if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { - return -1; - } - - return 0; -} - -static int -lpc11xx_flash_erase(struct target_s *target, uint32_t addr, int len) -{ - - if (addr % 4096) - return -1; - - /* prepare... */ - if (lpc11xx_flash_prepare(target, addr, len)) - return -1; - - /* and now erase them */ - flash_pgm.p.command[0] = IAP_CMD_ERASE; - flash_pgm.p.command[1] = addr / 4096; - flash_pgm.p.command[2] = (addr + len - 1) / 4096; - flash_pgm.p.command[3] = 12000; /* XXX safe to assume this? */ - lpc11x_iap_call(target, &flash_pgm.p, sizeof(flash_pgm.p)); - if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { - return -1; - } - flash_pgm.p.command[0] = IAP_CMD_BLANKCHECK; - lpc11x_iap_call(target, &flash_pgm.p, sizeof(flash_pgm.p)); - if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { - return -1; - } - - return 0; -} - -static int -lpc11xx_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, int len) -{ - unsigned first_chunk = dest / IAP_PGM_CHUNKSIZE; - unsigned last_chunk = (dest + len - 1) / IAP_PGM_CHUNKSIZE; - unsigned chunk_offset = dest % IAP_PGM_CHUNKSIZE; - unsigned chunk; - - for (chunk = first_chunk; chunk <= last_chunk; chunk++) { - - DEBUG("chunk %u len %d\n", chunk, len); - /* first and last chunk may require special handling */ - if ((chunk == first_chunk) || (chunk == last_chunk)) { - - /* fill with all ff to avoid sector rewrite corrupting other writes */ - memset(flash_pgm.data, 0xff, sizeof(flash_pgm.data)); - - /* copy as much as fits */ - int copylen = IAP_PGM_CHUNKSIZE - chunk_offset; - if (copylen > len) - copylen = len; - memcpy(&flash_pgm.data[chunk_offset], src, copylen); - - /* update to suit */ - len -= copylen; - src += copylen; - chunk_offset = 0; - - /* if we are programming the vectors, calculate the magic number */ - if (chunk == 0) { - uint32_t *w = (uint32_t *)(&flash_pgm.data[0]); - uint32_t sum = 0; - - for (unsigned i = 0; i < 7; i++) - sum += w[i]; - w[7] = 0 - sum; - } - - } else { - - /* interior chunk, must be aligned and full-sized */ - memcpy(flash_pgm.data, src, IAP_PGM_CHUNKSIZE); - len -= IAP_PGM_CHUNKSIZE; - src += IAP_PGM_CHUNKSIZE; - } - - /* prepare... */ - if (lpc11xx_flash_prepare(target, chunk * IAP_PGM_CHUNKSIZE, IAP_PGM_CHUNKSIZE)) - return -1; - - /* set the destination address and program */ - flash_pgm.p.command[0] = IAP_CMD_PROGRAM; - flash_pgm.p.command[1] = chunk * IAP_PGM_CHUNKSIZE; - flash_pgm.p.command[2] = IAP_RAM_BASE + offsetof(struct flash_program, data); - flash_pgm.p.command[3] = IAP_PGM_CHUNKSIZE; - flash_pgm.p.command[4] = 12000; /* XXX safe to presume this? */ - lpc11x_iap_call(target, &flash_pgm.p, sizeof(flash_pgm)); - if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { - return -1; - } - - } - - return 0; -} -- cgit v1.2.3 From 27a86e244f6dd913b58fd18d40e470ef20810881 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Wed, 19 Jun 2013 19:21:49 +1200 Subject: native: Enable hard SRST signal. --- src/platforms/native/platform.c | 15 ++++++++++++++- src/platforms/native/platform.h | 3 +++ 2 files changed, 17 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/platforms/native/platform.c b/src/platforms/native/platform.c index d6eb50c..f5b9135 100644 --- a/src/platforms/native/platform.c +++ b/src/platforms/native/platform.c @@ -82,7 +82,6 @@ int platform_init(void) gpio_set_mode(JTAG_PORT, GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, TMS_PIN | TCK_PIN | TDI_PIN); - /* This needs some fixing... */ /* Toggle required to sort out line drivers... */ gpio_port_write(GPIOA, 0x8100); @@ -99,6 +98,11 @@ int platform_init(void) * to release the device from reset if this floats. */ gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO7); + /* Enable SRST output */ + gpio_set_val(SRST_PORT, SRST_PIN, platform_hwversion() > 0); + gpio_set_mode(SRST_PORT, GPIO_MODE_OUTPUT_50_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, + SRST_PIN); /* Setup heartbeat timer */ systick_set_clocksource(STK_CTRL_CLKSOURCE_AHB_DIV8); @@ -127,6 +131,15 @@ int platform_init(void) return 0; } +void platform_srst_set_val(bool assert) +{ + if (platform_hwversion() == 0) { + gpio_set_val(SRST_PORT, SRST_PIN, assert); + } else { + gpio_set_val(SRST_PORT, SRST_PIN, !assert); + } +} + void platform_delay(uint32_t delay) { timeout_counter = delay; diff --git a/src/platforms/native/platform.h b/src/platforms/native/platform.h index fa9fc79..fd456d8 100644 --- a/src/platforms/native/platform.h +++ b/src/platforms/native/platform.h @@ -113,6 +113,9 @@ extern usbd_device *usbdev; gpio_set_mode(USBUSART_PORT, GPIO_MODE_OUTPUT_2_MHZ, \ GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, USBUSART_TX_PIN); +#define SRST_SET_VAL(x) \ + platform_srst_set_val(x) + #define USB_DRIVER stm32f103_usb_driver #define USB_IRQ NVIC_USB_LP_CAN_RX0_IRQ #define USB_ISR usb_lp_can_rx0_isr -- cgit v1.2.3 From d90e10cdbaa05509d1ee78f982d3aa0a2c94e972 Mon Sep 17 00:00:00 2001 From: Paul Fertser Date: Sun, 5 May 2013 00:46:49 +0400 Subject: adiv5_swdp: avoid dead-loop with a sleeping target A sleeping target continues to communicate over SWD properly but consistently returns SWDP_ACK_WAIT. It might be nice to be able to wait for the target to wake up on its own but if it's not going to wake up, BMP becomes absolutely unresponsive. Probably the timeout should be made configurable or some other workaround invented. Signed-off-by: Paul Fertser --- src/adiv5_swdp.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/adiv5_swdp.c b/src/adiv5_swdp.c index 8a38330..839127d 100644 --- a/src/adiv5_swdp.c +++ b/src/adiv5_swdp.c @@ -129,10 +129,14 @@ static uint32_t adiv5_swdp_low_access(ADIv5_DP_t *dp, uint8_t APnDP, uint8_t RnW if((addr == 4) || (addr == 8)) request ^= 0x20; + size_t tries = 1000; do { swdptap_seq_out(request, 8); ack = swdptap_seq_in(3); - } while(ack == SWDP_ACK_WAIT); + } while(--tries && ack == SWDP_ACK_WAIT); + + if(!tries) + PLATFORM_FATAL_ERROR(1); if(ack == SWDP_ACK_FAULT) { dp->fault = 1; -- cgit v1.2.3 From d8f737fc53fa27bb13a934f94e39157748401ce4 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Wed, 19 Jun 2013 21:05:53 +1200 Subject: Disable ADIv5 timeout while target is running. --- src/adiv5_jtagdp.c | 6 +++++- src/adiv5_swdp.c | 4 ++-- src/cortexm.c | 4 ++++ src/include/adiv5.h | 2 ++ 4 files changed, 13 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/adiv5_jtagdp.c b/src/adiv5_jtagdp.c index 693b94e..4306101 100644 --- a/src/adiv5_jtagdp.c +++ b/src/adiv5_jtagdp.c @@ -92,10 +92,14 @@ static uint32_t adiv5_jtagdp_low_access(ADIv5_DP_t *dp, uint8_t APnDP, uint8_t R jtag_dev_write_ir(dp->dev, APnDP?IR_APACC:IR_DPACC); + int tries = 1000; do { jtag_dev_shift_dr(dp->dev, (uint8_t*)&response, (uint8_t*)&request, 35); ack = response & 0x07; - } while(ack == JTAGDP_ACK_WAIT); + } while(--tries && (ack == JTAGDP_ACK_WAIT)); + + if (dp->allow_timeout && (ack == JTAGDP_ACK_WAIT)) + return 0; if((ack != JTAGDP_ACK_OK)) { /* Fatal error if invalid ACK response */ diff --git a/src/adiv5_swdp.c b/src/adiv5_swdp.c index 839127d..c021190 100644 --- a/src/adiv5_swdp.c +++ b/src/adiv5_swdp.c @@ -135,8 +135,8 @@ static uint32_t adiv5_swdp_low_access(ADIv5_DP_t *dp, uint8_t APnDP, uint8_t RnW ack = swdptap_seq_in(3); } while(--tries && ack == SWDP_ACK_WAIT); - if(!tries) - PLATFORM_FATAL_ERROR(1); + if (dp->allow_timeout && (ack == SWDP_ACK_WAIT)) + return 0; if(ack == SWDP_ACK_FAULT) { dp->fault = 1; diff --git a/src/cortexm.c b/src/cortexm.c index 7819598..a8bb34b 100644 --- a/src/cortexm.c +++ b/src/cortexm.c @@ -584,6 +584,7 @@ cortexm_halt_request(struct target_s *target) { ADIv5_AP_t *ap = adiv5_target_ap(target); + ap->dp->allow_timeout = false; adiv5_ap_mem_write(ap, CORTEXM_DHCSR, CORTEXM_DHCSR_DBGKEY | CORTEXM_DHCSR_C_HALT | CORTEXM_DHCSR_C_DEBUGEN); } @@ -596,6 +597,8 @@ cortexm_halt_wait(struct target_s *target) if (!(adiv5_ap_mem_read(ap, CORTEXM_DHCSR) & CORTEXM_DHCSR_S_HALT)) return 0; + ap->dp->allow_timeout = false; + /* We've halted. Let's find out why. */ uint32_t dfsr = adiv5_ap_mem_read(ap, CORTEXM_DFSR); adiv5_ap_mem_write(ap, CORTEXM_DFSR, dfsr); /* write back to reset */ @@ -654,6 +657,7 @@ cortexm_halt_resume(struct target_s *target, bool step) } adiv5_ap_mem_write(ap, CORTEXM_DHCSR, dhcsr); + ap->dp->allow_timeout = true; } static int cortexm_fault_unwind(struct target_s *target) diff --git a/src/include/adiv5.h b/src/include/adiv5.h index 1bfb5a1..64b6a28 100644 --- a/src/include/adiv5.h +++ b/src/include/adiv5.h @@ -106,6 +106,8 @@ typedef struct ADIv5_DP_s { uint32_t idcode; + bool allow_timeout; + void (*dp_write)(struct ADIv5_DP_s *dp, uint8_t addr, uint32_t value); uint32_t (*dp_read)(struct ADIv5_DP_s *dp, uint8_t addr); -- cgit v1.2.3 From a30ef31018c6e4ea4cba69755f2fcdd0dbc17baa Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Wed, 19 Jun 2013 21:06:59 +1200 Subject: Handle SW-DP fault on WDATAERR. --- src/adiv5_swdp.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/adiv5_swdp.c b/src/adiv5_swdp.c index c021190..7896d8b 100644 --- a/src/adiv5_swdp.c +++ b/src/adiv5_swdp.c @@ -73,6 +73,7 @@ int adiv5_swdp_scan(void) dp->error = adiv5_swdp_error; dp->low_access = adiv5_swdp_low_access; + adiv5_swdp_error(dp); adiv5_dp_init(dp); if(!target_list) morse("NO TARGETS.", 1); @@ -97,7 +98,7 @@ static uint32_t adiv5_swdp_error(ADIv5_DP_t *dp) err = adiv5_swdp_read(dp, ADIV5_DP_CTRLSTAT) & (ADIV5_DP_CTRLSTAT_STICKYORUN | ADIV5_DP_CTRLSTAT_STICKYCMP | - ADIV5_DP_CTRLSTAT_STICKYERR); + ADIV5_DP_CTRLSTAT_STICKYERR | ADIV5_DP_CTRLSTAT_WDATAERR); if(err & ADIV5_DP_CTRLSTAT_STICKYORUN) clr |= ADIV5_DP_ABORT_ORUNERRCLR; @@ -105,6 +106,8 @@ static uint32_t adiv5_swdp_error(ADIv5_DP_t *dp) clr |= ADIV5_DP_ABORT_STKCMPCLR; if(err & ADIV5_DP_CTRLSTAT_STICKYERR) clr |= ADIV5_DP_ABORT_STKERRCLR; + if(err & ADIV5_DP_CTRLSTAT_WDATAERR) + clr |= ADIV5_DP_ABORT_WDERRCLR; adiv5_swdp_write(dp, ADIV5_DP_ABORT, clr); dp->fault = 0; -- cgit v1.2.3 From 700833f38f72137bee78a51608ecbd2a9bb5cbd2 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Mon, 19 Aug 2013 12:27:36 +1200 Subject: Use do {...} while(0) for PLATFORM_FATAL_ERROR() macro. --- src/platforms/native/platform.h | 4 ++-- src/platforms/stlink/platform.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/platforms/native/platform.h b/src/platforms/native/platform.h index fd456d8..37104d6 100644 --- a/src/platforms/native/platform.h +++ b/src/platforms/native/platform.h @@ -163,14 +163,14 @@ extern const char *morse_msg; #define SET_ERROR_STATE(state) {gpio_set_val(LED_PORT, LED_ERROR, state);} #define PLATFORM_SET_FATAL_ERROR_RECOVERY() {setjmp(fatal_error_jmpbuf);} -#define PLATFORM_FATAL_ERROR(error) { \ +#define PLATFORM_FATAL_ERROR(error) do { \ if(running_status) gdb_putpacketz("X1D"); \ else gdb_putpacketz("EFF"); \ running_status = 0; \ target_list_free(); \ morse("TARGET LOST.", 1); \ longjmp(fatal_error_jmpbuf, (error)); \ -} +} while (0) int platform_init(void); void morse(const char *msg, char repeat); diff --git a/src/platforms/stlink/platform.h b/src/platforms/stlink/platform.h index 029eb0a..bee8879 100644 --- a/src/platforms/stlink/platform.h +++ b/src/platforms/stlink/platform.h @@ -147,13 +147,13 @@ extern uint16_t led_idle_run; #define SET_IDLE_STATE(state) {gpio_set_val(LED_PORT, led_idle_run, state);} #define PLATFORM_SET_FATAL_ERROR_RECOVERY() {setjmp(fatal_error_jmpbuf);} -#define PLATFORM_FATAL_ERROR(error) { \ +#define PLATFORM_FATAL_ERROR(error) do { \ if(running_status) gdb_putpacketz("X1D"); \ else gdb_putpacketz("EFF"); \ running_status = 0; \ target_list_free(); \ longjmp(fatal_error_jmpbuf, (error)); \ -} +} while (0) int platform_init(void); void morse(const char *msg, char repeat); -- cgit v1.2.3 From f1584b266ba43b9304254deead52f92b0824024b Mon Sep 17 00:00:00 2001 From: BuFran Date: Mon, 29 Jul 2013 20:10:19 +0200 Subject: [BUILD] Don't throw error on already cleaned output --- src/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 8ec9f13..d8d8b00 100644 --- a/src/Makefile +++ b/src/Makefile @@ -46,8 +46,8 @@ blackmagic: $(OBJ) .PHONY: clean host_clean clean: host_clean - $(RM) *.o *.d *~ blackmagic $(HOSTFILES) - $(RM) platforms/*/*.o platforms/*/*.d mapfile + -$(RM) *.o *.d *~ blackmagic $(HOSTFILES) + -$(RM) platforms/*/*.o platforms/*/*.d mapfile -include *.d -- cgit v1.2.3 From c28350f24234cdfe4aefdc14c77004919e7c2e3d Mon Sep 17 00:00:00 2001 From: BuFran Date: Mon, 29 Jul 2013 21:12:19 +0200 Subject: FIX: u{8,16,32} -> uint{8,16,32}_t to be compatible with new library The use of u8, u16, u32 has been deprecated in libopencm3. Update it with standard uint8_t, uint16_t, uint32_t types --- src/platforms/f4discovery/platform.h | 8 ++++---- src/platforms/native/platform.c | 6 +++--- src/platforms/native/platform.h | 8 ++++---- src/platforms/stlink/platform.h | 8 ++++---- src/platforms/stm32/cdcacm.c | 2 +- src/platforms/stm32/dfu_f1.c | 6 +++--- src/platforms/stm32/dfu_f4.c | 14 +++++++------- src/platforms/stm32/dfucore.c | 30 +++++++++++++++--------------- src/platforms/swlink/platform.h | 8 ++++---- 9 files changed, 45 insertions(+), 45 deletions(-) (limited to 'src') diff --git a/src/platforms/f4discovery/platform.h b/src/platforms/f4discovery/platform.h index 0010ec4..e50b6c7 100644 --- a/src/platforms/f4discovery/platform.h +++ b/src/platforms/f4discovery/platform.h @@ -190,23 +190,23 @@ void uart_usb_buf_drain(uint8_t ep); #define vasprintf vasiprintf #ifdef INLINE_GPIO -static inline void _gpio_set(u32 gpioport, u16 gpios) +static inline void _gpio_set(uint32_t gpioport, uint16_t gpios) { GPIO_BSRR(gpioport) = gpios; GPIO_BSRR(gpioport) = gpios; } #define gpio_set _gpio_set -static inline void _gpio_clear(u32 gpioport, u16 gpios) +static inline void _gpio_clear(uint32_t gpioport, uint16_t gpios) { GPIO_BSRR(gpioport) = gpios<<16; GPIO_BSRR(gpioport) = gpios<<16; } #define gpio_clear _gpio_clear -static inline u16 _gpio_get(u32 gpioport, u16 gpios) +static inline uint16_t _gpio_get(uint32_t gpioport, uint16_t gpios) { - return (u16)GPIO_IDR(gpioport) & gpios; + return (uint16_t)GPIO_IDR(gpioport) & gpios; } #define gpio_get _gpio_get #endif diff --git a/src/platforms/native/platform.c b/src/platforms/native/platform.c index f5b9135..3228fff 100644 --- a/src/platforms/native/platform.c +++ b/src/platforms/native/platform.c @@ -263,15 +263,15 @@ const char *platform_target_voltage(void) return gpio_get(GPIOB, GPIO0) ? "OK" : "ABSENT!"; static char ret[] = "0.0V"; - const u8 channel = 8; - adc_set_regular_sequence(ADC1, 1, (u8*)&channel); + const uint8_t channel = 8; + adc_set_regular_sequence(ADC1, 1, (uint8_t*)&channel); adc_start_conversion_direct(ADC1); /* Wait for end of conversion. */ while (!adc_eoc(ADC1)); - u32 val = adc_read_regular(ADC1) * 99; /* 0-4095 */ + uint32_t val = adc_read_regular(ADC1) * 99; /* 0-4095 */ ret[0] = '0' + val / 81910; ret[2] = '0' + (val / 8191) % 10; diff --git a/src/platforms/native/platform.h b/src/platforms/native/platform.h index 37104d6..77382dc 100644 --- a/src/platforms/native/platform.h +++ b/src/platforms/native/platform.h @@ -193,21 +193,21 @@ void uart_usb_buf_drain(uint8_t ep); #define vasprintf vasiprintf #ifdef INLINE_GPIO -static inline void _gpio_set(u32 gpioport, u16 gpios) +static inline void _gpio_set(uint32_t gpioport, uint16_t gpios) { GPIO_BSRR(gpioport) = gpios; } #define gpio_set _gpio_set -static inline void _gpio_clear(u32 gpioport, u16 gpios) +static inline void _gpio_clear(uint32_t gpioport, uint16_t gpios) { GPIO_BRR(gpioport) = gpios; } #define gpio_clear _gpio_clear -static inline u16 _gpio_get(u32 gpioport, u16 gpios) +static inline uint16_t _gpio_get(uint32_t gpioport, uint16_t gpios) { - return (u16)GPIO_IDR(gpioport) & gpios; + return (uint16_t)GPIO_IDR(gpioport) & gpios; } #define gpio_get _gpio_get #endif diff --git a/src/platforms/stlink/platform.h b/src/platforms/stlink/platform.h index bee8879..c79ea13 100644 --- a/src/platforms/stlink/platform.h +++ b/src/platforms/stlink/platform.h @@ -176,21 +176,21 @@ void uart_usb_buf_drain(uint8_t ep); #define vasprintf vasiprintf #ifdef INLINE_GPIO -static inline void _gpio_set(u32 gpioport, u16 gpios) +static inline void _gpio_set(uint32_t gpioport, uint16_t gpios) { GPIO_BSRR(gpioport) = gpios; } #define gpio_set _gpio_set -static inline void _gpio_clear(u32 gpioport, u16 gpios) +static inline void _gpio_clear(uint32_t gpioport, uint16_t gpios) { GPIO_BRR(gpioport) = gpios; } #define gpio_clear _gpio_clear -static inline u16 _gpio_get(u32 gpioport, u16 gpios) +static inline uint16_t _gpio_get(uint32_t gpioport, uint16_t gpios) { - return (u16)GPIO_IDR(gpioport) & gpios; + return (uint16_t)GPIO_IDR(gpioport) & gpios; } #define gpio_get _gpio_get #endif diff --git a/src/platforms/stm32/cdcacm.c b/src/platforms/stm32/cdcacm.c index 93b0f33..edd20d7 100644 --- a/src/platforms/stm32/cdcacm.c +++ b/src/platforms/stm32/cdcacm.c @@ -480,7 +480,7 @@ int cdcacm_get_dtr(void) return cdcacm_gdb_dtr; } -static void cdcacm_set_config(usbd_device *dev, u16 wValue) +static void cdcacm_set_config(usbd_device *dev, uint16_t wValue) { configured = wValue; diff --git a/src/platforms/stm32/dfu_f1.c b/src/platforms/stm32/dfu_f1.c index 827712d..08cbb02 100644 --- a/src/platforms/stm32/dfu_f1.c +++ b/src/platforms/stm32/dfu_f1.c @@ -48,7 +48,7 @@ void dfu_flash_program_buffer(uint32_t baseaddr, void *buf, int len) { for(int i = 0; i < len; i += 2) flash_program_half_word(baseaddr + i, - *(u16*)(buf+i)); + *(uint16_t*)(buf+i)); } uint32_t dfu_poll_timeout(uint8_t cmd, uint32_t addr, uint16_t blocknum) @@ -77,12 +77,12 @@ void dfu_protect_enable(void) void dfu_jump_app_if_valid(void) { /* Boot the application if it's valid */ - if((*(volatile u32*)APP_ADDRESS & 0x2FFE0000) == 0x20000000) { + if((*(volatile uint32_t*)APP_ADDRESS & 0x2FFE0000) == 0x20000000) { /* Set vector table base address */ SCB_VTOR = APP_ADDRESS & 0x1FFFFF; /* Max 2 MByte Flash*/ /* Initialise master stack pointer */ asm volatile ("msr msp, %0"::"g" - (*(volatile u32*)APP_ADDRESS)); + (*(volatile uint32_t*)APP_ADDRESS)); /* Jump to application */ (*(void(**)())(APP_ADDRESS + 4))(); } diff --git a/src/platforms/stm32/dfu_f4.c b/src/platforms/stm32/dfu_f4.c index 960ec23..1421b19 100644 --- a/src/platforms/stm32/dfu_f4.c +++ b/src/platforms/stm32/dfu_f4.c @@ -26,17 +26,17 @@ #include "usbdfu.h" -static u32 sector_addr[] = {0x8000000, 0x8004000, 0x8008000, 0x800c000, +static uint32_t sector_addr[] = {0x8000000, 0x8004000, 0x8008000, 0x800c000, 0x8010000, 0x8020000, 0x8040000, 0x8060000, 0x8080000, 0x80a0000, 0x80c0000, 0x80e0000, 0x8100000, 0}; -static u16 sector_erase_time[12]= {500, 500, 500, 500, +static uint16_t sector_erase_time[12]= {500, 500, 500, 500, 1100, 2600, 2600, 2600, 2600, 2600, 2600, 2600}; -static u8 sector_num = 0xff; +static uint8_t sector_num = 0xff; /* Find the sector number for a given address*/ -static void get_sector_num(u32 addr) +static void get_sector_num(uint32_t addr) { int i = 0; while(sector_addr[i+1]) { @@ -60,7 +60,7 @@ void dfu_flash_program_buffer(uint32_t baseaddr, void *buf, int len) { for(int i = 0; i < len; i += 4) flash_program_word(baseaddr + i, - *(u32*)(buf+i), + *(uint32_t*)(buf+i), FLASH_PROGRAM_X32); } @@ -93,12 +93,12 @@ void dfu_jump_app_if_valid(void) /* Boot the application if it's valid */ /* Vector table may be anywhere in 128 kByte RAM CCM not handled*/ - if((*(volatile u32*)APP_ADDRESS & 0x2FFC0000) == 0x20000000) { + if((*(volatile uint32_t*)APP_ADDRESS & 0x2FFC0000) == 0x20000000) { /* Set vector table base address */ SCB_VTOR = APP_ADDRESS & 0x1FFFFF; /* Max 2 MByte Flash*/ /* Initialise master stack pointer */ asm volatile ("msr msp, %0"::"g" - (*(volatile u32*)APP_ADDRESS)); + (*(volatile uint32_t*)APP_ADDRESS)); /* Jump to application */ (*(void(**)())(APP_ADDRESS + 4))(); } diff --git a/src/platforms/stm32/dfucore.c b/src/platforms/stm32/dfucore.c index 2786e9a..834c0ad 100644 --- a/src/platforms/stm32/dfucore.c +++ b/src/platforms/stm32/dfucore.c @@ -34,19 +34,19 @@ usbd_device *usbdev; /* We need a special large control buffer for this device: */ -u8 usbd_control_buffer[1024]; +uint8_t usbd_control_buffer[1024]; -static u32 max_address; +static uint32_t max_address; static enum dfu_state usbdfu_state = STATE_DFU_IDLE; static char *get_dev_unique_id(char *serial_no); static struct { - u8 buf[sizeof(usbd_control_buffer)]; - u16 len; - u32 addr; - u16 blocknum; + uint8_t buf[sizeof(usbd_control_buffer)]; + uint16_t len; + uint32_t addr; + uint16_t blocknum; } prog; const struct usb_device_descriptor dev = { @@ -121,13 +121,13 @@ static const char *usb_strings[] = { DFU_IFACE_STRING, }; -static u32 get_le32(const void *vp) +static uint32_t get_le32(const void *vp) { - const u8 *p = vp; - return ((u32)p[3] << 24) + ((u32)p[2] << 16) + (p[1] << 8) + p[0]; + const uint8_t *p = vp; + return ((uint32_t)p[3] << 24) + ((uint32_t)p[2] << 16) + (p[1] << 8) + p[0]; } -static u8 usbdfu_getstatus(u32 *bwPollTimeout) +static uint8_t usbdfu_getstatus(uint32_t *bwPollTimeout) { switch(usbdfu_state) { case STATE_DFU_DNLOAD_SYNC: @@ -157,7 +157,7 @@ usbdfu_getstatus_complete(usbd_device *dev, struct usb_setup_data *req) flash_unlock(); if(prog.blocknum == 0) { - u32 addr = get_le32(prog.buf + 1); + uint32_t addr = get_le32(prog.buf + 1); if (addr < APP_ADDRESS || (addr >= max_address)) { flash_lock(); @@ -171,7 +171,7 @@ usbdfu_getstatus_complete(usbd_device *dev, struct usb_setup_data *req) prog.addr = addr; } } else { - u32 baseaddr = prog.addr + + uint32_t baseaddr = prog.addr + ((prog.blocknum - 2) * dfu_function.wTransferSize); dfu_flash_program_buffer(baseaddr, prog.buf, prog.len); @@ -193,7 +193,7 @@ usbdfu_getstatus_complete(usbd_device *dev, struct usb_setup_data *req) } static int usbdfu_control_request(usbd_device *dev, - struct usb_setup_data *req, u8 **buf, u16 *len, + struct usb_setup_data *req, uint8_t **buf, uint16_t *len, void (**complete)(usbd_device *dev, struct usb_setup_data *req)) { (void)dev; @@ -227,7 +227,7 @@ static int usbdfu_control_request(usbd_device *dev, /* Upload not supported for now */ return 0; case DFU_GETSTATUS: { - u32 bwPollTimeout = 0; /* 24-bit integer in DFU class spec */ + uint32_t bwPollTimeout = 0; /* 24-bit integer in DFU class spec */ (*buf)[0] = usbdfu_getstatus(&bwPollTimeout); (*buf)[1] = bwPollTimeout & 0xFF; @@ -292,7 +292,7 @@ static char *get_dev_unique_id(char *s) /* Calculated the upper flash limit from the exported data in theparameter block*/ - max_address = (*(u32 *) FLASH_SIZE_R) <<10; + max_address = (*(uint32_t *) FLASH_SIZE_R) <<10; /* Fetch serial number from chip's unique ID */ for(i = 0; i < 8; i++) { s[7-i] = ((unique_id >> (4*i)) & 0xF) + '0'; diff --git a/src/platforms/swlink/platform.h b/src/platforms/swlink/platform.h index 7d36326..614a389 100644 --- a/src/platforms/swlink/platform.h +++ b/src/platforms/swlink/platform.h @@ -174,21 +174,21 @@ void uart_usb_buf_drain(uint8_t ep); #define vasprintf vasiprintf #ifdef INLINE_GPIO -static inline void _gpio_set(u32 gpioport, u16 gpios) +static inline void _gpio_set(uint32_t gpioport, uint16_t gpios) { GPIO_BSRR(gpioport) = gpios; } #define gpio_set _gpio_set -static inline void _gpio_clear(u32 gpioport, u16 gpios) +static inline void _gpio_clear(uint32_t gpioport, uint16_t gpios) { GPIO_BRR(gpioport) = gpios; } #define gpio_clear _gpio_clear -static inline u16 _gpio_get(u32 gpioport, u16 gpios) +static inline uint16_t _gpio_get(uint32_t gpioport, uint16_t gpios) { - return (u16)GPIO_IDR(gpioport) & gpios; + return (uint16_t)GPIO_IDR(gpioport) & gpios; } #define gpio_get _gpio_get #endif -- cgit v1.2.3 From c857165c12a80c3a2d4cc9d7a4398ec8ef95b1e8 Mon Sep 17 00:00:00 2001 From: BuFran Date: Mon, 29 Jul 2013 21:12:50 +0200 Subject: FIX: FLASH_* collision with libopencm3 definitions Resolve collision to FLASH_* from the libopencm3 by adding STM32F1_ prefix to the L1's --- src/stm32l1.c | 88 +++++++++++++++++++++++++++++------------------------------ 1 file changed, 44 insertions(+), 44 deletions(-) (limited to 'src') diff --git a/src/stm32l1.c b/src/stm32l1.c index 325b415..8e80582 100644 --- a/src/stm32l1.c +++ b/src/stm32l1.c @@ -56,40 +56,40 @@ static const char stm32l1_xml_memory_map[] = "" ""; /* Flash Controller Register Map */ -#define FLASH_BASE 0x40023C00 -#define FLASH_ACR (FLASH_BASE+0x00) -#define FLASH_PECR (FLASH_BASE+0x04) -#define FLASH_PDKEYR (FLASH_BASE+0x08) -#define FLASH_PEKEYR (FLASH_BASE+0x0C) -#define FLASH_PRGKEYR (FLASH_BASE+0x10) -#define FLASH_OPTKEYR (FLASH_BASE+0x14) -#define FLASH_SR (FLASH_BASE+0x18) -#define FLASH_OBR (FLASH_BASE+0x1C) -#define FLASH_WRPR1 (FLASH_BASE+0x20) -#define FLASH_WRPR2 (FLASH_BASE+0x80) -#define FLASH_WRPR3 (FLASH_BASE+0x84) - -#define FLASH_PECR_FPRG (1 << 10) -#define FLASH_PECR_ERASE (1 << 9) -#define FLASH_PECR_PROG (1 << 3) - -#define FLASH_SR_BSY (1 << 0) -#define FLASH_SR_EOP (1 << 1) - -#define FLASH_SR_ERROR_MASK (0x1f << 8) - -#define PEKEY1 0x89ABCDEF -#define PEKEY2 0x02030405 -#define PRGKEY1 0x8C9DAEBF -#define PRGKEY2 0x13141516 - -#define DBGMCU_IDCODE 0xE0042000 +#define STM32L1_FLASH_BASE 0x40023C00 +#define STM32L1_FLASH_ACR (STM32L1_FLASH_BASE + 0x00) +#define STM32L1_FLASH_PECR (STM32L1_FLASH_BASE + 0x04) +#define STM32L1_FLASH_PDKEYR (STM32L1_FLASH_BASE + 0x08) +#define STM32L1_FLASH_PEKEYR (STM32L1_FLASH_BASE + 0x0C) +#define STM32L1_FLASH_PRGKEYR (STM32L1_FLASH_BASE + 0x10) +#define STM32L1_FLASH_OPTKEYR (STM32L1_FLASH_BASE + 0x14) +#define STM32L1_FLASH_SR (STM32L1_FLASH_BASE + 0x18) +#define STM32L1_FLASH_OBR (STM32L1_FLASH_BASE + 0x1C) +#define STM32L1_FLASH_WRPR1 (STM32L1_FLASH_BASE + 0x20) +#define STM32L1_FLASH_WRPR2 (STM32L1_FLASH_BASE + 0x80) +#define STM32L1_FLASH_WRPR3 (STM32L1_FLASH_BASE + 0x84) + +#define STM32L1_FLASH_PECR_FPRG (1 << 10) +#define STM32L1_FLASH_PECR_ERASE (1 << 9) +#define STM32L1_FLASH_PECR_PROG (1 << 3) + +#define STM32L1_FLASH_SR_BSY (1 << 0) +#define STM32L1_FLASH_SR_EOP (1 << 1) + +#define STM32L1_FLASH_SR_ERROR_MASK (0x1f << 8) + +#define STM32L1_PEKEY1 0x89ABCDEF +#define STM32L1_PEKEY2 0x02030405 +#define STM32L1_PRGKEY1 0x8C9DAEBF +#define STM32L1_PRGKEY2 0x13141516 + +#define STM32L1_DBGMCU_IDCODE 0xE0042000 bool stm32l1_probe(struct target_s *target) { uint32_t idcode; - idcode = adiv5_ap_mem_read(adiv5_target_ap(target), DBGMCU_IDCODE); + idcode = adiv5_ap_mem_read(adiv5_target_ap(target), STM32L1_DBGMCU_IDCODE); switch(idcode & 0xFFF) { case 0x416: /* Medium density */ case 0x436: /* High density */ @@ -105,10 +105,10 @@ bool stm32l1_probe(struct target_s *target) static void stm32l1_flash_unlock(ADIv5_AP_t *ap) { - adiv5_ap_mem_write(ap, FLASH_PEKEYR, PEKEY1); - adiv5_ap_mem_write(ap, FLASH_PEKEYR, PEKEY2); - adiv5_ap_mem_write(ap, FLASH_PRGKEYR, PRGKEY1); - adiv5_ap_mem_write(ap, FLASH_PRGKEYR, PRGKEY2); + adiv5_ap_mem_write(ap, STM32L1_FLASH_PEKEYR, STM32L1_PEKEY1); + adiv5_ap_mem_write(ap, STM32L1_FLASH_PEKEYR, STM32L1_PEKEY2); + adiv5_ap_mem_write(ap, STM32L1_FLASH_PRGKEYR, STM32L1_PRGKEY1); + adiv5_ap_mem_write(ap, STM32L1_FLASH_PRGKEYR, STM32L1_PRGKEY2); } static int stm32l1_flash_erase(struct target_s *target, uint32_t addr, int len) @@ -122,10 +122,10 @@ static int stm32l1_flash_erase(struct target_s *target, uint32_t addr, int len) stm32l1_flash_unlock(ap); /* Flash page erase instruction */ - adiv5_ap_mem_write(ap, FLASH_PECR, FLASH_PECR_ERASE | FLASH_PECR_PROG); + adiv5_ap_mem_write(ap, STM32L1_FLASH_PECR, STM32L1_FLASH_PECR_ERASE | STM32L1_FLASH_PECR_PROG); /* Read FLASH_SR to poll for BSY bit */ - while(adiv5_ap_mem_read(ap, FLASH_SR) & FLASH_SR_BSY) + while(adiv5_ap_mem_read(ap, STM32L1_FLASH_SR) & STM32L1_FLASH_SR_BSY) if(target_check_error(target)) return -1; @@ -138,11 +138,11 @@ static int stm32l1_flash_erase(struct target_s *target, uint32_t addr, int len) } /* Disable programming mode */ - adiv5_ap_mem_write(ap, FLASH_PECR, 0); + adiv5_ap_mem_write(ap, STM32L1_FLASH_PECR, 0); /* Check for error */ - sr = adiv5_ap_mem_read(ap, FLASH_SR); - if ((sr & FLASH_SR_ERROR_MASK) || !(sr & FLASH_SR_EOP)) + sr = adiv5_ap_mem_read(ap, STM32L1_FLASH_SR); + if ((sr & STM32L1_FLASH_SR_ERROR_MASK) || !(sr & STM32L1_FLASH_SR_EOP)) return -1; return 0; @@ -183,10 +183,10 @@ static int stm32l1_flash_write(struct target_s *target, uint32_t dest, /* Write half-pages */ if(len > 128) { /* Enable half page mode */ - adiv5_ap_mem_write(ap, FLASH_PECR, FLASH_PECR_FPRG | FLASH_PECR_PROG); + adiv5_ap_mem_write(ap, STM32L1_FLASH_PECR, STM32L1_FLASH_PECR_FPRG | STM32L1_FLASH_PECR_PROG); /* Read FLASH_SR to poll for BSY bit */ - while(adiv5_ap_mem_read(ap, FLASH_SR) & FLASH_SR_BSY) + while(adiv5_ap_mem_read(ap, STM32L1_FLASH_SR) & STM32L1_FLASH_SR_BSY) if(target_check_error(target)) return -1; @@ -196,10 +196,10 @@ static int stm32l1_flash_write(struct target_s *target, uint32_t dest, len -= len & ~127; /* Disable half page mode */ - adiv5_ap_mem_write(ap, FLASH_PECR, 0); + adiv5_ap_mem_write(ap, STM32L1_FLASH_PECR, 0); /* Read FLASH_SR to poll for BSY bit */ - while(adiv5_ap_mem_read(ap, FLASH_SR) & FLASH_SR_BSY) + while(adiv5_ap_mem_read(ap, STM32L1_FLASH_SR) & STM32L1_FLASH_SR_BSY) if(target_check_error(target)) return -1; } @@ -221,8 +221,8 @@ static int stm32l1_flash_write(struct target_s *target, uint32_t dest, } /* Check for error */ - sr = adiv5_ap_mem_read(ap, FLASH_SR); - if ((sr & FLASH_SR_ERROR_MASK) || !(sr & FLASH_SR_EOP)) + sr = adiv5_ap_mem_read(ap, STM32L1_FLASH_SR); + if ((sr & STM32L1_FLASH_SR_ERROR_MASK) || !(sr & STM32L1_FLASH_SR_EOP)) return -1; return 0; -- cgit v1.2.3 From e67192348f21fdc3952cabb214a031311a91a367 Mon Sep 17 00:00:00 2001 From: BuFran Date: Mon, 29 Jul 2013 20:48:17 +0200 Subject: FIX: usbd_init compatibility fix Updated compatibility with libopencm3 commit 113e5c22e6390ba072148315e83a5faa5ff7ce86 --- src/platforms/stm32/cdcacm.c | 6 ++++-- src/platforms/stm32/dfucore.c | 5 +++-- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/platforms/stm32/cdcacm.c b/src/platforms/stm32/cdcacm.c index edd20d7..010117f 100644 --- a/src/platforms/stm32/cdcacm.c +++ b/src/platforms/stm32/cdcacm.c @@ -536,8 +536,10 @@ void cdcacm_init(void) get_dev_unique_id(serial_no); - usbdev = usbd_init(&USB_DRIVER, &dev, &config, usb_strings, sizeof(usb_strings)/sizeof(char *)); - usbd_set_control_buffer_size(usbdev, sizeof(usbd_control_buffer)); + usbdev = usbd_init(&USB_DRIVER, &dev, &config, usb_strings, + sizeof(usb_strings)/sizeof(char *), + usbd_control_buffer, sizeof(usbd_control_buffer)); + usbd_register_set_config_callback(usbdev, cdcacm_set_config); nvic_set_priority(USB_IRQ, IRQ_PRI_USB); diff --git a/src/platforms/stm32/dfucore.c b/src/platforms/stm32/dfucore.c index 834c0ad..a01616f 100644 --- a/src/platforms/stm32/dfucore.c +++ b/src/platforms/stm32/dfucore.c @@ -255,8 +255,9 @@ void dfu_init(const usbd_driver *driver) { get_dev_unique_id(serial_no); - usbdev = usbd_init(driver, &dev, &config, usb_strings, 4); - usbd_set_control_buffer_size(usbdev, sizeof(usbd_control_buffer)); + usbdev = usbd_init(driver, &dev, &config, usb_strings, 4, + usbd_control_buffer, sizeof(usbd_control_buffer)); + usbd_register_control_callback(usbdev, USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE, USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, -- cgit v1.2.3 From 40820a2354bd76b86e429dbd9f213375dfe05af4 Mon Sep 17 00:00:00 2001 From: Marc Singer Date: Fri, 6 Sep 2013 21:19:37 -0700 Subject: Added internal pull-up to PWR_BR. o Prevent probe from inadvertently powering target. If PWR_BR is allowed to float, the gate on Q1 (blackmagic_mini) will tend to be close enough to zero to turn the transistor on. We activate the internal pull-up on this IO pin to force the transistor off. --- src/platforms/native/platform.c | 9 +++++++++ src/platforms/native/platform.h | 5 ++++- 2 files changed, 13 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/platforms/native/platform.c b/src/platforms/native/platform.c index 3228fff..44a5793 100644 --- a/src/platforms/native/platform.c +++ b/src/platforms/native/platform.c @@ -104,6 +104,15 @@ int platform_init(void) GPIO_CNF_OUTPUT_PUSHPULL, SRST_PIN); + /* Enable internal pull-up on PWR_BR so that we don't drive + TPWR locally or inadvertently supply power to the target. */ + if (platform_hwversion () > 0) { + gpio_set (PWR_BR_PORT, PWR_BR_PIN); + gpio_set_mode(PWR_BR_PORT, GPIO_MODE_INPUT, + GPIO_CNF_INPUT_PULL_UPDOWN, + PWR_BR_PIN); + } + /* Setup heartbeat timer */ systick_set_clocksource(STK_CTRL_CLKSOURCE_AHB_DIV8); systick_set_reload(900000); /* Interrupt us at 10 Hz */ diff --git a/src/platforms/native/platform.h b/src/platforms/native/platform.h index 77382dc..40dd620 100644 --- a/src/platforms/native/platform.h +++ b/src/platforms/native/platform.h @@ -51,7 +51,8 @@ extern usbd_device *usbdev; * LED2 = PB11 (Red LED : Error) * * TPWR = RB0 (input) -- analogue on mini design ADC1, ch8 - * nTRST = PB1 + * nTRST = PB1 [blackmagic] + * PWR_BR = PB1 [blackmagic_mini] -- supply power to the target, active low * SRST_OUT = PA2 * TDI = PA3 * TMS = PA4 (input for SWDP) @@ -83,6 +84,8 @@ extern usbd_device *usbdev; #define TRST_PORT GPIOB #define TRST_PIN GPIO1 +#define PWR_BR_PORT GPIOB +#define PWR_BR_PIN GPIO1 #define SRST_PORT GPIOA #define SRST_PIN GPIO2 -- cgit v1.2.3 From b8f9a2ed4b607e5152eb007a100373b3253e32a0 Mon Sep 17 00:00:00 2001 From: Richard Eoin Meadows Date: Sun, 8 Sep 2013 13:13:16 +0100 Subject: Bugfix: Always apply the vector table magic number correctly. Previously when the flash write length was less than the Chunk size the 2nd chunk write would re-calculate and apply an incorrect magic number --- src/lpc11xx.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/lpc11xx.c b/src/lpc11xx.c index 83f37ba..9adbe2b 100644 --- a/src/lpc11xx.c +++ b/src/lpc11xx.c @@ -216,13 +216,18 @@ lpc11xx_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, chunk_offset = 0; /* if we are programming the vectors, calculate the magic number */ - if (chunk == 0) { + if (dest == 0) { uint32_t *w = (uint32_t *)(&flash_pgm.data[0]); uint32_t sum = 0; - for (unsigned i = 0; i < 7; i++) - sum += w[i]; - w[7] = 0 - sum; + if (copylen >= 7) { + for (unsigned i = 0; i < 7; i++) + sum += w[i]; + w[7] = 0 - sum; + } else { + /* We can't possibly calculate the magic number */ + return -1; + } } } else { -- cgit v1.2.3 From 3cce6f472c79efd53c474bb0173b9c2e2f43c5d4 Mon Sep 17 00:00:00 2001 From: Benno Leslie Date: Sun, 15 Sep 2013 19:15:49 +1000 Subject: Add support for the SYS_WRITEC semihosting operation. This is implemented in the same manner as QEMU semihosting support, specifically, a SYS_WRITEC results in a single character write to STDERR. --- src/cortexm.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'src') diff --git a/src/cortexm.c b/src/cortexm.c index a8bb34b..1fc5978 100644 --- a/src/cortexm.c +++ b/src/cortexm.c @@ -989,6 +989,9 @@ static int cortexm_hostio_request(target *t) gdb_putpacket_f("Fwrite,%08X,%08X,%08X", params[0] - 1, params[1], params[2]); break; + case SYS_WRITEC: /* writec */ + gdb_putpacket_f("Fwrite,2,%08X,1", arm_regs[1]); + break; case SYS_ISTTY: /* isatty */ gdb_putpacket_f("Fisatty,%08X", params[0] - 1); break; -- cgit v1.2.3 From c395c6f73a220cd6da26ff3b48afde8487b6199f Mon Sep 17 00:00:00 2001 From: Michael Tharp Date: Fri, 4 Oct 2013 21:24:53 -0400 Subject: Configure SRST output as open-drain for BMP Mini hardware --- src/platforms/native/platform.c | 11 ++++++++--- src/platforms/native/platform.h | 1 + 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/platforms/native/platform.c b/src/platforms/native/platform.c index 44a5793..640ba58 100644 --- a/src/platforms/native/platform.c +++ b/src/platforms/native/platform.c @@ -98,10 +98,15 @@ int platform_init(void) * to release the device from reset if this floats. */ gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO7); - /* Enable SRST output */ - gpio_set_val(SRST_PORT, SRST_PIN, platform_hwversion() > 0); + /* Enable SRST output. Original uses a NPN to pull down, so setting the + * output HIGH asserts. Mini is directly connected so use open drain output + * and set LOW to assert. + */ + platform_srst_set_val(false); gpio_set_mode(SRST_PORT, GPIO_MODE_OUTPUT_50_MHZ, - GPIO_CNF_OUTPUT_PUSHPULL, + (platform_hwversion() == 0 + ? GPIO_CNF_OUTPUT_PUSHPULL + : GPIO_CNF_OUTPUT_OPENDRAIN), SRST_PIN); /* Enable internal pull-up on PWR_BR so that we don't drive diff --git a/src/platforms/native/platform.h b/src/platforms/native/platform.h index 40dd620..20d1510 100644 --- a/src/platforms/native/platform.h +++ b/src/platforms/native/platform.h @@ -220,3 +220,4 @@ static inline uint16_t _gpio_get(uint32_t gpioport, uint16_t gpios) #define disconnect_usb() gpio_set_mode(USB_PU_PORT, GPIO_MODE_INPUT, 0, USB_PU_PIN); void assert_boot_pin(void); void setup_vbus_irq(void); +void platform_srst_set_val(bool assert); -- cgit v1.2.3 From 15e529a43a48be51f3da24ef39d0c5ea859b4cbe Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sun, 6 Oct 2013 15:45:54 +0200 Subject: stm32f1.c: On a read protected device, deny any other option action than erase. Otherwise the first option action triggers an error, inhibiting further option actions. --- src/stm32f1.c | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src') diff --git a/src/stm32f1.c b/src/stm32f1.c index 03dcc43..4dc5768 100644 --- a/src/stm32f1.c +++ b/src/stm32f1.c @@ -101,6 +101,8 @@ static const char stm32hd_xml_memory_map[] = "" #define FLASH_CR_MER (1 << 2) #define FLASH_CR_PER (1 << 1) +#define FLASH_OBR_RDPRT (1 << 1) + #define FLASH_SR_BSY (1 << 0) #define FLASH_OBP_RDP 0x1FFFF800 @@ -341,6 +343,7 @@ static bool stm32f1_cmd_option(target *t, int argc, char *argv[]) uint32_t addr, val; uint32_t flash_obp_rdp_key; ADIv5_AP_t *ap = adiv5_target_ap(t); + uint32_t rdprt; switch(t->idcode) { case 0x422: /* STM32F30x */ @@ -350,6 +353,7 @@ static bool stm32f1_cmd_option(target *t, int argc, char *argv[]) break; default: flash_obp_rdp_key = FLASH_OBP_RDP_KEY; } + rdprt = (adiv5_ap_mem_read(ap, FLASH_OBR) & FLASH_OBR_RDPRT); stm32f1_flash_unlock(ap); adiv5_ap_mem_write(ap, FLASH_OPTKEYR, KEY1); adiv5_ap_mem_write(ap, FLASH_OPTKEYR, KEY2); @@ -357,6 +361,10 @@ static bool stm32f1_cmd_option(target *t, int argc, char *argv[]) if ((argc == 2) && !strcmp(argv[1], "erase")) { stm32f1_option_erase(t); stm32f1_option_write(t, FLASH_OBP_RDP, flash_obp_rdp_key); + } else if (rdprt) { + gdb_out("Device is Read Protected\n"); + gdb_out("Use \"monitor option erase\" to unprotect, erasing device\n"); + return true; } else if (argc == 3) { addr = strtol(argv[1], NULL, 0); val = strtol(argv[2], NULL, 0); -- cgit v1.2.3 From 086f3565f0815a4ddfd926f8aa18bd5646a0f54f Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sun, 6 Oct 2013 16:47:30 +0200 Subject: stm32f1: Fix handling of option byte write. Write needs to happend on erased option bytes. --- src/stm32f1.c | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/stm32f1.c b/src/stm32f1.c index 4dc5768..670c5bd 100644 --- a/src/stm32f1.c +++ b/src/stm32f1.c @@ -324,10 +324,12 @@ static bool stm32f1_option_erase(target *t) return true; } -static bool stm32f1_option_write(target *t, uint32_t addr, uint16_t value) +static bool stm32f1_option_write_erased(target *t, uint32_t addr, uint16_t value) { ADIv5_AP_t *ap = adiv5_target_ap(t); + if (value == 0xffff) + return true; /* Erase option bytes instruction */ adiv5_ap_mem_write(ap, FLASH_CR, FLASH_CR_OPTPG | FLASH_CR_OPTWRE); adiv5_ap_mem_write_halfword(ap, addr, value); @@ -338,6 +340,36 @@ static bool stm32f1_option_write(target *t, uint32_t addr, uint16_t value) return true; } +static bool stm32f1_option_write(target *t, uint32_t addr, uint16_t value) +{ + ADIv5_AP_t *ap = adiv5_target_ap(t); + uint16_t opt_val[8]; + int i, index; + + index = (addr - FLASH_OBP_RDP) / 2; + if ((index < 0) || (index > 7)) + return false; + /* Retrieve old values */ + for (i = 0; i < 16; i = i +4) { + uint32_t val = adiv5_ap_mem_read(ap, FLASH_OBP_RDP + i); + opt_val[i/2] = val & 0xffff; + opt_val[i/2 +1] = val >> 16; + } + if (opt_val[index] == value) + return true; + /* Check for erased value */ + if (opt_val[index] != 0xffff) + if (!(stm32f1_option_erase(t))) + return false; + opt_val[index] = value; + /* Write changed values*/ + for (i = 0; i < 8; i++) + if (!(stm32f1_option_write_erased + (t, FLASH_OBP_RDP + i*2,opt_val[i]))) + return false; + return true; +} + static bool stm32f1_cmd_option(target *t, int argc, char *argv[]) { uint32_t addr, val; @@ -353,14 +385,14 @@ static bool stm32f1_cmd_option(target *t, int argc, char *argv[]) break; default: flash_obp_rdp_key = FLASH_OBP_RDP_KEY; } - rdprt = (adiv5_ap_mem_read(ap, FLASH_OBR) & FLASH_OBR_RDPRT); + rdprt = (adiv5_ap_mem_read(ap, FLASH_OBR) & FLASH_OBR_RDPRT); stm32f1_flash_unlock(ap); adiv5_ap_mem_write(ap, FLASH_OPTKEYR, KEY1); adiv5_ap_mem_write(ap, FLASH_OPTKEYR, KEY2); if ((argc == 2) && !strcmp(argv[1], "erase")) { stm32f1_option_erase(t); - stm32f1_option_write(t, FLASH_OBP_RDP, flash_obp_rdp_key); + stm32f1_option_write_erased(t, FLASH_OBP_RDP, flash_obp_rdp_key); } else if (rdprt) { gdb_out("Device is Read Protected\n"); gdb_out("Use \"monitor option erase\" to unprotect, erasing device\n"); -- cgit v1.2.3 From 5aa802969bbb4cf2291faa59ce31a1697ca71d2f Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sun, 6 Oct 2013 14:50:39 +0200 Subject: stlink: Give the NRST check more time as otherwise some L1 discovery board stayed in the bootloader. --- src/platforms/stlink/usbdfu.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/platforms/stlink/usbdfu.c b/src/platforms/stlink/usbdfu.c index f688c1c..76a19b0 100644 --- a/src/platforms/stlink/usbdfu.c +++ b/src/platforms/stlink/usbdfu.c @@ -40,13 +40,13 @@ static int stlink_test_nrst(void) * 11 for ST-Link V1, e.g. on VL Discovery, tag as rev 0 * 10 for ST-Link V2, e.g. on F4 Discovery, tag as rev 1 */ - rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN); - gpio_set_mode(GPIOC, GPIO_MODE_INPUT, - GPIO_CNF_INPUT_PULL_UPDOWN, GPIO14 | GPIO13); - gpio_set(GPIOC, GPIO14 | GPIO13); - for (i = 0; i < 100; i++) - rev = (~(gpio_get(GPIOC, GPIO14 | GPIO13)) >> 13) & 3; - + for (i = 0; i < 0x200; i++) { + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN); + gpio_set_mode(GPIOC, GPIO_MODE_INPUT, + GPIO_CNF_INPUT_PULL_UPDOWN, GPIO14 | GPIO13); + gpio_set(GPIOC, GPIO14 | GPIO13); + rev = (~(gpio_get(GPIOC, GPIO14 | GPIO13)) >> 13) & 3; + } switch (rev) { case 0: pin = GPIO1; -- cgit v1.2.3 From cbd73cfb8f00e9060b1c875560eac0ff3f69685a Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Mon, 14 Oct 2013 17:23:28 +0200 Subject: STM32F4: Recognize F401. --- src/stm32f4.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/stm32f4.c b/src/stm32f4.c index 471f167..cfbe9e3 100644 --- a/src/stm32f4.c +++ b/src/stm32f4.c @@ -170,6 +170,7 @@ bool stm32f4_probe(struct target_s *target) switch(idcode & 0xFFF) { case 0x411: /* Documented to be 0x413! This is what I read... */ case 0x413: + case 0x423: /* F401 */ case 0x419: /* 427/437 */ target->driver = stm32f4_driver_str; target->xml_mem_map = stm32f4_xml_memory_map; -- cgit v1.2.3 From 536482f8047f1ee984f362c5c5e3fe488353a1b7 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Mon, 14 Oct 2013 20:10:49 +0200 Subject: STM32F4: Add handling of second bank and dual boot devices. --- src/stm32f4.c | 119 +++++++++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 88 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/stm32f4.c b/src/stm32f4.c index cfbe9e3..0f2e840 100644 --- a/src/stm32f4.c +++ b/src/stm32f4.c @@ -23,11 +23,10 @@ * * Refereces: * ST doc - RM0090 - * Reference manual - STM32F405xx, STM32F407xx, STM32F415xx and STM32F417xx - * advanced ARM-based 32-bit MCUs - * ST doc - PM0081 - * Programming manual - STM32F40xxx and STM32F41xxx Flash programming - * manual + * Reference manual - STM32F405xx, STM32F407xx, STM32F415xx/417xx, + * STM32F42xxx and STM32F43xxx dvanced ARM-based 32-bit MCUs + * ST doc - RM0368 + * Reference manual - STM32F401xB/C advanced ARM-based 32-bit MCUs */ #include @@ -91,14 +90,18 @@ static const char stm32f4_xml_memory_map[] = "" #define FLASH_SR (FPEC_BASE+0x0C) #define FLASH_CR (FPEC_BASE+0x10) #define FLASH_OPTCR (FPEC_BASE+0x14) +#define FLASH_OPTCR1 (FPEC_BASE+0x18) #define FLASH_CR_PG (1 << 0) #define FLASH_CR_SER (1 << 1) #define FLASH_CR_MER (1 << 2) +#define FLASH_CR_SNB0 (1 << 3) +#define FLASH_CR_SNB4 (1 << 7) #define FLASH_CR_PSIZE8 (0 << 8) #define FLASH_CR_PSIZE16 (1 << 8) #define FLASH_CR_PSIZE32 (2 << 8) #define FLASH_CR_PSIZE64 (3 << 8) +#define FLASH_CR_MER1 (1 << 15) #define FLASH_CR_STRT (1 << 16) #define FLASH_CR_EOPIE (1 << 24) #define FLASH_CR_ERRIE (1 << 25) @@ -109,7 +112,12 @@ static const char stm32f4_xml_memory_map[] = "" #define FLASH_OPTCR_OPTLOCK (1 << 0) #define FLASH_OPTCR_OPTSTRT (1 << 1) -#define FLASH_OPTCR_RESERVED 0xf0000013 +#define FLASH_OPTCR_DB1M (1 << 30) +#define FLASH_OPTCR_RESET 0x0fffffed +#define FLASH_OPTCR_DEFAULT 0x0fffaaed +#define FLASH_OPTCR_RESET_F4_2_3 0x0ffffffd +#define FLASH_OPTCR_DEFAULT_F4_2_3 0x0fffaafd +#define FLASH_OPTCR1_RESET_F4_2_3 0x0fff0000 #define KEY1 0x45670123 #define KEY2 0xCDEF89AB @@ -173,6 +181,7 @@ bool stm32f4_probe(struct target_s *target) case 0x423: /* F401 */ case 0x419: /* 427/437 */ target->driver = stm32f4_driver_str; + target->idcode = idcode & 0xFFF; target->xml_mem_map = stm32f4_xml_memory_map; target->flash_erase = stm32f4_flash_erase; target->flash_write = stm32f4_flash_write; @@ -197,25 +206,54 @@ static int stm32f4_flash_erase(struct target_s *target, uint32_t addr, int len) uint16_t sr; uint32_t cr; uint32_t pagesize; + int sector; + int db1m = 0; + const uint8_t sector2size[] = + {0x04, 0x04, 0x04, 0x04, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20}; - addr &= 0x07FFC000; + addr &= 0x07FFc000; stm32f4_flash_unlock(ap); + if (target->idcode == 0x419) + db1m = adiv5_ap_mem_read(ap, FLASH_OPTCR) & FLASH_OPTCR_DB1M; while(len) { - if (addr < 0x10000) { /* Sector 0..3 */ - cr = (addr >> 11); - pagesize = 0x4000; - } else if (addr < 0x20000) { /* Sector 4 */ - cr = (4 << 3); - pagesize = 0x10000; - } else if (addr < 0x100000) { /* Sector 5..11 */ - cr = (((addr - 0x20000) >> 14) + 0x28); - pagesize = 0x20000; - } else { /* Sector > 11 ?? */ - return -1; + if (addr < 0x10000) + sector = addr/0x4000; /* Sector 0..3 */ + else if (addr < 0x20000) + sector = 4; + else if (!db1m) { + if (addr < 0x100000) /* Sector 5..11 */ + sector = addr/0x20000 + 4; + else { + addr = addr - 0x100000; + if (addr < 0x10000) + sector = addr/0x4000 + 12; /* Sector 12..15 */ + else if (addr < 0x20000) + sector = 16; + else /* Sector 17..23 */ + sector = addr/0x20000 + 16; + } + } else { /* 1MiB device mapped as dual boot */ + if (addr < 0x80000) /* Sector 5..7*/ + sector = addr/0x20000 + 4; + else { + addr = addr - 0x80000; + if (addr < 0x10000) + sector = addr/0x4000 + 12; /* Sector 12..15 */ + else if (addr < 0x20000) + sector = 16; + else /* Sector 17..19 */ + sector = addr/0x20000 + 16; + } + } + cr = FLASH_CR_EOPIE | FLASH_CR_ERRIE | FLASH_CR_SER; + if (sector > 11) { + sector = sector - 12; + cr |= FLASH_CR_SNB4; } - cr |= FLASH_CR_EOPIE | FLASH_CR_ERRIE | FLASH_CR_SER; + cr |= (sector) * FLASH_CR_SNB0; + /* Flash page erase instruction */ adiv5_ap_mem_write(ap, FLASH_CR, cr); /* write address to FMA */ @@ -225,7 +263,7 @@ static int stm32f4_flash_erase(struct target_s *target, uint32_t addr, int len) while(adiv5_ap_mem_read(ap, FLASH_SR) & FLASH_SR_BSY) if(target_check_error(target)) return -1; - + pagesize = (sector2size[sector]) << 12; len -= pagesize; addr += pagesize; } @@ -277,6 +315,7 @@ static bool stm32f4_cmd_erase_mass(target *t) { const char spinner[] = "|/-\\"; int spinindex = 0; + uint32_t flash_cr = FLASH_CR_MER; ADIv5_AP_t *ap = adiv5_target_ap(t); @@ -284,9 +323,10 @@ static bool stm32f4_cmd_erase_mass(target *t) stm32f4_flash_unlock(ap); /* Flash mass erase start instruction */ - adiv5_ap_mem_write(ap, FLASH_CR, FLASH_CR_MER); - adiv5_ap_mem_write(ap, FLASH_CR, FLASH_CR_STRT | FLASH_CR_MER); - + if (t->idcode == 0x419) + flash_cr |= FLASH_CR_MER1; + adiv5_ap_mem_write(ap, FLASH_CR, flash_cr); + adiv5_ap_mem_write(ap, FLASH_CR, flash_cr | FLASH_CR_STRT; /* Read FLASH_SR to poll for BSY bit */ while(adiv5_ap_mem_read(ap, FLASH_SR) & FLASH_SR_BSY) { gdb_outf("\b%c", spinner[spinindex++ % 4]); @@ -305,17 +345,22 @@ static bool stm32f4_cmd_erase_mass(target *t) return true; } -static bool stm32f4_option_write(target *t, uint32_t value) +static bool stm32f4_option_write(target *t, uint32_t value, uint32_t value1) { ADIv5_AP_t *ap = adiv5_target_ap(t); adiv5_ap_mem_write(ap, FLASH_OPTKEYR, OPTKEY1); adiv5_ap_mem_write(ap, FLASH_OPTKEYR, OPTKEY2); - value &= ~FLASH_OPTCR_RESERVED; while(adiv5_ap_mem_read(ap, FLASH_SR) & FLASH_SR_BSY) if(target_check_error(t)) return -1; - + if (t->idcode == 0x419) { + value1 &= FLASH_OPTCR1_RESET_F4_2_3; + /* WRITE option bytes instruction */ + adiv5_ap_mem_write(ap, FLASH_OPTCR1, value); + value &= FLASH_OPTCR_RESET_F4_2_3; + } else + value &= FLASH_OPTCR_RESET; /* WRITE option bytes instruction */ adiv5_ap_mem_write(ap, FLASH_OPTCR, value); adiv5_ap_mem_write(ap, FLASH_OPTCR, value | FLASH_OPTCR_OPTSTRT); @@ -329,19 +374,26 @@ static bool stm32f4_option_write(target *t, uint32_t value) static bool stm32f4_cmd_option(target *t, int argc, char *argv[]) { - uint32_t addr, val; + uint32_t addr, val, val1; ADIv5_AP_t *ap = adiv5_target_ap(t); if ((argc == 2) && !strcmp(argv[1], "erase")) { - stm32f4_option_write(t, 0x0fffaaed); + if (t->idcode == 0x419) + stm32f4_option_write(t, FLASH_OPTCR_DEFAULT_F4_2_3, 0xffffffff); + else + stm32f4_option_write(t, FLASH_OPTCR_DEFAULT, 0xffffffff); } - else if ((argc == 3) && !strcmp(argv[1], "write")) { + else if ((argc > 2) && !strcmp(argv[1], "write")) { val = strtoul(argv[2], NULL, 0); - stm32f4_option_write(t, val); + if (argc > 3) + val1 = strtoul(argv[3], NULL, 0); + else + val1 = 0xffffffff; + stm32f4_option_write(t, val, val1); } else { gdb_out("usage: monitor option erase\n"); - gdb_out("usage: monitor option write \n"); + gdb_out("usage: monitor option write \n"); } for (int i = 0; i < 0xf; i += 8) { @@ -349,5 +401,10 @@ static bool stm32f4_cmd_option(target *t, int argc, char *argv[]) val = adiv5_ap_mem_read(ap, addr); gdb_outf("0x%08X: 0x%04X\n", addr, val & 0xFFFF); } + if (t->idcode == 0x419){ + addr = 0x1fffE008; + val = adiv5_ap_mem_read(ap, addr); + gdb_outf("0x%08X: 0x%04X\n", addr, val & 0xFFFF); + } return true; } -- cgit v1.2.3 From 09fbe783c5cdbc4d817fa4b59ccaab15f0167d97 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Mon, 14 Oct 2013 17:02:59 +0200 Subject: f4discovery: Limit clock to 48 MHz and stack 24 kiByte so that code can be compiled unchanged for F401Discovery too. TODO: Bump clk up to 84 MHz as soon as libopencm3 supports that speed. --- src/platforms/f4discovery/Makefile.inc | 2 +- src/platforms/f4discovery/platform.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/platforms/f4discovery/Makefile.inc b/src/platforms/f4discovery/Makefile.inc index f67b278..88575bb 100644 --- a/src/platforms/f4discovery/Makefile.inc +++ b/src/platforms/f4discovery/Makefile.inc @@ -7,7 +7,7 @@ CFLAGS += -Istm32/include -mcpu=cortex-m4 -mthumb \ -DSTM32F4 -DF4DISCOVERY -I../libopencm3/include \ -Iplatforms/stm32 -LDFLAGS = -lopencm3_stm32f4 -Wl,--defsym,_stack=0x20020000 \ +LDFLAGS = -lopencm3_stm32f4 -Wl,--defsym,_stack=0x20006000 \ -Wl,-T,platforms/stm32/f4discovery.ld -nostartfiles -lc -lnosys \ -Wl,-Map=mapfile -mthumb -mcpu=cortex-m4 -Wl,-gc-sections \ -mfloat-abi=hard -mfpu=fpv4-sp-d16 \ diff --git a/src/platforms/f4discovery/platform.c b/src/platforms/f4discovery/platform.c index 645a3c5..6ee36bd 100644 --- a/src/platforms/f4discovery/platform.c +++ b/src/platforms/f4discovery/platform.c @@ -53,7 +53,7 @@ int platform_init(void) scb_reset_core(); } - rcc_clock_setup_hse_3v3(&hse_8mhz_3v3[CLOCK_3V3_168MHZ]); + rcc_clock_setup_hse_3v3(&hse_8mhz_3v3[CLOCK_3V3_48MHZ]); /* Enable peripherals */ rcc_peripheral_enable_clock(&RCC_AHB2ENR, RCC_AHB2ENR_OTGFSEN); -- cgit v1.2.3 From 42570efaf8f76655fb6458f00dbfd20af0a73322 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Tue, 22 Oct 2013 07:48:06 +0800 Subject: Revert "STM32F4: Add handling of second bank and dual boot devices." This reverts commit 536482f8047f1ee984f362c5c5e3fe488353a1b7. --- src/stm32f4.c | 119 +++++++++++++++------------------------------------------- 1 file changed, 31 insertions(+), 88 deletions(-) (limited to 'src') diff --git a/src/stm32f4.c b/src/stm32f4.c index 0f2e840..cfbe9e3 100644 --- a/src/stm32f4.c +++ b/src/stm32f4.c @@ -23,10 +23,11 @@ * * Refereces: * ST doc - RM0090 - * Reference manual - STM32F405xx, STM32F407xx, STM32F415xx/417xx, - * STM32F42xxx and STM32F43xxx dvanced ARM-based 32-bit MCUs - * ST doc - RM0368 - * Reference manual - STM32F401xB/C advanced ARM-based 32-bit MCUs + * Reference manual - STM32F405xx, STM32F407xx, STM32F415xx and STM32F417xx + * advanced ARM-based 32-bit MCUs + * ST doc - PM0081 + * Programming manual - STM32F40xxx and STM32F41xxx Flash programming + * manual */ #include @@ -90,18 +91,14 @@ static const char stm32f4_xml_memory_map[] = "" #define FLASH_SR (FPEC_BASE+0x0C) #define FLASH_CR (FPEC_BASE+0x10) #define FLASH_OPTCR (FPEC_BASE+0x14) -#define FLASH_OPTCR1 (FPEC_BASE+0x18) #define FLASH_CR_PG (1 << 0) #define FLASH_CR_SER (1 << 1) #define FLASH_CR_MER (1 << 2) -#define FLASH_CR_SNB0 (1 << 3) -#define FLASH_CR_SNB4 (1 << 7) #define FLASH_CR_PSIZE8 (0 << 8) #define FLASH_CR_PSIZE16 (1 << 8) #define FLASH_CR_PSIZE32 (2 << 8) #define FLASH_CR_PSIZE64 (3 << 8) -#define FLASH_CR_MER1 (1 << 15) #define FLASH_CR_STRT (1 << 16) #define FLASH_CR_EOPIE (1 << 24) #define FLASH_CR_ERRIE (1 << 25) @@ -112,12 +109,7 @@ static const char stm32f4_xml_memory_map[] = "" #define FLASH_OPTCR_OPTLOCK (1 << 0) #define FLASH_OPTCR_OPTSTRT (1 << 1) -#define FLASH_OPTCR_DB1M (1 << 30) -#define FLASH_OPTCR_RESET 0x0fffffed -#define FLASH_OPTCR_DEFAULT 0x0fffaaed -#define FLASH_OPTCR_RESET_F4_2_3 0x0ffffffd -#define FLASH_OPTCR_DEFAULT_F4_2_3 0x0fffaafd -#define FLASH_OPTCR1_RESET_F4_2_3 0x0fff0000 +#define FLASH_OPTCR_RESERVED 0xf0000013 #define KEY1 0x45670123 #define KEY2 0xCDEF89AB @@ -181,7 +173,6 @@ bool stm32f4_probe(struct target_s *target) case 0x423: /* F401 */ case 0x419: /* 427/437 */ target->driver = stm32f4_driver_str; - target->idcode = idcode & 0xFFF; target->xml_mem_map = stm32f4_xml_memory_map; target->flash_erase = stm32f4_flash_erase; target->flash_write = stm32f4_flash_write; @@ -206,54 +197,25 @@ static int stm32f4_flash_erase(struct target_s *target, uint32_t addr, int len) uint16_t sr; uint32_t cr; uint32_t pagesize; - int sector; - int db1m = 0; - const uint8_t sector2size[] = - {0x04, 0x04, 0x04, 0x04, 0x10, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20}; - addr &= 0x07FFc000; + addr &= 0x07FFC000; stm32f4_flash_unlock(ap); - if (target->idcode == 0x419) - db1m = adiv5_ap_mem_read(ap, FLASH_OPTCR) & FLASH_OPTCR_DB1M; while(len) { - if (addr < 0x10000) - sector = addr/0x4000; /* Sector 0..3 */ - else if (addr < 0x20000) - sector = 4; - else if (!db1m) { - if (addr < 0x100000) /* Sector 5..11 */ - sector = addr/0x20000 + 4; - else { - addr = addr - 0x100000; - if (addr < 0x10000) - sector = addr/0x4000 + 12; /* Sector 12..15 */ - else if (addr < 0x20000) - sector = 16; - else /* Sector 17..23 */ - sector = addr/0x20000 + 16; - } - } else { /* 1MiB device mapped as dual boot */ - if (addr < 0x80000) /* Sector 5..7*/ - sector = addr/0x20000 + 4; - else { - addr = addr - 0x80000; - if (addr < 0x10000) - sector = addr/0x4000 + 12; /* Sector 12..15 */ - else if (addr < 0x20000) - sector = 16; - else /* Sector 17..19 */ - sector = addr/0x20000 + 16; - } - } - cr = FLASH_CR_EOPIE | FLASH_CR_ERRIE | FLASH_CR_SER; - if (sector > 11) { - sector = sector - 12; - cr |= FLASH_CR_SNB4; + if (addr < 0x10000) { /* Sector 0..3 */ + cr = (addr >> 11); + pagesize = 0x4000; + } else if (addr < 0x20000) { /* Sector 4 */ + cr = (4 << 3); + pagesize = 0x10000; + } else if (addr < 0x100000) { /* Sector 5..11 */ + cr = (((addr - 0x20000) >> 14) + 0x28); + pagesize = 0x20000; + } else { /* Sector > 11 ?? */ + return -1; } - cr |= (sector) * FLASH_CR_SNB0; - + cr |= FLASH_CR_EOPIE | FLASH_CR_ERRIE | FLASH_CR_SER; /* Flash page erase instruction */ adiv5_ap_mem_write(ap, FLASH_CR, cr); /* write address to FMA */ @@ -263,7 +225,7 @@ static int stm32f4_flash_erase(struct target_s *target, uint32_t addr, int len) while(adiv5_ap_mem_read(ap, FLASH_SR) & FLASH_SR_BSY) if(target_check_error(target)) return -1; - pagesize = (sector2size[sector]) << 12; + len -= pagesize; addr += pagesize; } @@ -315,7 +277,6 @@ static bool stm32f4_cmd_erase_mass(target *t) { const char spinner[] = "|/-\\"; int spinindex = 0; - uint32_t flash_cr = FLASH_CR_MER; ADIv5_AP_t *ap = adiv5_target_ap(t); @@ -323,10 +284,9 @@ static bool stm32f4_cmd_erase_mass(target *t) stm32f4_flash_unlock(ap); /* Flash mass erase start instruction */ - if (t->idcode == 0x419) - flash_cr |= FLASH_CR_MER1; - adiv5_ap_mem_write(ap, FLASH_CR, flash_cr); - adiv5_ap_mem_write(ap, FLASH_CR, flash_cr | FLASH_CR_STRT; + adiv5_ap_mem_write(ap, FLASH_CR, FLASH_CR_MER); + adiv5_ap_mem_write(ap, FLASH_CR, FLASH_CR_STRT | FLASH_CR_MER); + /* Read FLASH_SR to poll for BSY bit */ while(adiv5_ap_mem_read(ap, FLASH_SR) & FLASH_SR_BSY) { gdb_outf("\b%c", spinner[spinindex++ % 4]); @@ -345,22 +305,17 @@ static bool stm32f4_cmd_erase_mass(target *t) return true; } -static bool stm32f4_option_write(target *t, uint32_t value, uint32_t value1) +static bool stm32f4_option_write(target *t, uint32_t value) { ADIv5_AP_t *ap = adiv5_target_ap(t); adiv5_ap_mem_write(ap, FLASH_OPTKEYR, OPTKEY1); adiv5_ap_mem_write(ap, FLASH_OPTKEYR, OPTKEY2); + value &= ~FLASH_OPTCR_RESERVED; while(adiv5_ap_mem_read(ap, FLASH_SR) & FLASH_SR_BSY) if(target_check_error(t)) return -1; - if (t->idcode == 0x419) { - value1 &= FLASH_OPTCR1_RESET_F4_2_3; - /* WRITE option bytes instruction */ - adiv5_ap_mem_write(ap, FLASH_OPTCR1, value); - value &= FLASH_OPTCR_RESET_F4_2_3; - } else - value &= FLASH_OPTCR_RESET; + /* WRITE option bytes instruction */ adiv5_ap_mem_write(ap, FLASH_OPTCR, value); adiv5_ap_mem_write(ap, FLASH_OPTCR, value | FLASH_OPTCR_OPTSTRT); @@ -374,26 +329,19 @@ static bool stm32f4_option_write(target *t, uint32_t value, uint32_t value1) static bool stm32f4_cmd_option(target *t, int argc, char *argv[]) { - uint32_t addr, val, val1; + uint32_t addr, val; ADIv5_AP_t *ap = adiv5_target_ap(t); if ((argc == 2) && !strcmp(argv[1], "erase")) { - if (t->idcode == 0x419) - stm32f4_option_write(t, FLASH_OPTCR_DEFAULT_F4_2_3, 0xffffffff); - else - stm32f4_option_write(t, FLASH_OPTCR_DEFAULT, 0xffffffff); + stm32f4_option_write(t, 0x0fffaaed); } - else if ((argc > 2) && !strcmp(argv[1], "write")) { + else if ((argc == 3) && !strcmp(argv[1], "write")) { val = strtoul(argv[2], NULL, 0); - if (argc > 3) - val1 = strtoul(argv[3], NULL, 0); - else - val1 = 0xffffffff; - stm32f4_option_write(t, val, val1); + stm32f4_option_write(t, val); } else { gdb_out("usage: monitor option erase\n"); - gdb_out("usage: monitor option write \n"); + gdb_out("usage: monitor option write \n"); } for (int i = 0; i < 0xf; i += 8) { @@ -401,10 +349,5 @@ static bool stm32f4_cmd_option(target *t, int argc, char *argv[]) val = adiv5_ap_mem_read(ap, addr); gdb_outf("0x%08X: 0x%04X\n", addr, val & 0xFFFF); } - if (t->idcode == 0x419){ - addr = 0x1fffE008; - val = adiv5_ap_mem_read(ap, addr); - gdb_outf("0x%08X: 0x%04X\n", addr, val & 0xFFFF); - } return true; } -- cgit v1.2.3 From 8014d434dedca4f8066dfd5b3d25bf98e72a66b7 Mon Sep 17 00:00:00 2001 From: Frantisek Burian Date: Sat, 4 Jan 2014 17:27:57 +0100 Subject: Update to the newest libopencm3 --- libopencm3 | 2 +- src/platforms/f4discovery/platform.c | 2 +- src/platforms/f4discovery/usbdfu.c | 2 +- src/platforms/native/platform.c | 2 +- src/platforms/native/usbdfu.c | 2 +- src/platforms/stlink/platform.c | 6 +++--- src/platforms/stlink/usbdfu.c | 2 +- src/platforms/swlink/platform.c | 2 +- src/platforms/swlink/usbdfu.c | 2 +- 9 files changed, 11 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/libopencm3 b/libopencm3 index f4cd74a..a909b5c 160000 --- a/libopencm3 +++ b/libopencm3 @@ -1 +1 @@ -Subproject commit f4cd74a741084decb805d8dd15253f77f404ad24 +Subproject commit a909b5ca9e18f802e3caef19e63d38861662c128 diff --git a/src/platforms/f4discovery/platform.c b/src/platforms/f4discovery/platform.c index 6ee36bd..2786954 100644 --- a/src/platforms/f4discovery/platform.c +++ b/src/platforms/f4discovery/platform.c @@ -81,7 +81,7 @@ int platform_init(void) LED_UART | LED_IDLE_RUN | LED_ERROR | LED_BOOTLOADER); /* Setup heartbeat timer */ - systick_set_clocksource(STK_CTRL_CLKSOURCE_AHB_DIV8); + systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); systick_set_reload(168000000/(10*8)); /* Interrupt us at 10 Hz */ SCB_SHPR(11) &= ~((15 << 4) & 0xff); SCB_SHPR(11) |= ((14 << 4) & 0xff); diff --git a/src/platforms/f4discovery/usbdfu.c b/src/platforms/f4discovery/usbdfu.c index 998628b..b7af115 100644 --- a/src/platforms/f4discovery/usbdfu.c +++ b/src/platforms/f4discovery/usbdfu.c @@ -42,7 +42,7 @@ int main(void) /* Set up clock*/ rcc_clock_setup_hse_3v3(&hse_8mhz_3v3[CLOCK_3V3_168MHZ]); - systick_set_clocksource(STK_CTRL_CLKSOURCE_AHB_DIV8); + systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); systick_set_reload(2100000); systick_interrupt_enable(); diff --git a/src/platforms/native/platform.c b/src/platforms/native/platform.c index 214625e..c0ce658 100644 --- a/src/platforms/native/platform.c +++ b/src/platforms/native/platform.c @@ -119,7 +119,7 @@ int platform_init(void) } /* Setup heartbeat timer */ - systick_set_clocksource(STK_CTRL_CLKSOURCE_AHB_DIV8); + systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); systick_set_reload(900000); /* Interrupt us at 10 Hz */ SCB_SHPR(11) &= ~((15 << 4) & 0xff); SCB_SHPR(11) |= ((14 << 4) & 0xff); diff --git a/src/platforms/native/usbdfu.c b/src/platforms/native/usbdfu.c index 35572a5..068138e 100644 --- a/src/platforms/native/usbdfu.c +++ b/src/platforms/native/usbdfu.c @@ -41,7 +41,7 @@ int main(void) dfu_protect_enable(); rcc_clock_setup_in_hse_8mhz_out_72mhz(); - systick_set_clocksource(STK_CTRL_CLKSOURCE_AHB_DIV8); + systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); systick_set_reload(900000); rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); diff --git a/src/platforms/stlink/platform.c b/src/platforms/stlink/platform.c index 03509ea..d7ae41d 100644 --- a/src/platforms/stlink/platform.c +++ b/src/platforms/stlink/platform.c @@ -22,13 +22,13 @@ * implementation. */ -#include +#include #include #include #include #include #include -#include +#include #include "platform.h" #include "jtag_scan.h" @@ -108,7 +108,7 @@ int platform_init(void) GPIO_CNF_OUTPUT_PUSHPULL, led_idle_run); /* Setup heartbeat timer */ - systick_set_clocksource(STK_CTRL_CLKSOURCE_AHB_DIV8); + systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); systick_set_reload(900000); /* Interrupt us at 10 Hz */ SCB_SHPR(11) &= ~((15 << 4) & 0xff); SCB_SHPR(11) |= ((14 << 4) & 0xff); diff --git a/src/platforms/stlink/usbdfu.c b/src/platforms/stlink/usbdfu.c index 76a19b0..c14fd5a 100644 --- a/src/platforms/stlink/usbdfu.c +++ b/src/platforms/stlink/usbdfu.c @@ -95,7 +95,7 @@ int main(void) dfu_protect_enable(); rcc_clock_setup_in_hse_8mhz_out_72mhz(); - systick_set_clocksource(STK_CTRL_CLKSOURCE_AHB_DIV8); + systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); systick_set_reload(900000); /* Handle USB disconnect/connect */ diff --git a/src/platforms/swlink/platform.c b/src/platforms/swlink/platform.c index 1b45cfb..ea88dcb 100644 --- a/src/platforms/swlink/platform.c +++ b/src/platforms/swlink/platform.c @@ -86,7 +86,7 @@ int platform_init(void) AFIO_MAPR = data; /* Setup heartbeat timer */ - systick_set_clocksource(STK_CTRL_CLKSOURCE_AHB_DIV8); + systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); systick_set_reload(900000); /* Interrupt us at 10 Hz */ SCB_SHPR(11) &= ~((15 << 4) & 0xff); SCB_SHPR(11) |= ((14 << 4) & 0xff); diff --git a/src/platforms/swlink/usbdfu.c b/src/platforms/swlink/usbdfu.c index 29c3809..69cc1e2 100644 --- a/src/platforms/swlink/usbdfu.c +++ b/src/platforms/swlink/usbdfu.c @@ -61,7 +61,7 @@ int main(void) dfu_protect_enable(); rcc_clock_setup_in_hse_8mhz_out_72mhz(); - systick_set_clocksource(STK_CTRL_CLKSOURCE_AHB_DIV8); + systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); systick_set_reload(900000); /* Handle USB disconnect/connect */ -- cgit v1.2.3 From 29c7846612f90acb7ced1f6a1d49d9062609ec2b Mon Sep 17 00:00:00 2001 From: Allen Ibara Date: Fri, 10 Jan 2014 10:26:45 -0800 Subject: LPC43XX: Make sure to align target struct to word alignment --- src/lpc43xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/lpc43xx.c b/src/lpc43xx.c index 0a8745d..1a437e3 100644 --- a/src/lpc43xx.c +++ b/src/lpc43xx.c @@ -106,7 +106,7 @@ struct flash_param { } make_active; } params; uint32_t result[5]; /* result data */ -}; +} __attribute__((aligned(4))); struct flash_program { struct flash_param p; -- cgit v1.2.3 From 813622b1b6146371a3a9ff50bc62727ecd1f6b26 Mon Sep 17 00:00:00 2001 From: Allen Ibara Date: Fri, 10 Jan 2014 10:48:59 -0800 Subject: LPC43XX: Add mkboot target command; dont make banks bootable by default. This used to be done transparently in the write step, however that breaks the 'verify' command. This is also more flexible for cases where you want to write a flash bank without ever intending it to be bootable. --- src/lpc43xx.c | 51 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 44 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/lpc43xx.c b/src/lpc43xx.c index 1a437e3..49f8068 100644 --- a/src/lpc43xx.c +++ b/src/lpc43xx.c @@ -114,6 +114,7 @@ struct flash_program { }; static bool lpc43xx_cmd_erase(target *t); +static bool lpc43xx_cmd_mkboot(target *target, int argc, const char *argv[]); static int lpc43xx_flash_init(struct target_s *target); static void lpc43xx_iap_call(struct target_s *target, struct flash_param *param, unsigned param_len); static int lpc43xx_flash_prepare(struct target_s *target, uint32_t addr, int len); @@ -122,6 +123,7 @@ static int lpc43xx_flash_write(struct target_s *target, uint32_t dest, const uin const struct command_s lpc43xx_cmd_list[] = { {"erase_mass", (cmd_handler)lpc43xx_cmd_erase, "Erase entire flash memory"}, + {"mkboot", lpc43xx_cmd_mkboot, "Make flash bank bootable"}, {NULL, NULL, NULL} }; @@ -467,21 +469,56 @@ static int lpc43xx_flash_write(struct target_s *target, uint32_t dest, const uin if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { return -1; } + } + + return 0; +} - /* special command to compute/write magic vector for signature */ - if (chunk == first_chunk) +/* + * Call Boot ROM code to make a flash bank bootable by computing and writing the + * correct signature into the exception table near the start of the bank. + * + * This is done indepently of writing to give the user a chance to verify flash + * before changing it. + */ +static bool lpc43xx_cmd_mkboot(target *target, int argc, const char *argv[]) +{ + /* Usage: mkboot 0 or mkboot 1 */ + if (argc == 2) + { + const long int bank = strtol(argv[1], NULL, 0); + + if (bank == 0 || bank == 1) { + lpc43xx_flash_init(target); + struct flash_program flash_pgm; + + /* special command to compute/write magic vector for signature */ flash_pgm.p.command = IAP_CMD_SET_ACTIVE_BANK; - flash_pgm.p.params.make_active.flash_bank = flash_bank(dest); + flash_pgm.p.params.make_active.flash_bank = bank; flash_pgm.p.params.make_active.cpu_clk_khz = CPU_CLK_KHZ; flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS; lpc43xx_iap_call(target, &flash_pgm.p, sizeof(flash_pgm)); - if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { - return -1; + if (flash_pgm.p.result[0] == IAP_STATUS_CMD_SUCCESS) { + gdb_outf("Set bootable OK.\n"); + return true; + } + else + { + gdb_outf("Set bootable failed.\n"); } } - + else + { + gdb_outf("Unexpected bank number, should be 0 or 1.\n"); + } + } + else + { + gdb_outf("Expected bank argument 0 or 1.\n"); } - return 0; + + return false; } + -- cgit v1.2.3 From 911af3b8363247d132abb9a11559104b0402ae56 Mon Sep 17 00:00:00 2001 From: Allen Ibara Date: Fri, 10 Jan 2014 10:54:56 -0800 Subject: LPC43XX: Add reset command to do a system reset (but not the debug). --- src/lpc43xx.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'src') diff --git a/src/lpc43xx.c b/src/lpc43xx.c index 49f8068..a578e67 100644 --- a/src/lpc43xx.c +++ b/src/lpc43xx.c @@ -114,6 +114,7 @@ struct flash_program { }; static bool lpc43xx_cmd_erase(target *t); +static bool lpc43xx_cmd_reset(target *target, int argc, const char *argv[]); static bool lpc43xx_cmd_mkboot(target *target, int argc, const char *argv[]); static int lpc43xx_flash_init(struct target_s *target); static void lpc43xx_iap_call(struct target_s *target, struct flash_param *param, unsigned param_len); @@ -123,6 +124,7 @@ static int lpc43xx_flash_write(struct target_s *target, uint32_t dest, const uin const struct command_s lpc43xx_cmd_list[] = { {"erase_mass", (cmd_handler)lpc43xx_cmd_erase, "Erase entire flash memory"}, + {"reset", lpc43xx_cmd_reset, "Reset target"}, {"mkboot", lpc43xx_cmd_mkboot, "Make flash bank bootable"}, {NULL, NULL, NULL} }; @@ -198,6 +200,20 @@ bool lpc43xx_probe(struct target_s *target) return false; } +/* Reset all major systems _except_ debug */ +static bool lpc43xx_cmd_reset(target *target, int __attribute__((unused)) argc, const char __attribute__((unused)) *argv[]) +{ + /* Cortex-M4 Application Interrupt and Reset Control Register */ + static const uint32_t AIRCR = 0xE000ED0C; + /* Magic value key */ + static const uint32_t reset_val = 0x05FA0004; + + /* System reset on target */ + target_mem_write_words(target, AIRCR, &reset_val, sizeof(reset_val)); + + return true; +} + static bool lpc43xx_cmd_erase(target *target) { uint32_t bank = 0; -- cgit v1.2.3 From df9c19f071b970b1a33c5ce1a99de706433e1113 Mon Sep 17 00:00:00 2001 From: Allen Ibara Date: Fri, 10 Jan 2014 10:56:19 -0800 Subject: LPC43XX: Remove type cast for erase function --- src/lpc43xx.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/lpc43xx.c b/src/lpc43xx.c index a578e67..758c2f1 100644 --- a/src/lpc43xx.c +++ b/src/lpc43xx.c @@ -113,7 +113,7 @@ struct flash_program { uint8_t data[IAP_PGM_CHUNKSIZE]; }; -static bool lpc43xx_cmd_erase(target *t); +static bool lpc43xx_cmd_erase(target *target, int argc, const char *argv[]); static bool lpc43xx_cmd_reset(target *target, int argc, const char *argv[]); static bool lpc43xx_cmd_mkboot(target *target, int argc, const char *argv[]); static int lpc43xx_flash_init(struct target_s *target); @@ -123,7 +123,7 @@ static int lpc43xx_flash_erase(struct target_s *target, uint32_t addr, int len); static int lpc43xx_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, int len); const struct command_s lpc43xx_cmd_list[] = { - {"erase_mass", (cmd_handler)lpc43xx_cmd_erase, "Erase entire flash memory"}, + {"erase_mass", lpc43xx_cmd_erase, "Erase entire flash memory"}, {"reset", lpc43xx_cmd_reset, "Reset target"}, {"mkboot", lpc43xx_cmd_mkboot, "Make flash bank bootable"}, {NULL, NULL, NULL} @@ -214,7 +214,7 @@ static bool lpc43xx_cmd_reset(target *target, int __attribute__((unused)) argc, return true; } -static bool lpc43xx_cmd_erase(target *target) +static bool lpc43xx_cmd_erase(target *target, int __attribute__((unused)) argc, const char __attribute__((unused)) *argv[]) { uint32_t bank = 0; struct flash_program flash_pgm; -- cgit v1.2.3 From 487252150fbeb9c0265ad7e9a6aa4057e09b4246 Mon Sep 17 00:00:00 2001 From: Allen Ibara Date: Fri, 10 Jan 2014 10:59:44 -0800 Subject: LPC: Cleanup regs_size (in bytes). Also use sizeof() to make it clear why we multiple and divide by 4. --- src/arm7tdmi.c | 2 +- src/lpc11xx.c | 2 +- src/lpc43xx.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/arm7tdmi.c b/src/arm7tdmi.c index ad38ab3..26c5233 100644 --- a/src/arm7tdmi.c +++ b/src/arm7tdmi.c @@ -131,7 +131,7 @@ void arm7tdmi_jtag_handler(jtag_dev_t *dev) t->mem_write_words = (void *)do_nothing; t->mem_read_bytes = (void *)do_nothing; t->mem_write_bytes = (void *)do_nothing; - t->regs_size = 16 * 4; + t->regs_size = 16 * sizeof(uint32_t); t->regs_read = (void *)arm7_regs_read; t->regs_write = (void *)arm7_regs_write; t->pc_write = (void *)do_nothing; diff --git a/src/lpc11xx.c b/src/lpc11xx.c index 9adbe2b..01afd87 100644 --- a/src/lpc11xx.c +++ b/src/lpc11xx.c @@ -116,7 +116,7 @@ lpc11xx_probe(struct target_s *target) static void lpc11x_iap_call(struct target_s *target, struct flash_param *param, unsigned param_len) { - uint32_t regs[target->regs_size / 4]; + uint32_t regs[target->regs_size / sizeof(uint32_t)]; /* fill out the remainder of the parameters and copy the structure to RAM */ param->opcodes[0] = 0xbe00; diff --git a/src/lpc43xx.c b/src/lpc43xx.c index 758c2f1..fbd3941 100644 --- a/src/lpc43xx.c +++ b/src/lpc43xx.c @@ -331,7 +331,7 @@ static int32_t sector_number(uint32_t addr) static void lpc43xx_iap_call(struct target_s *target, struct flash_param *param, unsigned param_len) { - uint32_t regs[target->regs_size / 4]; + uint32_t regs[target->regs_size / sizeof(uint32_t)]; uint32_t iap_entry; target_mem_read_words(target, &iap_entry, IAP_ENTRYPOINT_LOCATION, sizeof(iap_entry)); -- cgit v1.2.3 From 2b798fa8fc7b06de6053f09ad4394ee1454a5d82 Mon Sep 17 00:00:00 2001 From: Allen Ibara Date: Fri, 10 Jan 2014 11:10:57 -0800 Subject: LPC43XX: Make the chunk_offset logic more explicit. --- src/lpc43xx.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/lpc43xx.c b/src/lpc43xx.c index fbd3941..6954404 100644 --- a/src/lpc43xx.c +++ b/src/lpc43xx.c @@ -431,12 +431,20 @@ static int lpc43xx_flash_write(struct target_s *target, uint32_t dest, const uin { unsigned first_chunk = dest / IAP_PGM_CHUNKSIZE; unsigned last_chunk = (dest + len - 1) / IAP_PGM_CHUNKSIZE; - unsigned chunk_offset = dest % IAP_PGM_CHUNKSIZE; + unsigned chunk_offset; unsigned chunk; struct flash_program flash_pgm; for (chunk = first_chunk; chunk <= last_chunk; chunk++) { + if (chunk == first_chunk) + { + chunk_offset = dest % IAP_PGM_CHUNKSIZE; + } + else + { + chunk_offset = 0; + } /* first and last chunk may require special handling */ if ((chunk == first_chunk) || (chunk == last_chunk)) { @@ -454,7 +462,6 @@ static int lpc43xx_flash_write(struct target_s *target, uint32_t dest, const uin /* update to suit */ len -= copylen; src += copylen; - chunk_offset = 0; } else { /* interior chunk, must be aligned and full-sized */ -- cgit v1.2.3 From 01244fc84dca3d63483a292945a8a1a28098d4d7 Mon Sep 17 00:00:00 2001 From: Allen Ibara Date: Fri, 10 Jan 2014 11:53:46 -0800 Subject: LPC43XX: Force target to use internal clock. Without this, flash write timing might be incorrect. --- src/lpc43xx.c | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'src') diff --git a/src/lpc43xx.c b/src/lpc43xx.c index 6954404..b3a48a9 100644 --- a/src/lpc43xx.c +++ b/src/lpc43xx.c @@ -121,6 +121,7 @@ static void lpc43xx_iap_call(struct target_s *target, struct flash_param *param, static int lpc43xx_flash_prepare(struct target_s *target, uint32_t addr, int len); static int lpc43xx_flash_erase(struct target_s *target, uint32_t addr, int len); static int lpc43xx_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, int len); +static void lpc43xx_set_internal_clock(struct target_s *target); const struct command_s lpc43xx_cmd_list[] = { {"erase_mass", lpc43xx_cmd_erase, "Erase entire flash memory"}, @@ -255,6 +256,9 @@ static int lpc43xx_flash_init(struct target_s *target) { struct flash_program flash_pgm; + /* Force internal clock */ + lpc43xx_set_internal_clock(target); + /* Initialize flash IAP */ flash_pgm.p.command = IAP_CMD_INIT; flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS; @@ -427,6 +431,12 @@ lpc43xx_flash_erase(struct target_s *target, uint32_t addr, int len) return 0; } +static void lpc43xx_set_internal_clock(struct target_s *target) +{ + const uint32_t val2 = (1 << 11) | (1 << 24); + target_mem_write_words(target, 0x40050000 + 0x06C, &val2, sizeof(val2)); +} + static int lpc43xx_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, int len) { unsigned first_chunk = dest / IAP_PGM_CHUNKSIZE; -- cgit v1.2.3 From ce17cc2e2b8b5afe79247dcd96f1fc222fed1dfc Mon Sep 17 00:00:00 2001 From: Pavel Burgr Date: Sat, 14 Dec 2013 21:25:10 +0100 Subject: Fix in checksum calculation condition --- src/lpc11xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/lpc11xx.c b/src/lpc11xx.c index 9adbe2b..f7d72fa 100644 --- a/src/lpc11xx.c +++ b/src/lpc11xx.c @@ -216,7 +216,7 @@ lpc11xx_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, chunk_offset = 0; /* if we are programming the vectors, calculate the magic number */ - if (dest == 0) { + if (chunk * IAP_PGM_CHUNKSIZE == 0) { uint32_t *w = (uint32_t *)(&flash_pgm.data[0]); uint32_t sum = 0; -- cgit v1.2.3 From 0c9d5d816639c2b4ebce2b234be52e6aac4275a7 Mon Sep 17 00:00:00 2001 From: bon@elektron.ikp.physik.tu-darmstadt.de Date: Mon, 6 Jan 2014 12:51:09 +0100 Subject: Add dfu bootloader update application and use absolute delay for stlink Hello, appended 3 patches - adds a dfu-bootloader appliaction - uses absolute delays when waiting for pull-up delays on the STLINK (hopefully fixes issue #30) Updating the dfu-bootloader by additional application is helpfull for the STLINK, as for flashing the bootloader by SWDb otherwise jumpers need to be soldered or external SWD is not possible. Use like: - dfu-util -s 0x08002000:leave -D dfu_upgrade.bin - dfu-util -s 0x08000000:leave -D blackmagic_dfu.bin - Push reset buttom and reconnect to enter new dfu bootloader - dfu-util -s 0x08002000:leave -D blackmagic.bin -- Uwe Bonnes bon@elektron.ikp.physik.tu-darmstadt.de Institut fuer Kernphysik Schlossgartenstrasse 9 64289 Darmstadt --------- Tel. 06151 162516 -------- Fax. 06151 164321 ---------- >From fae5022c304a8866f056ea66660ac7ce3809dcf8 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Sun, 20 Oct 2013 15:00:36 +0200 Subject: F1: Prepare to update dfu bootloader via DFU with additional application. --- .gitignore | 6 +- src/platforms/native/platform.h | 2 + src/platforms/native/usbdfu.c | 6 +- src/platforms/stlink/Makefile.inc | 13 +++- src/platforms/stlink/dfu_upgrade.c | 127 +++++++++++++++++++++++++++++++++++++ src/platforms/stlink/platform.h | 2 + src/platforms/stlink/usbdfu.c | 33 ++++++---- src/platforms/stm32/dfu_f1.c | 17 +++-- src/platforms/stm32/dfucore.c | 17 +++-- src/platforms/stm32/usbdfu.h | 16 ++--- src/platforms/swlink/platform.h | 2 + src/platforms/swlink/usbdfu.c | 6 +- 12 files changed, 209 insertions(+), 38 deletions(-) create mode 100644 src/platforms/stlink/dfu_upgrade.c (limited to 'src') diff --git a/.gitignore b/.gitignore index 92e1e57..82a3e84 100644 --- a/.gitignore +++ b/.gitignore @@ -1,8 +1,8 @@ blackmagic -blackmagic.bin +*.bin +*.hex blackmagic_dfu -blackmagic_dfu.bin -blackmagic_dfu.hex +dfu_upgrade mapfile *.o *.d diff --git a/src/platforms/native/platform.h b/src/platforms/native/platform.h index 62d565b..a1a28cf 100644 --- a/src/platforms/native/platform.h +++ b/src/platforms/native/platform.h @@ -37,8 +37,10 @@ #define PLATFORM_HAS_TRACESWO #define BOARD_IDENT "Black Magic Probe" #define BOARD_IDENT_DFU "Black Magic Probe (Upgrade)" +#define BOARD_IDENT_UPD "Black Magic Probe (DFU Upgrade)" #define DFU_IDENT "Black Magic Firmware Upgrade" #define DFU_IFACE_STRING "@Internal Flash /0x08000000/8*001Ka,120*001Kg" +#define UPD_IFACE_STRING "@Internal Flash /0x08000000/8*001Kg" extern usbd_device *usbdev; #define CDCACM_GDB_ENDPOINT 1 diff --git a/src/platforms/native/usbdfu.c b/src/platforms/native/usbdfu.c index 068138e..e9094a3 100644 --- a/src/platforms/native/usbdfu.c +++ b/src/platforms/native/usbdfu.c @@ -25,6 +25,8 @@ #include "usbdfu.h" +uint32_t app_address = 0x08002000; + void dfu_detach(void) { /* USB device must detach, we just reset... */ @@ -38,7 +40,7 @@ int main(void) if(gpio_get(GPIOB, GPIO12)) dfu_jump_app_if_valid(); - dfu_protect_enable(); + dfu_protect(DFU_MODE); rcc_clock_setup_in_hse_8mhz_out_72mhz(); systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); @@ -56,7 +58,7 @@ int main(void) gpio_set_mode(GPIOB, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO2 | GPIO10); - dfu_init(&stm32f103_usb_driver); + dfu_init(&stm32f103_usb_driver, DFU_MODE); gpio_set(GPIOA, GPIO8); gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, diff --git a/src/platforms/stlink/Makefile.inc b/src/platforms/stlink/Makefile.inc index 1f46588..5cfe726 100644 --- a/src/platforms/stlink/Makefile.inc +++ b/src/platforms/stlink/Makefile.inc @@ -18,7 +18,7 @@ SRC += cdcacm.c \ platform.c \ usbuart.c \ -all: blackmagic.bin blackmagic_dfu.bin blackmagic_dfu.hex +all: blackmagic.bin blackmagic_dfu.bin blackmagic_dfu.hex dfu_upgrade.bin dfu_upgrade.hex blackmagic.bin: blackmagic $(OBJCOPY) -O binary $^ $@ @@ -32,6 +32,15 @@ blackmagic_dfu.bin: blackmagic_dfu blackmagic_dfu.hex: blackmagic_dfu $(OBJCOPY) -O ihex $^ $@ +dfu_upgrade: dfu_upgrade.o dfucore.o dfu_f1.o + $(CC) $^ -o $@ $(LDFLAGS) + +dfu_upgrade.bin: dfu_upgrade + $(OBJCOPY) -O binary $^ $@ + +dfu_upgrade.hex: dfu_upgrade + $(OBJCOPY) -O ihex $^ $@ + host_clean: - -rm blackmagic.bin blackmagic_dfu blackmagic_dfu.bin blackmagic_dfu.hex + -rm blackmagic.bin blackmagic_dfu blackmagic_dfu.bin blackmagic_dfu.hex dfu_upgrade dfu_upgrade.bin dfu_upgrade.hex diff --git a/src/platforms/stlink/dfu_upgrade.c b/src/platforms/stlink/dfu_upgrade.c new file mode 100644 index 0000000..2c7c1ad --- /dev/null +++ b/src/platforms/stlink/dfu_upgrade.c @@ -0,0 +1,127 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2013 Gareth McMullin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * 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, see . + */ + +#include +#include +#include +#include +#include + +#include "usbdfu.h" +uint32_t app_address = 0x08000000; + +static uint8_t rev; +static uint16_t led_idle_run; +static uint32_t led2_state = 0; + +void dfu_detach(void) +{ + /* Disconnect USB cable by resetting USB Device + and pulling USB_DP low*/ + rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1ENR_USBEN); + rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1ENR_USBEN); + rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USBEN); + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); + gpio_clear(GPIOA, GPIO12); + gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_OPENDRAIN, GPIO12); + /* Pull PB0 (T_NRST) low + */ + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPBEN); + gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_OPENDRAIN, GPIO0); + gpio_clear(GPIOB, GPIO0); + SCB_VTOR = 0; + scb_reset_core(); +} + +void stlink_set_rev(void) +{ + int i; + + /* First, get Board revision by pulling PC13/14 up. Read + * 11 for ST-Link V1, e.g. on VL Discovery, tag as rev 0 + * 10 for ST-Link V2, e.g. on F4 Discovery, tag as rev 1 + */ + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN); + gpio_set_mode(GPIOC, GPIO_MODE_INPUT, + GPIO_CNF_INPUT_PULL_UPDOWN, GPIO14 | GPIO13); + gpio_set(GPIOC, GPIO14 | GPIO13); + for (i = 0; i < 100; i++) + rev = (~(gpio_get(GPIOC, GPIO14 | GPIO13)) >> 13) & 3; + + switch (rev) { + case 0: + led_idle_run = GPIO8; + break; + default: + led_idle_run = GPIO9; + } + gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, led_idle_run); +} + +int main(void) +{ + + rcc_clock_setup_in_hse_8mhz_out_72mhz(); + + stlink_set_rev(); + + systick_set_clocksource(STK_CTRL_CLKSOURCE_AHB_DIV8); + systick_set_reload(900000); + + dfu_protect(UPD_MODE); + + /* Handle USB disconnect/connect */ + /* Just in case: Disconnect USB cable by resetting USB Device + * and pulling USB_DP low + * Device will reconnect automatically as Pull-Up is hard wired*/ + rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1ENR_USBEN); + rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1ENR_USBEN); + rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USBEN); + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); + gpio_clear(GPIOA, GPIO12); + gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_OPENDRAIN, GPIO12); + + systick_interrupt_enable(); + systick_counter_enable(); + + dfu_init(&stm32f103_usb_driver, UPD_MODE); + + dfu_main(); +} + +void sys_tick_handler(void) +{ + if (rev == 0) { + gpio_toggle(GPIOA, led_idle_run); + } else { + if (led2_state & 1) { + gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, + GPIO_CNF_OUTPUT_PUSHPULL, led_idle_run); + gpio_set(GPIOA, led_idle_run); + } else { + gpio_set_mode(GPIOA, GPIO_MODE_INPUT, + GPIO_CNF_INPUT_ANALOG, led_idle_run); + } + led2_state++; + } +} diff --git a/src/platforms/stlink/platform.h b/src/platforms/stlink/platform.h index a9e405b..ffe9fbf 100644 --- a/src/platforms/stlink/platform.h +++ b/src/platforms/stlink/platform.h @@ -36,8 +36,10 @@ #define CDCACM_PACKET_SIZE 64 #define BOARD_IDENT "Black Magic Probe (STLINK), (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" #define BOARD_IDENT_DFU "Black Magic (Upgrade) for STLink/Discovery, (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" +#define BOARD_IDENT_UPD "Black Magic (DFU Upgrade) for STLink/Discovery, (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" #define DFU_IDENT "Black Magic Firmware Upgrade (STLINK)" #define DFU_IFACE_STRING "@Internal Flash /0x08000000/8*001Ka,56*001Kg" +#define UPD_IFACE_STRING "@Internal Flash /0x08000000/8*001Kg" extern usbd_device *usbdev; #define CDCACM_GDB_ENDPOINT 1 diff --git a/src/platforms/stlink/usbdfu.c b/src/platforms/stlink/usbdfu.c index c14fd5a..1a40e64 100644 --- a/src/platforms/stlink/usbdfu.c +++ b/src/platforms/stlink/usbdfu.c @@ -29,24 +29,31 @@ static uint8_t rev; static uint16_t led_idle_run; static uint32_t led2_state = 0; +uint32_t app_address = 0x08002000; + static int stlink_test_nrst(void) { /* Test if JRST/NRST is pulled down*/ - int i; uint16_t nrst; uint16_t pin; + uint32_t systick_value; + + systick_set_clocksource(STK_CTRL_CLKSOURCE_AHB_DIV8); + systick_set_reload(0xffffff); /* no underflow for about 16.7 seconds*/ + systick_counter_enable(); + /* systick ist now running with 1 MHz, systick counts down */ /* First, get Board revision by pulling PC13/14 up. Read * 11 for ST-Link V1, e.g. on VL Discovery, tag as rev 0 * 10 for ST-Link V2, e.g. on F4 Discovery, tag as rev 1 */ - for (i = 0; i < 0x200; i++) { - rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN); - gpio_set_mode(GPIOC, GPIO_MODE_INPUT, - GPIO_CNF_INPUT_PULL_UPDOWN, GPIO14 | GPIO13); - gpio_set(GPIOC, GPIO14 | GPIO13); - rev = (~(gpio_get(GPIOC, GPIO14 | GPIO13)) >> 13) & 3; - } + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN); + gpio_set_mode(GPIOC, GPIO_MODE_INPUT, + GPIO_CNF_INPUT_PULL_UPDOWN, GPIO14 | GPIO13); + gpio_set(GPIOC, GPIO14 | GPIO13); + systick_value = systick_get_value(); + while (systick_get_value() > (systick_value - 1000)); /* Wait 1 msec*/ + rev = (~(gpio_get(GPIOC, GPIO14 | GPIO13)) >> 13) & 3; switch (rev) { case 0: pin = GPIO1; @@ -62,8 +69,10 @@ static int stlink_test_nrst(void) gpio_set_mode(GPIOB, GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, pin); gpio_set(GPIOB, pin); - for (i = 0; i < 100; i++) - nrst = gpio_get(GPIOB, pin); + systick_value = systick_get_value(); + while (systick_get_value() > (systick_value - 20000)); /* Wait 20 msec*/ + nrst = gpio_get(GPIOB, pin); + systick_counter_disable(); return (nrst) ? 1 : 0; } @@ -92,7 +101,7 @@ int main(void) if(((GPIOA_CRL & 0x40) == 0x40) && stlink_test_nrst()) dfu_jump_app_if_valid(); - dfu_protect_enable(); + dfu_protect(DFU_MODE); rcc_clock_setup_in_hse_8mhz_out_72mhz(); systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); @@ -113,7 +122,7 @@ int main(void) systick_interrupt_enable(); systick_counter_enable(); - dfu_init(&stm32f103_usb_driver); + dfu_init(&stm32f103_usb_driver, DFU_MODE); dfu_main(); } diff --git a/src/platforms/stm32/dfu_f1.c b/src/platforms/stm32/dfu_f1.c index 08cbb02..77b6f58 100644 --- a/src/platforms/stm32/dfu_f1.c +++ b/src/platforms/stm32/dfu_f1.c @@ -59,8 +59,9 @@ uint32_t dfu_poll_timeout(uint8_t cmd, uint32_t addr, uint16_t blocknum) return 100; } -void dfu_protect_enable(void) +void dfu_protect(dfu_mode_t mode) { + if (mode == DFU_MODE) { #ifdef DFU_SELF_PROTECT if ((FLASH_WRPR & 0x03) != 0x00) { flash_unlock(); @@ -72,19 +73,25 @@ void dfu_protect_enable(void) flash_program_option_bytes(FLASH_OBP_WRP10, 0x03FC); } #endif + } + else if (mode == UPD_MODE) { + flash_unlock(); + FLASH_CR = 0; + flash_erase_option_bytes(); + } } void dfu_jump_app_if_valid(void) { /* Boot the application if it's valid */ - if((*(volatile uint32_t*)APP_ADDRESS & 0x2FFE0000) == 0x20000000) { + if((*(volatile uint32_t*)app_address & 0x2FFE0000) == 0x20000000) { /* Set vector table base address */ - SCB_VTOR = APP_ADDRESS & 0x1FFFFF; /* Max 2 MByte Flash*/ + SCB_VTOR = app_address & 0x1FFFFF; /* Max 2 MByte Flash*/ /* Initialise master stack pointer */ asm volatile ("msr msp, %0"::"g" - (*(volatile uint32_t*)APP_ADDRESS)); + (*(volatile uint32_t*)app_address)); /* Jump to application */ - (*(void(**)())(APP_ADDRESS + 4))(); + (*(void(**)())(app_address + 4))(); } } diff --git a/src/platforms/stm32/dfucore.c b/src/platforms/stm32/dfucore.c index a01616f..85e5e87 100644 --- a/src/platforms/stm32/dfucore.c +++ b/src/platforms/stm32/dfucore.c @@ -121,6 +121,14 @@ static const char *usb_strings[] = { DFU_IFACE_STRING, }; +static const char *usb_strings_upd[] = { + "Black Sphere Technologies", + BOARD_IDENT_UPD, + serial_no, + /* This string is used by ST Microelectronics' DfuSe utility */ + UPD_IFACE_STRING, +}; + static uint32_t get_le32(const void *vp) { const uint8_t *p = vp; @@ -158,8 +166,8 @@ usbdfu_getstatus_complete(usbd_device *dev, struct usb_setup_data *req) flash_unlock(); if(prog.blocknum == 0) { uint32_t addr = get_le32(prog.buf + 1); - if (addr < APP_ADDRESS || - (addr >= max_address)) { + if (addr < app_address || + (addr >= max_address)) { flash_lock(); usbd_ep_stall_set(dev, 0, 1); return; @@ -251,11 +259,12 @@ static int usbdfu_control_request(usbd_device *dev, return 0; } -void dfu_init(const usbd_driver *driver) +void dfu_init(const usbd_driver *driver, dfu_mode_t mode) { get_dev_unique_id(serial_no); - usbdev = usbd_init(driver, &dev, &config, usb_strings, 4, + usbdev = usbd_init(driver, &dev, &config, + (mode == DFU_MODE)?usb_strings:usb_strings_upd, 4, usbd_control_buffer, sizeof(usbd_control_buffer)); usbd_register_control_callback(usbdev, diff --git a/src/platforms/stm32/usbdfu.h b/src/platforms/stm32/usbdfu.h index d331ca4..e460082 100644 --- a/src/platforms/stm32/usbdfu.h +++ b/src/platforms/stm32/usbdfu.h @@ -19,25 +19,25 @@ #include -#ifdef STM32F4 -# define APP_ADDRESS 0x08010000 -#else -# define APP_ADDRESS 0x08002000 -#endif - /* Commands sent with wBlockNum == 0 as per ST implementation. */ #define CMD_SETADDR 0x21 #define CMD_ERASE 0x41 +extern uint32_t app_address; + +typedef enum { + DFU_MODE = 0, + UPD_MODE = 1 +} dfu_mode_t; /* dfucore.c - DFU core, common to libopencm3 platforms. */ -void dfu_init(const usbd_driver *driver); +void dfu_init(const usbd_driver *driver, dfu_mode_t mode); void dfu_main(void); /* Device specific functions */ void dfu_check_and_do_sector_erase(uint32_t sector); void dfu_flash_program_buffer(uint32_t baseaddr, void *buf, int len); uint32_t dfu_poll_timeout(uint8_t cmd, uint32_t addr, uint16_t blocknum); -void dfu_protect_enable(void); +void dfu_protect(dfu_mode_t mode); void dfu_jump_app_if_valid(void); /* Platform specific function */ diff --git a/src/platforms/swlink/platform.h b/src/platforms/swlink/platform.h index d0c9618..90acfb3 100644 --- a/src/platforms/swlink/platform.h +++ b/src/platforms/swlink/platform.h @@ -36,8 +36,10 @@ #define CDCACM_PACKET_SIZE 64 #define BOARD_IDENT "Black Magic Probe (SWLINK), (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" #define BOARD_IDENT_DFU "Black Magic (Upgrade), STM8S Discovery, (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" +#define BOARD_IDENT_UPD "Black Magic (DFU Upgrade), STM8S Discovery, (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" #define DFU_IDENT "Black Magic Firmware Upgrade (SWLINK)" #define DFU_IFACE_STRING "@Internal Flash /0x08000000/8*001Ka,56*001Kg" +#define UPD_IFACE_STRING "@Internal Flash /0x08000000/8*001Kg" extern usbd_device *usbdev; #define CDCACM_GDB_ENDPOINT 1 diff --git a/src/platforms/swlink/usbdfu.c b/src/platforms/swlink/usbdfu.c index 69cc1e2..de0b7ab 100644 --- a/src/platforms/swlink/usbdfu.c +++ b/src/platforms/swlink/usbdfu.c @@ -25,6 +25,8 @@ #include "usbdfu.h" +uint32_t app_address = 0x08002000; + void dfu_detach(void) { /* Disconnect USB cable by resetting USB Device @@ -58,7 +60,7 @@ int main(void) if(((GPIOA_CRL & 0x40) == 0x40) && pin_b) dfu_jump_app_if_valid(); - dfu_protect_enable(); + dfu_protect(DFU_MODE); rcc_clock_setup_in_hse_8mhz_out_72mhz(); systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); @@ -83,7 +85,7 @@ int main(void) systick_interrupt_enable(); systick_counter_enable(); - dfu_init(&stm32f103_usb_driver); + dfu_init(&stm32f103_usb_driver, DFU_MODE); dfu_main(); } -- cgit v1.2.3 From d27c50c6019d190c8bfc44d76ab5fee67b5164fa Mon Sep 17 00:00:00 2001 From: bon@elektron.ikp.physik.tu-darmstadt.de Date: Thu, 23 Jan 2014 15:51:13 +0100 Subject: Add STM32F03X and STM32F07X handling. --- src/stm32f1.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/stm32f1.c b/src/stm32f1.c index 670c5bd..d3cb234 100644 --- a/src/stm32f1.c +++ b/src/stm32f1.c @@ -58,7 +58,9 @@ static int stm32f1_flash_write(struct target_s *target, uint32_t dest, static const char stm32f1_driver_str[] = "STM32, Medium density."; static const char stm32hd_driver_str[] = "STM32, High density."; static const char stm32f3_driver_str[] = "STM32F3xx"; -static const char stm32f0_driver_str[] = "STM32F0xx"; +static const char stm32f03_driver_str[] = "STM32F03x"; +static const char stm32f05_driver_str[] = "STM32F05x"; +static const char stm32f07_driver_str[] = "STM32F07x"; static const char stm32f1_xml_memory_map[] = "" /* "idcode = adiv5_ap_mem_read(adiv5_target_ap(target), DBGMCU_IDCODE_F0) & 0xfff; switch(target->idcode) { - case 0x440: /* STM32F0 */ - target->driver = stm32f0_driver_str; + case 0x444: /* STM32F03 */ + case 0x440: /* STM32F05 */ + case 0x448: /* STM32F07 */ + switch(target->idcode) { + case 0x444: /* STM32F03 */ + target->driver = stm32f03_driver_str; + break; + case 0x440: /* STM32F05 */ + target->driver = stm32f05_driver_str; + break; + case 0x448: /* STM32F07 */ + target->driver = stm32f07_driver_str; + break; + } target->xml_mem_map = stm32f1_xml_memory_map; target->flash_erase = stm32md_flash_erase; target->flash_write = stm32f1_flash_write; -- cgit v1.2.3 From e5624a7e6dadb3433ff2c6b3004e2e9862bb1d55 Mon Sep 17 00:00:00 2001 From: Richard Eoin Meadows Date: Sun, 26 Jan 2014 23:54:23 +0000 Subject: Added support for the LPC1115FBD48/303 (ID determined experimentally) --- src/lpc11xx.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/lpc11xx.c b/src/lpc11xx.c index 670bba8..30db181 100644 --- a/src/lpc11xx.c +++ b/src/lpc11xx.c @@ -64,7 +64,7 @@ static const char lpc11xx_xml_memory_map[] = "" " PUBLIC \"+//IDN gnu.org//DTD GDB Memory Map V1.0//EN\"" " \"http://sourceware.org/gdb/gdb-memory-map.dtd\">"*/ "" - " " + " " " 0x1000" " " " " @@ -100,6 +100,7 @@ lpc11xx_probe(struct target_s *target) case 0x1440102B: /* lpc1114 */ case 0x0A40902B: case 0x1A40902B: + case 0x2058002B: /* lpc1115 */ case 0x1431102B: /* lpc11c22 */ case 0x1430102B: /* lpc11c24 */ target->driver = "lpc11xx"; -- cgit v1.2.3 From 690e99c6b269bb555d41d0f3f1bfeee0189b8156 Mon Sep 17 00:00:00 2001 From: Frantisek Burian Date: Thu, 13 Feb 2014 17:52:09 +0100 Subject: Fix the STK_CTRL to the STK_CSR library change. --- src/platforms/stlink/dfu_upgrade.c | 2 +- src/platforms/stlink/usbdfu.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/platforms/stlink/dfu_upgrade.c b/src/platforms/stlink/dfu_upgrade.c index 2c7c1ad..8d954ca 100644 --- a/src/platforms/stlink/dfu_upgrade.c +++ b/src/platforms/stlink/dfu_upgrade.c @@ -84,7 +84,7 @@ int main(void) stlink_set_rev(); - systick_set_clocksource(STK_CTRL_CLKSOURCE_AHB_DIV8); + systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); systick_set_reload(900000); dfu_protect(UPD_MODE); diff --git a/src/platforms/stlink/usbdfu.c b/src/platforms/stlink/usbdfu.c index 1a40e64..3c2b8be 100644 --- a/src/platforms/stlink/usbdfu.c +++ b/src/platforms/stlink/usbdfu.c @@ -38,7 +38,7 @@ static int stlink_test_nrst(void) uint16_t pin; uint32_t systick_value; - systick_set_clocksource(STK_CTRL_CLKSOURCE_AHB_DIV8); + systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); systick_set_reload(0xffffff); /* no underflow for about 16.7 seconds*/ systick_counter_enable(); /* systick ist now running with 1 MHz, systick counts down */ -- cgit v1.2.3 From 12aeaad441a251e91ecb48528c6446a7461b435a Mon Sep 17 00:00:00 2001 From: Frantisek Burian Date: Thu, 13 Feb 2014 18:21:16 +0100 Subject: [locm3] Use the new clock-enabling mechanisms in locm3. --- src/platforms/f4discovery/platform.h | 7 +++---- src/platforms/native/platform.c | 12 ++++++------ src/platforms/native/platform.h | 7 +++---- src/platforms/native/usbdfu.c | 6 +++--- src/platforms/stlink/dfu_upgrade.c | 18 ++++++++---------- src/platforms/stlink/platform.c | 21 ++++++++++----------- src/platforms/stlink/platform.h | 5 ++--- src/platforms/stlink/usbdfu.c | 20 +++++++++----------- src/platforms/stm32/usbuart.c | 2 +- src/platforms/swlink/platform.c | 19 +++++++++---------- src/platforms/swlink/platform.h | 7 +++---- src/platforms/swlink/usbdfu.c | 18 ++++++++---------- 12 files changed, 65 insertions(+), 77 deletions(-) (limited to 'src') diff --git a/src/platforms/f4discovery/platform.h b/src/platforms/f4discovery/platform.h index 5523b9c..a777ed2 100644 --- a/src/platforms/f4discovery/platform.h +++ b/src/platforms/f4discovery/platform.h @@ -118,15 +118,14 @@ extern usbd_device *usbdev; #define USBUSART USART3 #define USBUSART_CR1 USART3_CR1 #define USBUSART_IRQ NVIC_USART3_IRQ -#define USBUSART_APB_ENR RCC_APB1ENR -#define USBUSART_CLK_ENABLE RCC_APB1ENR_USART3EN +#define USBUSART_CLK RCC_USART3 #define USBUSART_TX_PORT GPIOD #define USBUSART_TX_PIN GPIO8 #define USBUSART_RX_PORT GPIOD #define USBUSART_RX_PIN GPIO9 #define USBUSART_ISR usart3_isr #define USBUSART_TIM TIM4 -#define USBUSART_TIM_CLK_EN() rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_TIM4EN) +#define USBUSART_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM4) #define USBUSART_TIM_IRQ NVIC_TIM4_IRQ #define USBUSART_TIM_ISR tim4_isr @@ -140,7 +139,7 @@ extern usbd_device *usbdev; } while(0) #define TRACE_TIM TIM3 -#define TRACE_TIM_CLK_EN() rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_TIM3EN) +#define TRACE_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM3) #define TRACE_IRQ NVIC_TIM3_IRQ #define TRACE_ISR tim3_isr diff --git a/src/platforms/native/platform.c b/src/platforms/native/platform.c index c0ce658..d6ca992 100644 --- a/src/platforms/native/platform.c +++ b/src/platforms/native/platform.c @@ -68,11 +68,11 @@ int platform_init(void) rcc_clock_setup_in_hse_8mhz_out_72mhz(); /* Enable peripherals */ - rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USBEN); - rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); - rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPBEN); - rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_AFIOEN); - rcc_peripheral_enable_clock(&RCC_AHBENR, RCC_AHBENR_CRCEN); + rcc_periph_clock_enable(RCC_USB); + rcc_periph_clock_enable(RCC_GPIOA); + rcc_periph_clock_enable(RCC_GPIOB); + rcc_periph_clock_enable(RCC_AFIO); + rcc_periph_clock_enable(RCC_CRC); /* Setup GPIO ports */ gpio_clear(USB_PU_PORT, USB_PU_PIN); @@ -248,7 +248,7 @@ static void morse_update(void) static void adc_init(void) { - rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_ADC1EN); + rcc_periph_clock_enable(RCC_ADC1); gpio_set_mode(GPIOB, GPIO_MODE_INPUT, GPIO_CNF_INPUT_ANALOG, GPIO0); diff --git a/src/platforms/native/platform.h b/src/platforms/native/platform.h index a1a28cf..2916e64 100644 --- a/src/platforms/native/platform.h +++ b/src/platforms/native/platform.h @@ -137,18 +137,17 @@ extern usbd_device *usbdev; #define USBUSART USART1 #define USBUSART_CR1 USART1_CR1 #define USBUSART_IRQ NVIC_USART1_IRQ -#define USBUSART_APB_ENR RCC_APB2ENR -#define USBUSART_CLK_ENABLE RCC_APB2ENR_USART1EN +#define USBUSART_CLK RCC_USART1 #define USBUSART_PORT GPIOA #define USBUSART_TX_PIN GPIO9 #define USBUSART_ISR usart1_isr #define USBUSART_TIM TIM4 -#define USBUSART_TIM_CLK_EN() rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_TIM4EN) +#define USBUSART_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM4) #define USBUSART_TIM_IRQ NVIC_TIM4_IRQ #define USBUSART_TIM_ISR tim4_isr #define TRACE_TIM TIM3 -#define TRACE_TIM_CLK_EN() rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_TIM3EN) +#define TRACE_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM3) #define TRACE_IRQ NVIC_TIM3_IRQ #define TRACE_ISR tim3_isr diff --git a/src/platforms/native/usbdfu.c b/src/platforms/native/usbdfu.c index e9094a3..3aac079 100644 --- a/src/platforms/native/usbdfu.c +++ b/src/platforms/native/usbdfu.c @@ -36,7 +36,7 @@ void dfu_detach(void) int main(void) { /* Check the force bootloader pin*/ - rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPBEN); + rcc_periph_clock_enable(RCC_GPIOB); if(gpio_get(GPIOB, GPIO12)) dfu_jump_app_if_valid(); @@ -46,8 +46,8 @@ int main(void) systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); systick_set_reload(900000); - rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); - rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USBEN); + rcc_periph_clock_enable(RCC_GPIOA); + rcc_periph_clock_enable(RCC_USB); gpio_set_mode(GPIOA, GPIO_MODE_INPUT, 0, GPIO8); systick_interrupt_enable(); diff --git a/src/platforms/stlink/dfu_upgrade.c b/src/platforms/stlink/dfu_upgrade.c index 8d954ca..b15117b 100644 --- a/src/platforms/stlink/dfu_upgrade.c +++ b/src/platforms/stlink/dfu_upgrade.c @@ -34,16 +34,15 @@ void dfu_detach(void) { /* Disconnect USB cable by resetting USB Device and pulling USB_DP low*/ - rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1ENR_USBEN); - rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1ENR_USBEN); - rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USBEN); - rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); + rcc_periph_reset_pulse(RST_USB); + rcc_periph_clock_enable(RCC_USB); + rcc_periph_clock_enable(RCC_GPIOA); gpio_clear(GPIOA, GPIO12); gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO12); /* Pull PB0 (T_NRST) low */ - rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPBEN); + rcc_periph_clock_enable(RCC_GPIOB); gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO0); gpio_clear(GPIOB, GPIO0); @@ -59,7 +58,7 @@ void stlink_set_rev(void) * 11 for ST-Link V1, e.g. on VL Discovery, tag as rev 0 * 10 for ST-Link V2, e.g. on F4 Discovery, tag as rev 1 */ - rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN); + rcc_periph_clock_enable(RCC_GPIOC); gpio_set_mode(GPIOC, GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, GPIO14 | GPIO13); gpio_set(GPIOC, GPIO14 | GPIO13); @@ -93,10 +92,9 @@ int main(void) /* Just in case: Disconnect USB cable by resetting USB Device * and pulling USB_DP low * Device will reconnect automatically as Pull-Up is hard wired*/ - rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1ENR_USBEN); - rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1ENR_USBEN); - rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USBEN); - rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); + rcc_periph_reset_pulse(RST_USB); + rcc_periph_clock_enable(RCC_USB); + rcc_periph_clock_enable(RCC_GPIOA); gpio_clear(GPIOA, GPIO12); gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO12); diff --git a/src/platforms/stlink/platform.c b/src/platforms/stlink/platform.c index d7ae41d..ec8c000 100644 --- a/src/platforms/stlink/platform.c +++ b/src/platforms/stlink/platform.c @@ -74,12 +74,12 @@ int platform_init(void) rcc_clock_setup_in_hse_8mhz_out_72mhz(); /* Enable peripherals */ - rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USBEN); - rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); - rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPBEN); - rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN); - rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_AFIOEN); - rcc_peripheral_enable_clock(&RCC_AHBENR, RCC_AHBENR_CRCEN); + rcc_periph_clock_enable(RCC_USB); + rcc_periph_clock_enable(RCC_GPIOA); + rcc_periph_clock_enable(RCC_GPIOB); + rcc_periph_clock_enable(RCC_GPIOC); + rcc_periph_clock_enable(RCC_AFIO); + rcc_periph_clock_enable(RCC_CRC); /* On Rev 1 unconditionally activate MCO on PORTA8 with HSE * platform_hwversion() also needed to initialize led_idle_run! @@ -167,10 +167,9 @@ const char *platform_target_voltage(void) void disconnect_usb(void) { /* Disconnect USB cable by resetting USB Device and pulling USB_DP low*/ - rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1ENR_USBEN); - rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1ENR_USBEN); - rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USBEN); - rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); + rcc_periph_reset_pulse(RST_USB); + rcc_periph_clock_enable(RCC_USB); + rcc_periph_clock_enable(RCC_GPIOA); gpio_clear(GPIOA, GPIO12); gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO12); @@ -179,7 +178,7 @@ void disconnect_usb(void) void assert_boot_pin(void) { uint32_t crl = GPIOA_CRL; - rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); + rcc_periph_clock_enable(RCC_GPIOA); /* Enable Pull on GPIOA1. We don't rely on the external pin * really pulled, but only on the value of the CNF register * changed from the reset value diff --git a/src/platforms/stlink/platform.h b/src/platforms/stlink/platform.h index ffe9fbf..6268a0e 100644 --- a/src/platforms/stlink/platform.h +++ b/src/platforms/stlink/platform.h @@ -123,13 +123,12 @@ extern usbd_device *usbdev; #define USBUSART USART2 #define USBUSART_CR1 USART2_CR1 #define USBUSART_IRQ NVIC_USART2_IRQ -#define USBUSART_APB_ENR RCC_APB1ENR -#define USBUSART_CLK_ENABLE RCC_APB1ENR_USART2EN +#define USBUSART_CLK RCC_USART2 #define USBUSART_PORT GPIOA #define USBUSART_TX_PIN GPIO2 #define USBUSART_ISR usart2_isr #define USBUSART_TIM TIM4 -#define USBUSART_TIM_CLK_EN() rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_TIM4EN) +#define USBUSART_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM4) #define USBUSART_TIM_IRQ NVIC_TIM4_IRQ #define USBUSART_TIM_ISR tim4_isr diff --git a/src/platforms/stlink/usbdfu.c b/src/platforms/stlink/usbdfu.c index 3c2b8be..843033b 100644 --- a/src/platforms/stlink/usbdfu.c +++ b/src/platforms/stlink/usbdfu.c @@ -47,7 +47,7 @@ static int stlink_test_nrst(void) * 11 for ST-Link V1, e.g. on VL Discovery, tag as rev 0 * 10 for ST-Link V2, e.g. on F4 Discovery, tag as rev 1 */ - rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPCEN); + rcc_periph_clock_enable(RCC_GPIOC); gpio_set_mode(GPIOC, GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, GPIO14 | GPIO13); gpio_set(GPIOC, GPIO14 | GPIO13); @@ -65,7 +65,7 @@ static int stlink_test_nrst(void) } gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, led_idle_run); - rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPBEN); + rcc_periph_clock_enable(RCC_GPIOB); gpio_set_mode(GPIOB, GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, pin); gpio_set(GPIOB, pin); @@ -80,10 +80,9 @@ void dfu_detach(void) { /* Disconnect USB cable by resetting USB Device and pulling USB_DP low*/ - rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1ENR_USBEN); - rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1ENR_USBEN); - rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USBEN); - rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); + rcc_periph_reset_pulse(RST_USB); + rcc_periph_clock_enable(RCC_USB); + rcc_periph_clock_enable(RCC_GPIOA); gpio_clear(GPIOA, GPIO12); gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO12); @@ -93,7 +92,7 @@ void dfu_detach(void) int main(void) { /* Check the force bootloader pin*/ - rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); + rcc_periph_clock_enable(RCC_GPIOA); /* Check value of GPIOA1 configuration. This pin is unconnected on * STLink V1 and V2. If we have a value other than the reset value (0x4), * we have a warm start and request Bootloader entry @@ -111,10 +110,9 @@ int main(void) /* Just in case: Disconnect USB cable by resetting USB Device * and pulling USB_DP low * Device will reconnect automatically as Pull-Up is hard wired*/ - rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1ENR_USBEN); - rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1ENR_USBEN); - rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USBEN); - rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); + rcc_periph_reset_pulse(RST_USB); + rcc_periph_clock_enable(RCC_USB); + rcc_periph_clock_enable(RCC_GPIOA); gpio_clear(GPIOA, GPIO12); gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO12); diff --git a/src/platforms/stm32/usbuart.c b/src/platforms/stm32/usbuart.c index 7f5ebde..95371dd 100644 --- a/src/platforms/stm32/usbuart.c +++ b/src/platforms/stm32/usbuart.c @@ -52,7 +52,7 @@ void usbuart_init(void) return; #endif - rcc_peripheral_enable_clock(&USBUSART_APB_ENR, USBUSART_CLK_ENABLE); + rcc_periph_clock_enable(USBUSART_CLK); UART_PIN_SETUP(); diff --git a/src/platforms/swlink/platform.c b/src/platforms/swlink/platform.c index ea88dcb..28db60f 100644 --- a/src/platforms/swlink/platform.c +++ b/src/platforms/swlink/platform.c @@ -47,11 +47,11 @@ int platform_init(void) rcc_clock_setup_in_hse_8mhz_out_72mhz(); /* Enable peripherals */ - rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USBEN); - rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); - rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPBEN); - rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_AFIOEN); - rcc_peripheral_enable_clock(&RCC_AHBENR, RCC_AHBENR_CRCEN); + rcc_periph_clock_enable(RCC_USB); + rcc_periph_clock_enable(RCC_GPIOA); + rcc_periph_clock_enable(RCC_GPIOB); + rcc_periph_clock_enable(RCC_AFIO); + rcc_periph_clock_enable(RCC_CRC); /* Unmap JTAG Pins so we can reuse as GPIO */ data = AFIO_MAPR; @@ -135,10 +135,9 @@ const char *platform_target_voltage(void) void disconnect_usb(void) { /* Disconnect USB cable by resetting USB Device and pulling USB_DP low*/ - rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1ENR_USBEN); - rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1ENR_USBEN); - rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USBEN); - rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); + rcc_periph_reset_pulse(RST_USB); + rcc_periph_clock_enable(RCC_USB); + rcc_periph_clock_enable(RCC_GPIOA); gpio_clear(GPIOA, GPIO12); gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO12); @@ -147,7 +146,7 @@ void disconnect_usb(void) void assert_boot_pin(void) { uint32_t crl = GPIOA_CRL; - rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); + rcc_periph_clock_enable(RCC_GPIOA); /* Enable Pull on GPIOA1. We don't rely on the external pin * really pulled, but only on the value of the CNF register * changed from the reset value diff --git a/src/platforms/swlink/platform.h b/src/platforms/swlink/platform.h index 90acfb3..dd2ac8a 100644 --- a/src/platforms/swlink/platform.h +++ b/src/platforms/swlink/platform.h @@ -115,18 +115,17 @@ extern usbd_device *usbdev; #define USBUSART USART1 #define USBUSART_CR1 USART1_CR1 #define USBUSART_IRQ NVIC_USART1_IRQ -#define USBUSART_APB_ENR RCC_APB2ENR -#define USBUSART_CLK_ENABLE RCC_APB2ENR_USART1EN +#define USBUSART_CLK RCC_USART1 #define USBUSART_PORT GPIOB #define USBUSART_TX_PIN GPIO6 #define USBUSART_ISR usart1_isr #define USBUSART_TIM TIM4 -#define USBUSART_TIM_CLK_EN() rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_TIM4EN) +#define USBUSART_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM4) #define USBUSART_TIM_IRQ NVIC_TIM4_IRQ #define USBUSART_TIM_ISR tim4_isr #define TRACE_TIM TIM2 -#define TRACE_TIM_CLK_EN() rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_TIM2EN) +#define TRACE_TIM_CLK_EN() rcc_periph_clock_enable(RCC_TIM2) #define TRACE_IRQ NVIC_TIM2_IRQ #define TRACE_ISR tim2_isr #define TRACE_IC_IN TIM_IC_IN_TI2 diff --git a/src/platforms/swlink/usbdfu.c b/src/platforms/swlink/usbdfu.c index de0b7ab..f87ccf4 100644 --- a/src/platforms/swlink/usbdfu.c +++ b/src/platforms/swlink/usbdfu.c @@ -31,10 +31,9 @@ void dfu_detach(void) { /* Disconnect USB cable by resetting USB Device and pulling USB_DP low*/ - rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1ENR_USBEN); - rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1ENR_USBEN); - rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USBEN); - rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); + rcc_periph_reset_pulse(RST_USB); + rcc_periph_clock_enable(RCC_USB); + rcc_periph_clock_enable(RCC_GPIOA); gpio_clear(GPIOA, GPIO12); gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO12); @@ -45,8 +44,8 @@ int main(void) { /* Check the force bootloader pin*/ uint16_t pin_b; - rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); - rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPBEN); + rcc_periph_clock_enable(RCC_GPIOA); + rcc_periph_clock_enable(RCC_GPIOB); /* Switch PB5 (SWIM_RST_IN) up */ gpio_set(GPIOB, GPIO5); gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_2_MHZ, @@ -70,10 +69,9 @@ int main(void) /* Just in case: Disconnect USB cable by resetting USB Device * and pulling USB_DP low * Device will reconnect automatically as Pull-Up is hard wired*/ - rcc_peripheral_reset(&RCC_APB1RSTR, RCC_APB1ENR_USBEN); - rcc_peripheral_clear_reset(&RCC_APB1RSTR, RCC_APB1ENR_USBEN); - rcc_peripheral_enable_clock(&RCC_APB1ENR, RCC_APB1ENR_USBEN); - rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPAEN); + rcc_periph_reset_pulse(RST_USB); + rcc_periph_clock_enable(RCC_USB); + rcc_periph_clock_enable(RCC_GPIOA); gpio_clear(GPIOA, GPIO12); gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO12); -- cgit v1.2.3 From cbb85b6a4523cb62e17a5cf83c0b2950acfd93fe Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sat, 8 Mar 2014 18:58:39 +1300 Subject: LPC812 support --- src/lpc11xx.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 53 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/lpc11xx.c b/src/lpc11xx.c index 30db181..d03e726 100644 --- a/src/lpc11xx.c +++ b/src/lpc11xx.c @@ -22,14 +22,14 @@ struct flash_program { static struct flash_program flash_pgm; -#define MSP 17 // Main stack pointer register number -#define MIN_RAM_SIZE_FOR_LPC1xxx 2048 -#define RAM_USAGE_FOR_IAP_ROUTINES 32 // IAP routines use 32 bytes at top of ram +#define MSP 17 /* Main stack pointer register number */ +#define MIN_RAM_SIZE_FOR_LPC8xx 1024 +#define MIN_RAM_SIZE_FOR_LPC1xxx 2048 +#define RAM_USAGE_FOR_IAP_ROUTINES 32 /* IAP routines use 32 bytes at top of ram */ #define IAP_ENTRYPOINT 0x1fff1ff1 #define IAP_RAM_BASE 0x10000000 - #define IAP_CMD_PREPARE 50 #define IAP_CMD_PROGRAM 51 #define IAP_CMD_ERASE 52 @@ -48,6 +48,8 @@ static struct flash_program flash_pgm; #define IAP_STATUS_COMPARE_ERROR 10 #define IAP_STATUS_BUSY 11 +static const char lpc8xx_driver[] = "lpc8xx"; +static const char lpc11xx_driver[] = "lpc11xx"; static void lpc11x_iap_call(struct target_s *target, struct flash_param *param, unsigned param_len); static int lpc11xx_flash_prepare(struct target_s *target, uint32_t addr, int len); static int lpc11xx_flash_erase(struct target_s *target, uint32_t addr, int len); @@ -70,6 +72,24 @@ static const char lpc11xx_xml_memory_map[] = "" " " ""; +/* + * Memory map for the lpc8xx devices, which otherwise look much like the lpc11xx. + * + * We could decode the RAM/flash sizes, but we just encode the largest possible here. + * + * Note that the LPC810 and LPC811 map their flash oddly; see the NXP LPC800 user + * manual (UM10601) for more details. + */ +static const char lpc8xx_xml_memory_map[] = "" +/* ""*/ + "" + " " + " 0x400" + " " + " " + ""; bool lpc11xx_probe(struct target_s *target) @@ -103,11 +123,19 @@ lpc11xx_probe(struct target_s *target) case 0x2058002B: /* lpc1115 */ case 0x1431102B: /* lpc11c22 */ case 0x1430102B: /* lpc11c24 */ - target->driver = "lpc11xx"; + target->driver = lpc11xx_driver; target->xml_mem_map = lpc11xx_xml_memory_map; target->flash_erase = lpc11xx_flash_erase; target->flash_write = lpc11xx_flash_write; + return true; + + case 0x1812202b: /* LPC812M101FDH20 */ + target->driver = lpc8xx_driver; + target->xml_mem_map = lpc8xx_xml_memory_map; + target->flash_erase = lpc11xx_flash_erase; + target->flash_write = lpc11xx_flash_write; + return true; } @@ -129,7 +157,11 @@ lpc11x_iap_call(struct target_s *target, struct flash_param *param, unsigned par regs[0] = IAP_RAM_BASE + offsetof(struct flash_param, command); regs[1] = IAP_RAM_BASE + offsetof(struct flash_param, result); - regs[MSP] = IAP_RAM_BASE + MIN_RAM_SIZE_FOR_LPC1xxx - RAM_USAGE_FOR_IAP_ROUTINES;// stack pointer - top of the smallest ram less 32 for IAP usage + // stack pointer - top of the smallest ram less 32 for IAP usage + if (target->driver == lpc8xx_driver) + regs[MSP] = IAP_RAM_BASE + MIN_RAM_SIZE_FOR_LPC8xx - RAM_USAGE_FOR_IAP_ROUTINES; + else + regs[MSP] = IAP_RAM_BASE + MIN_RAM_SIZE_FOR_LPC1xxx - RAM_USAGE_FOR_IAP_ROUTINES; regs[14] = IAP_RAM_BASE | 1; regs[15] = IAP_ENTRYPOINT; target_regs_write(target, regs); @@ -142,14 +174,22 @@ lpc11x_iap_call(struct target_s *target, struct flash_param *param, unsigned par target_mem_read_words(target, (void *)param, IAP_RAM_BASE, sizeof(struct flash_param)); } +static int flash_page_size(struct target_s *target) +{ + if (target->driver == lpc8xx_driver) + return 1024; + else + return 4096; +} + static int lpc11xx_flash_prepare(struct target_s *target, uint32_t addr, int len) { /* prepare the sector(s) to be erased */ memset(&flash_pgm.p, 0, sizeof(flash_pgm.p)); flash_pgm.p.command[0] = IAP_CMD_PREPARE; - flash_pgm.p.command[1] = addr / 4096; - flash_pgm.p.command[2] = (addr + len - 1) / 4096; + flash_pgm.p.command[1] = addr / flash_page_size(target); + flash_pgm.p.command[2] = (addr + len - 1) / flash_page_size(target); lpc11x_iap_call(target, &flash_pgm.p, sizeof(flash_pgm.p)); if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { @@ -163,7 +203,7 @@ static int lpc11xx_flash_erase(struct target_s *target, uint32_t addr, int len) { - if (addr % 4096) + if (addr % flash_page_size(target)) return -1; /* prepare... */ @@ -172,8 +212,8 @@ lpc11xx_flash_erase(struct target_s *target, uint32_t addr, int len) /* and now erase them */ flash_pgm.p.command[0] = IAP_CMD_ERASE; - flash_pgm.p.command[1] = addr / 4096; - flash_pgm.p.command[2] = (addr + len - 1) / 4096; + flash_pgm.p.command[1] = addr / flash_page_size(target); + flash_pgm.p.command[2] = (addr + len - 1) / flash_page_size(target); flash_pgm.p.command[3] = 12000; /* XXX safe to assume this? */ lpc11x_iap_call(target, &flash_pgm.p, sizeof(flash_pgm.p)); if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { @@ -217,7 +257,7 @@ lpc11xx_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, chunk_offset = 0; /* if we are programming the vectors, calculate the magic number */ - if (chunk * IAP_PGM_CHUNKSIZE == 0) { + if (chunk == 0) { uint32_t *w = (uint32_t *)(&flash_pgm.data[0]); uint32_t sum = 0; @@ -248,6 +288,7 @@ lpc11xx_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, flash_pgm.p.command[1] = chunk * IAP_PGM_CHUNKSIZE; flash_pgm.p.command[2] = IAP_RAM_BASE + offsetof(struct flash_program, data); flash_pgm.p.command[3] = IAP_PGM_CHUNKSIZE; + /* assuming we are running off IRC - safe lower bound */ flash_pgm.p.command[4] = 12000; /* XXX safe to presume this? */ lpc11x_iap_call(target, &flash_pgm.p, sizeof(flash_pgm)); if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { -- cgit v1.2.3 From 096e1b32c6e9572bcd776699c8093f1d65ebc7ce Mon Sep 17 00:00:00 2001 From: Jared Boone Date: Mon, 3 Mar 2014 09:56:08 -0800 Subject: Add support for LPC11U14 (tested) and related U-series microcontrollers (untested). --- src/lpc11xx.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/lpc11xx.c b/src/lpc11xx.c index 30db181..1e9b84d 100644 --- a/src/lpc11xx.c +++ b/src/lpc11xx.c @@ -64,7 +64,7 @@ static const char lpc11xx_xml_memory_map[] = "" " PUBLIC \"+//IDN gnu.org//DTD GDB Memory Map V1.0//EN\"" " \"http://sourceware.org/gdb/gdb-memory-map.dtd\">"*/ "" - " " + " " " 0x1000" " " " " @@ -103,6 +103,15 @@ lpc11xx_probe(struct target_s *target) case 0x2058002B: /* lpc1115 */ case 0x1431102B: /* lpc11c22 */ case 0x1430102B: /* lpc11c24 */ + case 0x095C802B: /* lpc11u12x/201 */ + case 0x295C802B: + case 0x097A802B: /* lpc11u13/201 */ + case 0x297A802B: + case 0x0998802B: /* lpc11u14x/201 */ + case 0x2998802B: + case 0x2972402B: /* lpc11u23/301 */ + case 0x2988402B: /* lpc11u24x/301 */ + case 0x2980002B: /* lpc11u24x/401 */ target->driver = "lpc11xx"; target->xml_mem_map = lpc11xx_xml_memory_map; target->flash_erase = lpc11xx_flash_erase; -- cgit v1.2.3 From 307747262001d61edba984caafa630b258374fed Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Mon, 31 Mar 2014 20:58:06 +1300 Subject: Unwind hardfaults in dual-stack mode. --- src/cortexm.c | 32 ++++++++++++++++++++++++++------ 1 file changed, 26 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/cortexm.c b/src/cortexm.c index 1fc5978..819dacd 100644 --- a/src/cortexm.c +++ b/src/cortexm.c @@ -323,6 +323,14 @@ static const char tdesc_cortex_mf[] = " " ""; +#define REG_SP 13 +#define REG_LR 14 +#define REG_PC 15 +#define REG_XPSR 16 +#define REG_MSP 17 +#define REG_PSP 18 +#define REG_SPECIAL 19 + bool cortexm_probe(struct target_s *target) { @@ -677,17 +685,29 @@ static int cortexm_fault_unwind(struct target_s *target) /* Read registers for post-exception stack pointer */ target_regs_read(target, regs); /* save retcode currently in lr */ - retcode = regs[14]; + retcode = regs[REG_LR]; + bool spsel = retcode & (1<<2); + bool fpca = !(retcode & (1<<4)); /* Read stack for pre-exception registers */ - target_mem_read_words(target, stack, regs[13], sizeof(stack)); - regs[14] = stack[5]; /* restore LR to pre-exception state */ - regs[15] = stack[6]; /* restore PC to pre-exception state */ + uint32_t sp = spsel ? regs[REG_PSP] : regs[REG_MSP]; + target_mem_read_words(target, stack, sp, sizeof(stack)); + regs[REG_LR] = stack[5]; /* restore LR to pre-exception state */ + regs[REG_PC] = stack[6]; /* restore PC to pre-exception state */ /* adjust stack to pop exception state */ - framesize = (retcode & (1<<4)) ? 0x68 : 0x20; /* check for basic vs. extended frame */ + framesize = fpca ? 0x68 : 0x20; /* check for basic vs. extended frame */ if (stack[7] & (1<<9)) /* check for stack alignment fixup */ framesize += 4; - regs[13] += framesize; + + if (spsel) { + regs[REG_SPECIAL] |= 0x4000000; + regs[REG_SP] = regs[REG_PSP] += framesize; + } else { + regs[REG_SP] = regs[REG_MSP] += framesize; + } + + if (fpca) + regs[REG_SPECIAL] |= 0x2000000; /* FIXME: stack[7] contains xPSR when this is supported */ /* although, if we caught the exception it will be unchanged */ -- cgit v1.2.3 From 34d0f64529a77c0375af8c9429b5571e7cedcb0b Mon Sep 17 00:00:00 2001 From: Mike Date: Fri, 25 Apr 2014 22:34:58 +0100 Subject: Nordic nRF51 series support --- flashstub/nrf51.s | 40 +++++++++ src/Makefile | 1 + src/cortexm.c | 1 + src/include/target.h | 1 + src/nrf51.c | 244 +++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 287 insertions(+) create mode 100644 flashstub/nrf51.s create mode 100644 src/nrf51.c (limited to 'src') diff --git a/flashstub/nrf51.s b/flashstub/nrf51.s new file mode 100644 index 0000000..e23b613 --- /dev/null +++ b/flashstub/nrf51.s @@ -0,0 +1,40 @@ +.global _start + +_start: + ldr r0, _ready + ldr r1, _addr + mov r2, pc + add r2, #(_data - . - 2) + ldr r3, _size +_next: + cmp r3, #0 + beq _done + @ Write data to flash + ldr r4, [r2] + str r4, [r1] + +_wait: @ Wait for READY bit + ldr r4, [r0] + mov r6, #1 + tst r4, r6 + beq _wait + + sub r3, #4 + add r1, #4 + add r2, #4 + b _next +_done: + bkpt + +@.align 4 +.org 0x24 +_ready: + .word 0x4001E400 +_addr: + .word 0 +_size: + .word 12 +_data: + .word 0xAAAAAAAA + .word 0xBBBBBBBB + .word 0xCCCCCCCC diff --git a/src/Makefile b/src/Makefile index d8d8b00..85b0337 100644 --- a/src/Makefile +++ b/src/Makefile @@ -28,6 +28,7 @@ SRC = \ lpc11xx.c \ lpc43xx.c \ main.c \ + nrf51.c \ platform.c \ sam3x.c \ stm32f1.c \ diff --git a/src/cortexm.c b/src/cortexm.c index 819dacd..8a9beb8 100644 --- a/src/cortexm.c +++ b/src/cortexm.c @@ -383,6 +383,7 @@ cortexm_probe(struct target_s *target) PROBE(lpc11xx_probe); PROBE(lpc43xx_probe); PROBE(sam3x_probe); + PROBE(nrf51_probe); PROBE(lmi_probe); #undef PROBE diff --git a/src/include/target.h b/src/include/target.h index 574a0eb..03230a5 100644 --- a/src/include/target.h +++ b/src/include/target.h @@ -212,6 +212,7 @@ bool lmi_probe(struct target_s *target); bool lpc11xx_probe(struct target_s *target); bool lpc43xx_probe(struct target_s *target); bool sam3x_probe(struct target_s *target); +bool nrf51_probe(struct target_s *target); #endif diff --git a/src/nrf51.c b/src/nrf51.c new file mode 100644 index 0000000..7a9d136 --- /dev/null +++ b/src/nrf51.c @@ -0,0 +1,244 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2014 Mike Walters + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * 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, see . + */ + +/* This file implements nRF51 target specific functions for detecting + * the device, providing the XML memory map and Flash memory programming. + */ + +#include +#include + +#include "general.h" +#include "adiv5.h" +#include "target.h" +#include "command.h" +#include "gdb_packet.h" + +static int nrf51_flash_erase(struct target_s *target, uint32_t addr, int len); +static int nrf51_flash_write(struct target_s *target, uint32_t dest, + const uint8_t *src, int len); + +static bool nrf51_cmd_erase_all(target *t); + +const struct command_s nrf51_cmd_list[] = { + {"erase_mass", (cmd_handler)nrf51_cmd_erase_all, "Erase entire flash memory"}, + {NULL, NULL, NULL} +}; + +static const char nrf51_xml_memory_map[] = "" +/* ""*/ + "" + " " + " 0x400" + " " + " " + ""; + +/* Non-Volatile Memory Controller (NVMC) Registers */ +#define NRF51_NVMC 0x4001E000 +#define NRF51_NVMC_READY (NRF51_NVMC + 0x400) +#define NRF51_NVMC_CONFIG (NRF51_NVMC + 0x504) +#define NRF51_NVMC_ERASEPAGE (NRF51_NVMC + 0x508) +#define NRF51_NVMC_ERASEALL (NRF51_NVMC + 0x50C) +#define NRF51_NVMC_ERASEUICR (NRF51_NVMC + 0x514) + +#define NRF51_NVMC_CONFIG_REN 0x0 // Read only access +#define NRF51_NVMC_CONFIG_WEN 0x1 // Write enable +#define NRF51_NVMC_CONFIG_EEN 0x2 // Erase enable + +/* Factory Information Configuration Registers (FICR) */ +#define NRF51_FICR 0x10000000 +#define NRF51_FICR_CODEPAGESIZE (NRF51_FICR + 0x010) +#define NRF51_FICR_CODESIZE (NRF51_FICR + 0x014) +#define NRF51_FICR_CONFIGID (NRF51_FICR + 0x05C) + +#define NRF51_PAGE_SIZE 1024 + +uint16_t nrf51_flash_write_stub[] = { +// _start: + 0x4808, // ldr r0, [pc, #32] ; (24 <_ready>) + 0x4909, // ldr r1, [pc, #36] ; (28 <_addr>) + 0x467a, // mov r2, pc + 0x3228, // adds r2, #40 ; 0x28 + 0x4b08, // ldr r3, [pc, #32] ; (2c <_size>) + +// next: + 0x2b00, // cmp r3, #0 + 0xd009, // beq.n 22 <_done> + 0x6814, // ldr r4, [r2, #0] + 0x600c, // str r4, [r1, #0] + +// wait: + 0x6804, // ldr r4, [r0, #0] + 0x2601, // movs r6, #1 + 0x4234, // tst r4, r6 + 0xd0fb, // beq.n 12 <_wait> + + 0x3b04, // subs r3, #4 + 0x3104, // adds r1, #4 + 0x3204, // adds r2, #4 + 0xe7f3, // b.n a <_next> + +// done: + 0xbe00, // bkpt 0x0000 + +// ready: + 0xe400, 0x4001 // .word 0x4001e400 +// addr: +// 0x0000, 0x0000 +// size: +// 0x0000, 0x0000 +// data: +// ... + +}; + +bool nrf51_probe(struct target_s *target) +{ + ADIv5_AP_t *ap = adiv5_target_ap(target); + + target->idcode = adiv5_ap_mem_read(ap, NRF51_FICR_CONFIGID) & 0xFFFF; + + switch (target->idcode) { + case 0x001D: + case 0x002A: + case 0x0044: + case 0x003C: + case 0x0020: + case 0x002F: + case 0x0040: + case 0x0047: + case 0x004D: + case 0x0026: + case 0x004C: + target->driver = "Nordic nRF51"; + target->xml_mem_map = nrf51_xml_memory_map; + target->flash_erase = nrf51_flash_erase; + target->flash_write = nrf51_flash_write; + target_add_commands(target, nrf51_cmd_list, "nRF51"); + return true; + } + + return false; +} + +static int nrf51_flash_erase(struct target_s *target, uint32_t addr, int len) +{ + + ADIv5_AP_t *ap = adiv5_target_ap(target); + + addr &= ~(NRF51_PAGE_SIZE - 1); + len &= ~(NRF51_PAGE_SIZE - 1); + + /* Enable erase */ + adiv5_ap_mem_write(ap, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_EEN); + + /* Poll for NVMC_READY */ + while(adiv5_ap_mem_read(ap, NRF51_NVMC_READY) == 0) + if(target_check_error(target)) + return -1; + + while (len) { + /* Write address of first word in page to erase it */ + adiv5_ap_mem_write(ap, NRF51_NVMC_ERASEPAGE, addr); + + /* Poll for NVMC_READY */ + while(adiv5_ap_mem_read(ap, NRF51_NVMC_READY) == 0) + if(target_check_error(target)) + return -1; + + addr += NRF51_PAGE_SIZE; + len -= NRF51_PAGE_SIZE; + } + + /* Return to read-only */ + adiv5_ap_mem_write(ap, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_REN); + + /* Poll for NVMC_READY */ + while(adiv5_ap_mem_read(ap, NRF51_NVMC_READY) == 0) + if(target_check_error(target)) + return -1; + + return 0; +} + +static int nrf51_flash_write(struct target_s *target, uint32_t dest, + const uint8_t *src, int len) +{ + ADIv5_AP_t *ap = adiv5_target_ap(target); + uint32_t offset = dest % 4; + uint32_t words = (offset + len + 3) / 4; + uint32_t data[2 + words]; + + /* Construct data buffer used by stub */ + data[0] = dest - offset; + data[1] = words * 4; /* length must always be a multiple of 4 */ + data[2] = 0xFFFFFFFF; /* pad partial words with all 1s to avoid */ + data[words + 1] = 0xFFFFFFFF; /* damaging overlapping areas */ + memcpy((uint8_t *)&data[2] + offset, src, len); + + /* Enable write */ + adiv5_ap_mem_write(ap, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_WEN); + + /* Poll for NVMC_READY */ + while(adiv5_ap_mem_read(ap, NRF51_NVMC_READY) == 0) + if(target_check_error(target)) + return -1; + + /* Write stub and data to target ram and set PC */ + target_mem_write_words(target, 0x20000000, (void*)nrf51_flash_write_stub, 0x28); + target_mem_write_words(target, 0x20000028, data, len + 8); + target_pc_write(target, 0x20000000); + if(target_check_error(target)) + return -1; + + /* Execute the stub */ + target_halt_resume(target, 0); + while(!target_halt_wait(target)); + + /* Return to read-only */ + adiv5_ap_mem_write(ap, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_REN); + + return 0; +} + +static bool nrf51_cmd_erase_all(target *t) +{ + ADIv5_AP_t *ap = adiv5_target_ap(t); + + /* Enable erase */ + adiv5_ap_mem_write(ap, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_EEN); + + /* Poll for NVMC_READY */ + while(adiv5_ap_mem_read(ap, NRF51_NVMC_READY) == 0) + if(target_check_error(t)) + return false; + + /* Erase all */ + adiv5_ap_mem_write(ap, NRF51_NVMC_ERASEALL, 1); + + /* Poll for NVMC_READY */ + while(adiv5_ap_mem_read(ap, NRF51_NVMC_READY) == 0) + if(target_check_error(t)) + return false; + + return true; +} \ No newline at end of file -- cgit v1.2.3 From 72ae78a185d08d9979748dcef3d0cd29deddde9b Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Thu, 8 May 2014 11:02:35 -0700 Subject: Updated libopencm3. Fixes broken bootloader, issue #43. --- libopencm3 | 2 +- src/platforms/f4discovery/platform.c | 2 +- src/platforms/f4discovery/platform.h | 3 +++ src/platforms/native/platform.c | 3 ++- src/platforms/native/platform.h | 4 ++++ src/platforms/stlink/platform.c | 2 +- src/platforms/stlink/platform.h | 4 ++++ src/platforms/stm32/dfu_f1.c | 1 + src/platforms/stm32/dfu_f4.c | 2 ++ src/platforms/swlink/platform.c | 2 +- src/platforms/swlink/platform.h | 4 ++++ 11 files changed, 24 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/libopencm3 b/libopencm3 index a909b5c..67242de 160000 --- a/libopencm3 +++ b/libopencm3 @@ -1 +1 @@ -Subproject commit a909b5ca9e18f802e3caef19e63d38861662c128 +Subproject commit 67242de60dec0227739cd549e8a78e1a3c15dbf5 diff --git a/src/platforms/f4discovery/platform.c b/src/platforms/f4discovery/platform.c index 2786954..5b073e9 100644 --- a/src/platforms/f4discovery/platform.c +++ b/src/platforms/f4discovery/platform.c @@ -22,6 +22,7 @@ * implementation. */ +#include "platform.h" #include #include #include @@ -31,7 +32,6 @@ #include #include -#include "platform.h" #include "jtag_scan.h" #include diff --git a/src/platforms/f4discovery/platform.h b/src/platforms/f4discovery/platform.h index a777ed2..bbf01e1 100644 --- a/src/platforms/f4discovery/platform.h +++ b/src/platforms/f4discovery/platform.h @@ -24,6 +24,9 @@ #ifndef __PLATFORM_H #define __PLATFORM_H +#include +#include +#include #include #include diff --git a/src/platforms/native/platform.c b/src/platforms/native/platform.c index d6ca992..cb9e69e 100644 --- a/src/platforms/native/platform.c +++ b/src/platforms/native/platform.c @@ -22,6 +22,8 @@ * implementation. */ +#include "platform.h" + #include #include #include @@ -31,7 +33,6 @@ #include #include -#include "platform.h" #include "jtag_scan.h" #include diff --git a/src/platforms/native/platform.h b/src/platforms/native/platform.h index 2916e64..082f6ef 100644 --- a/src/platforms/native/platform.h +++ b/src/platforms/native/platform.h @@ -24,6 +24,10 @@ #ifndef __PLATFORM_H #define __PLATFORM_H +#include +#include +#include + #include #include diff --git a/src/platforms/stlink/platform.c b/src/platforms/stlink/platform.c index ec8c000..1369c37 100644 --- a/src/platforms/stlink/platform.c +++ b/src/platforms/stlink/platform.c @@ -22,6 +22,7 @@ * implementation. */ +#include "platform.h" #include #include #include @@ -30,7 +31,6 @@ #include #include -#include "platform.h" #include "jtag_scan.h" #include diff --git a/src/platforms/stlink/platform.h b/src/platforms/stlink/platform.h index 6268a0e..0780706 100644 --- a/src/platforms/stlink/platform.h +++ b/src/platforms/stlink/platform.h @@ -24,6 +24,10 @@ #ifndef __PLATFORM_H #define __PLATFORM_H +#include +#include +#include + #include #include diff --git a/src/platforms/stm32/dfu_f1.c b/src/platforms/stm32/dfu_f1.c index 77b6f58..bb1e274 100644 --- a/src/platforms/stm32/dfu_f1.c +++ b/src/platforms/stm32/dfu_f1.c @@ -17,6 +17,7 @@ * along with this program. If not, see . */ +#include "platform.h" #include #include diff --git a/src/platforms/stm32/dfu_f4.c b/src/platforms/stm32/dfu_f4.c index 1421b19..3d1e369 100644 --- a/src/platforms/stm32/dfu_f4.c +++ b/src/platforms/stm32/dfu_f4.c @@ -17,6 +17,8 @@ * along with this program. If not, see . */ +#include "platform.h" + #if defined(STM32F2) # include #elif defined(STM32F4) diff --git a/src/platforms/swlink/platform.c b/src/platforms/swlink/platform.c index 28db60f..0f5695d 100644 --- a/src/platforms/swlink/platform.c +++ b/src/platforms/swlink/platform.c @@ -22,6 +22,7 @@ * implementation. */ +#include "platform.h" #include #include #include @@ -30,7 +31,6 @@ #include #include -#include "platform.h" #include "jtag_scan.h" #include diff --git a/src/platforms/swlink/platform.h b/src/platforms/swlink/platform.h index dd2ac8a..fe3dc46 100644 --- a/src/platforms/swlink/platform.h +++ b/src/platforms/swlink/platform.h @@ -24,6 +24,10 @@ #ifndef __PLATFORM_H #define __PLATFORM_H +#include +#include +#include + #include #include -- cgit v1.2.3 From 63bce97cbd521fd464c2e11bfbb034edf602f68c Mon Sep 17 00:00:00 2001 From: Richard Eoin Meadows Date: Mon, 26 May 2014 13:25:53 +0100 Subject: PLATFORM_FATAL_ERRORs are now caught even when they happen in the initial JTAG scan that occours during platform_init. Previously any fatal errors that occoured during this scan caused a hardfault. --- src/platforms/f4discovery/platform.c | 5 +++++ src/platforms/native/platform.c | 5 +++++ src/platforms/stlink/platform.c | 5 +++++ src/platforms/swlink/platform.c | 5 +++++ 4 files changed, 20 insertions(+) (limited to 'src') diff --git a/src/platforms/f4discovery/platform.c b/src/platforms/f4discovery/platform.c index 5b073e9..efe8050 100644 --- a/src/platforms/f4discovery/platform.c +++ b/src/platforms/f4discovery/platform.c @@ -92,6 +92,11 @@ int platform_init(void) cdcacm_init(); + // Set recovery point + if (setjmp(fatal_error_jmpbuf)) { + return 0; // Do nothing on failure + } + jtag_scan(NULL); return 0; diff --git a/src/platforms/native/platform.c b/src/platforms/native/platform.c index cb9e69e..81a54d8 100644 --- a/src/platforms/native/platform.c +++ b/src/platforms/native/platform.c @@ -140,6 +140,11 @@ int platform_init(void) cdcacm_init(); usbuart_init(); + // Set recovery point + if (setjmp(fatal_error_jmpbuf)) { + return 0; // Do nothing on failure + } + jtag_scan(NULL); return 0; diff --git a/src/platforms/stlink/platform.c b/src/platforms/stlink/platform.c index 1369c37..cf2d954 100644 --- a/src/platforms/stlink/platform.c +++ b/src/platforms/stlink/platform.c @@ -121,6 +121,11 @@ int platform_init(void) cdcacm_init(); + // Set recovery point + if (setjmp(fatal_error_jmpbuf)) { + return 0; // Do nothing on failure + } + jtag_scan(NULL); return 0; diff --git a/src/platforms/swlink/platform.c b/src/platforms/swlink/platform.c index 0f5695d..74f8691 100644 --- a/src/platforms/swlink/platform.c +++ b/src/platforms/swlink/platform.c @@ -99,6 +99,11 @@ int platform_init(void) cdcacm_init(); + // Set recovery point + if (setjmp(fatal_error_jmpbuf)) { + return 0; // Do nothing on failure + } + jtag_scan(NULL); return 0; -- cgit v1.2.3 From c9089f58514b59cfc43e27796eb258cbabb2112b Mon Sep 17 00:00:00 2001 From: Richard Eoin Meadows Date: Fri, 11 Apr 2014 18:35:55 +0100 Subject: Added monitor option to toggle target power --- src/command.c | 12 ++++++++++++ src/platforms/native/platform.c | 8 +++++++- src/platforms/native/platform.h | 2 ++ 3 files changed, 21 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/command.c b/src/command.c index 8378576..0c97949 100644 --- a/src/command.c +++ b/src/command.c @@ -47,6 +47,7 @@ static bool cmd_swdp_scan(void); static bool cmd_targets(target *t); static bool cmd_morse(void); static bool cmd_connect_srst(target *t, int argc, const char **argv); +static bool cmd_target_power(target *t, int argc, const char **argv); #ifdef PLATFORM_HAS_TRACESWO static bool cmd_traceswo(void); #endif @@ -59,6 +60,7 @@ const struct command_s cmd_list[] = { {"targets", (cmd_handler)cmd_targets, "Display list of available targets" }, {"morse", (cmd_handler)cmd_morse, "Display morse error message" }, {"connect_srst", (cmd_handler)cmd_connect_srst, "Configure connect under SRST: (enable|disable)" }, + {"tpwr", (cmd_handler)cmd_target_power, "Supplies power to the target: (enable|disable)"}, #ifdef PLATFORM_HAS_TRACESWO {"traceswo", (cmd_handler)cmd_traceswo, "Start trace capture" }, #endif @@ -221,6 +223,16 @@ static bool cmd_connect_srst(target *t, int argc, const char **argv) connect_assert_srst = !strcmp(argv[1], "enable"); return true; } +static bool cmd_target_power(target *t, int argc, const char **argv) +{ + (void)t; + if (argc == 1) + gdb_outf("Target Power: %s\n", + !platform_target_get_power() ? "enabled" : "disabled"); + else + platform_target_set_power(!strncmp(argv[1], "enable", strlen(argv[1]))); + return true; +} #ifdef PLATFORM_HAS_TRACESWO static bool cmd_traceswo(void) diff --git a/src/platforms/native/platform.c b/src/platforms/native/platform.c index cb9e69e..224daf8 100644 --- a/src/platforms/native/platform.c +++ b/src/platforms/native/platform.c @@ -153,7 +153,13 @@ void platform_srst_set_val(bool assert) gpio_set_val(SRST_PORT, SRST_PIN, !assert); } } - +bool platform_target_get_power(void) { + return gpio_get(PWR_BR_PORT, PWR_BR_PIN); +} +void platform_target_set_power(bool power) +{ + gpio_set_val(PWR_BR_PORT, PWR_BR_PIN, !power); +} void platform_delay(uint32_t delay) { timeout_counter = delay; diff --git a/src/platforms/native/platform.h b/src/platforms/native/platform.h index 082f6ef..5ca0408 100644 --- a/src/platforms/native/platform.h +++ b/src/platforms/native/platform.h @@ -231,3 +231,5 @@ static inline uint16_t _gpio_get(uint32_t gpioport, uint16_t gpios) void assert_boot_pin(void); void setup_vbus_irq(void); void platform_srst_set_val(bool assert); +bool platform_target_get_power(void); +void platform_target_set_power(bool power); -- cgit v1.2.3 From 42e41edfa1d7e1f5aa5e4b131d3af846ad71f0ff Mon Sep 17 00:00:00 2001 From: Richard Eoin Meadows Date: Wed, 28 May 2014 12:33:43 +0100 Subject: Target power option is only for versions > 0 --- src/platforms/native/platform.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/platforms/native/platform.c b/src/platforms/native/platform.c index 224daf8..d361ca8 100644 --- a/src/platforms/native/platform.c +++ b/src/platforms/native/platform.c @@ -154,11 +154,16 @@ void platform_srst_set_val(bool assert) } } bool platform_target_get_power(void) { - return gpio_get(PWR_BR_PORT, PWR_BR_PIN); + if (platform_hwversion() > 0) { + return gpio_get(PWR_BR_PORT, PWR_BR_PIN); + } + return 1; // 1 = Unpowered } void platform_target_set_power(bool power) { - gpio_set_val(PWR_BR_PORT, PWR_BR_PIN, !power); + if (platform_hwversion() > 0) { + gpio_set_val(PWR_BR_PORT, PWR_BR_PIN, !power); + } } void platform_delay(uint32_t delay) { -- cgit v1.2.3 From c1b1d45155ba666d43d4d26b997b45eef8ff50f8 Mon Sep 17 00:00:00 2001 From: Richard Eoin Meadows Date: Wed, 28 May 2014 12:45:21 +0100 Subject: TRST only exists on hardware version 0 --- src/platforms/stm32/jtagtap.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/platforms/stm32/jtagtap.c b/src/platforms/stm32/jtagtap.c index 78dd300..2d09b84 100644 --- a/src/platforms/stm32/jtagtap.c +++ b/src/platforms/stm32/jtagtap.c @@ -42,10 +42,12 @@ int jtagtap_init(void) void jtagtap_reset(void) { #ifdef TRST_PORT - volatile int i; - gpio_clear(TRST_PORT, TRST_PIN); - for(i = 0; i < 10000; i++) asm("nop"); - gpio_set(TRST_PORT, TRST_PIN); + if (platform_hwversion() == 0) { + volatile int i; + gpio_clear(TRST_PORT, TRST_PIN); + for(i = 0; i < 10000; i++) asm("nop"); + gpio_set(TRST_PORT, TRST_PIN); + } #endif jtagtap_soft_reset(); } -- cgit v1.2.3 From 3543e560afdbd795683e7781c6d6dc5ff7567951 Mon Sep 17 00:00:00 2001 From: none Date: Tue, 10 Jun 2014 21:23:17 -0700 Subject: Fix lpc11xx magic number programming when chunks overlap In the case where the vectors are in a separate section smaller than the chunksize, the lpc11xx magic number calculation could generate an incorrect value. --- src/lpc11xx.c | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/lpc11xx.c b/src/lpc11xx.c index 1e9b84d..880f27a 100644 --- a/src/lpc11xx.c +++ b/src/lpc11xx.c @@ -220,26 +220,26 @@ lpc11xx_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, copylen = len; memcpy(&flash_pgm.data[chunk_offset], src, copylen); - /* update to suit */ - len -= copylen; - src += copylen; - chunk_offset = 0; - /* if we are programming the vectors, calculate the magic number */ - if (chunk * IAP_PGM_CHUNKSIZE == 0) { + if ((chunk == 0) && (chunk_offset == 0)) { + if (copylen < 32) { + /* we have to be programming at least the first 8 vectors... */ + return -1; + } + uint32_t *w = (uint32_t *)(&flash_pgm.data[0]); uint32_t sum = 0; - if (copylen >= 7) { - for (unsigned i = 0; i < 7; i++) - sum += w[i]; - w[7] = 0 - sum; - } else { - /* We can't possibly calculate the magic number */ - return -1; - } + for (unsigned i = 0; i < 7; i++) + sum += w[i]; + w[7] = ~sum + 1; } + /* update to suit */ + len -= copylen; + src += copylen; + chunk_offset = 0; + } else { /* interior chunk, must be aligned and full-sized */ -- cgit v1.2.3 From 380f128d0a038a825e4c89a8013eeddca5ab00fe Mon Sep 17 00:00:00 2001 From: Richard Eoin Meadows Date: Fri, 6 Jun 2014 19:57:15 +0100 Subject: Added monitor commands for reading various nRF51 device parameters --- src/nrf51.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 96 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/nrf51.c b/src/nrf51.c index 7a9d136..83773eb 100644 --- a/src/nrf51.c +++ b/src/nrf51.c @@ -35,9 +35,24 @@ static int nrf51_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, int len); static bool nrf51_cmd_erase_all(target *t); +static bool nrf51_cmd_read_hwid(target *t); +static bool nrf51_cmd_read_fwid(target *t); +static bool nrf51_cmd_read_deviceid(target *t); +static bool nrf51_cmd_read_deviceaddr(target *t); +static bool nrf51_cmd_read_help(); +static bool nrf51_cmd_read(target *t, int argc, const char *argv[]); const struct command_s nrf51_cmd_list[] = { {"erase_mass", (cmd_handler)nrf51_cmd_erase_all, "Erase entire flash memory"}, + {"read", (cmd_handler)nrf51_cmd_read, "Read device parameters"}, + {NULL, NULL, NULL} +}; +const struct command_s nrf51_read_cmd_list[] = { + {"help", (cmd_handler)nrf51_cmd_read_help, "Display help for read commands"}, + {"hwid", (cmd_handler)nrf51_cmd_read_hwid, "Read hardware identification number"}, + {"fwid", (cmd_handler)nrf51_cmd_read_fwid, "Read pre-loaded firmware ID"}, + {"deviceid", (cmd_handler)nrf51_cmd_read_deviceid, "Read unique device ID"}, + {"deviceaddr", (cmd_handler)nrf51_cmd_read_deviceaddr, "Read device address"}, {NULL, NULL, NULL} }; @@ -65,10 +80,15 @@ static const char nrf51_xml_memory_map[] = "" #define NRF51_NVMC_CONFIG_EEN 0x2 // Erase enable /* Factory Information Configuration Registers (FICR) */ -#define NRF51_FICR 0x10000000 -#define NRF51_FICR_CODEPAGESIZE (NRF51_FICR + 0x010) +#define NRF51_FICR 0x10000000 +#define NRF51_FICR_CODEPAGESIZE (NRF51_FICR + 0x010) #define NRF51_FICR_CODESIZE (NRF51_FICR + 0x014) #define NRF51_FICR_CONFIGID (NRF51_FICR + 0x05C) +#define NRF51_FICR_DEVICEID_LOW (NRF51_FICR + 0x060) +#define NRF51_FICR_DEVICEID_HIGH (NRF51_FICR + 0x064) +#define NRF51_FICR_DEVICEADDRTYPE (NRF51_FICR + 0x0A0) +#define NRF51_FICR_DEVICEADDR_LOW (NRF51_FICR + 0x0A4) +#define NRF51_FICR_DEVICEADDR_HIGH (NRF51_FICR + 0x0A8) #define NRF51_PAGE_SIZE 1024 @@ -224,6 +244,8 @@ static bool nrf51_cmd_erase_all(target *t) { ADIv5_AP_t *ap = adiv5_target_ap(t); + gdb_out("erase..\n"); + /* Enable erase */ adiv5_ap_mem_write(ap, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_EEN); @@ -241,4 +263,75 @@ static bool nrf51_cmd_erase_all(target *t) return false; return true; -} \ No newline at end of file +} + +static bool nrf51_cmd_read_hwid(target *t) +{ + ADIv5_AP_t *ap = adiv5_target_ap(t); + + uint32_t hwid = adiv5_ap_mem_read(ap, NRF51_FICR_CONFIGID) & 0xFFFF; + gdb_outf("Hardware ID: 0x%04X\n", hwid); + + return true; +} +static bool nrf51_cmd_read_fwid(target *t) +{ + ADIv5_AP_t *ap = adiv5_target_ap(t); + + uint32_t fwid = (adiv5_ap_mem_read(ap, NRF51_FICR_CONFIGID) >> 16) & 0xFFFF; + gdb_outf("Firmware ID: 0x%04X\n", fwid); + + return true; +} +static bool nrf51_cmd_read_deviceid(target *t) +{ + ADIv5_AP_t *ap = adiv5_target_ap(t); + + uint32_t deviceid_low = adiv5_ap_mem_read(ap, NRF51_FICR_DEVICEID_LOW); + uint32_t deviceid_high = adiv5_ap_mem_read(ap, NRF51_FICR_DEVICEID_HIGH); + + gdb_outf("Device ID: 0x%08X%08X\n", deviceid_high, deviceid_low); + + return true; +} +static bool nrf51_cmd_read_deviceaddr(target *t) +{ + ADIv5_AP_t *ap = adiv5_target_ap(t); + + uint32_t addr_type = adiv5_ap_mem_read(ap, NRF51_FICR_DEVICEADDRTYPE); + uint32_t addr_low = adiv5_ap_mem_read(ap, NRF51_FICR_DEVICEADDR_LOW); + uint32_t addr_high = adiv5_ap_mem_read(ap, NRF51_FICR_DEVICEADDR_HIGH) & 0xFFFF; + + if ((addr_type & 1) == 0) { + gdb_outf("Publicly Listed Address: 0x%04X%08X\n", addr_high, addr_low); + } else { + gdb_outf("Randomly Assigned Address: 0x%04X%08X\n", addr_high, addr_low); + } + + return true; +} +static bool nrf51_cmd_read_help() +{ + const struct command_s *c; + + gdb_out("Read commands:\n"); + for(c = nrf51_read_cmd_list; c->cmd; c++) + gdb_outf("\t%s -- %s\n", c->cmd, c->help); + + return true; +} +static bool nrf51_cmd_read(target *t, int argc, const char *argv[]) +{ + const struct command_s *c; + + for(c = nrf51_read_cmd_list; c->cmd; c++) { + /* Accept a partial match as GDB does. + * So 'mon ver' will match 'monitor version' + */ + if(!strncmp(argv[1], c->cmd, strlen(argv[1]))) + return !c->handler(t, argc - 1, &argv[1]); + } + + return nrf51_cmd_read_help(t); +} + -- cgit v1.2.3 From 7dc18768c4bfc949c8fc1f12c753a1e0df7ee0cc Mon Sep 17 00:00:00 2001 From: Richard Eoin Meadows Date: Tue, 10 Jun 2014 23:21:16 +0100 Subject: Support erasing + flashing the User Information Configuration Registers (UICRs) --- src/nrf51.c | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/nrf51.c b/src/nrf51.c index 7a9d136..08dcdb9 100644 --- a/src/nrf51.c +++ b/src/nrf51.c @@ -49,6 +49,9 @@ static const char nrf51_xml_memory_map[] = "" " " " 0x400" " " + " " + " 0x400" + " " " " ""; @@ -70,6 +73,9 @@ static const char nrf51_xml_memory_map[] = "" #define NRF51_FICR_CODESIZE (NRF51_FICR + 0x014) #define NRF51_FICR_CONFIGID (NRF51_FICR + 0x05C) +/* User Information Configuration Registers (UICR) */ +#define NRF51_UICR 0x10001000 + #define NRF51_PAGE_SIZE 1024 uint16_t nrf51_flash_write_stub[] = { @@ -157,8 +163,14 @@ static int nrf51_flash_erase(struct target_s *target, uint32_t addr, int len) return -1; while (len) { - /* Write address of first word in page to erase it */ - adiv5_ap_mem_write(ap, NRF51_NVMC_ERASEPAGE, addr); + if (addr == NRF51_UICR) { // Special Case + /* Write to the ERASE_UICR register to erase */ + adiv5_ap_mem_write(ap, NRF51_NVMC_ERASEUICR, 0x1); + + } else { // Standard Flash Page + /* Write address of first word in page to erase it */ + adiv5_ap_mem_write(ap, NRF51_NVMC_ERASEPAGE, addr); + } /* Poll for NVMC_READY */ while(adiv5_ap_mem_read(ap, NRF51_NVMC_READY) == 0) @@ -241,4 +253,4 @@ static bool nrf51_cmd_erase_all(target *t) return false; return true; -} \ No newline at end of file +} -- cgit v1.2.3 From 88a80e25d53e18ef4da60bb62d0d0b605ab8b801 Mon Sep 17 00:00:00 2001 From: Frantisek Burian Date: Sat, 4 Jan 2014 17:24:32 +0100 Subject: [SUP] Add support for stm32l152c-discovery board --- src/stm32l1.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/stm32l1.c b/src/stm32l1.c index 8e80582..873d9b9 100644 --- a/src/stm32l1.c +++ b/src/stm32l1.c @@ -92,7 +92,8 @@ bool stm32l1_probe(struct target_s *target) idcode = adiv5_ap_mem_read(adiv5_target_ap(target), STM32L1_DBGMCU_IDCODE); switch(idcode & 0xFFF) { case 0x416: /* Medium density */ - case 0x436: /* High density */ + case 0x427: /* Medium+ density*/ + case 0x436: /* Medium+/High density */ target->driver = stm32l1_driver_str; target->xml_mem_map = stm32l1_xml_memory_map; target->flash_erase = stm32l1_flash_erase; -- cgit v1.2.3 From fad6eb3c148ac463c04c3762fc21b03a4db1f8e2 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Wed, 30 Jul 2014 19:57:18 +1200 Subject: Fix parity support on USB UART interface. --- src/platforms/stm32/usbuart.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/platforms/stm32/usbuart.c b/src/platforms/stm32/usbuart.c index 95371dd..f8f56bf 100644 --- a/src/platforms/stm32/usbuart.c +++ b/src/platforms/stm32/usbuart.c @@ -138,7 +138,12 @@ static void usbuart_run(void) void usbuart_set_line_coding(struct usb_cdc_line_coding *coding) { usart_set_baudrate(USBUSART, coding->dwDTERate); - usart_set_databits(USBUSART, coding->bDataBits); + + if (coding->bParityType) + usart_set_databits(USBUSART, coding->bDataBits + 1); + else + usart_set_databits(USBUSART, coding->bDataBits); + switch(coding->bCharFormat) { case 0: usart_set_stopbits(USBUSART, USART_STOPBITS_1); @@ -150,6 +155,7 @@ void usbuart_set_line_coding(struct usb_cdc_line_coding *coding) usart_set_stopbits(USBUSART, USART_STOPBITS_2); break; } + switch(coding->bParityType) { case 0: usart_set_parity(USBUSART, USART_PARITY_NONE); -- cgit v1.2.3 From f06bc0fd79e2b16365c87cfb14d8dd64e6826535 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Wed, 30 Jul 2014 20:27:30 +1200 Subject: Minor fixes to stm32f1 flash routines. --- src/stm32f1.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/stm32f1.c b/src/stm32f1.c index d3cb234..237135f 100644 --- a/src/stm32f1.c +++ b/src/stm32f1.c @@ -228,7 +228,7 @@ static int stm32f1_flash_erase(struct target_s *target, uint32_t addr, int len, uint16_t sr; addr &= ~(pagesize - 1); - len &= ~(pagesize - 1); + len = (len + pagesize - 1) & ~(pagesize - 1); stm32f1_flash_unlock(ap); @@ -273,6 +273,8 @@ static int stm32f1_flash_write(struct target_s *target, uint32_t dest, ADIv5_AP_t *ap = adiv5_target_ap(target); uint32_t offset = dest % 4; uint32_t words = (offset + len + 3) / 4; + if (words > 256) + return -1; uint32_t data[2 + words]; /* Construct data buffer used by stub */ @@ -284,7 +286,7 @@ static int stm32f1_flash_write(struct target_s *target, uint32_t dest, /* Write stub and data to target ram and set PC */ target_mem_write_words(target, 0x20000000, (void*)stm32f1_flash_write_stub, 0x2C); - target_mem_write_words(target, 0x2000002C, data, len + 8); + target_mem_write_words(target, 0x2000002C, data, sizeof(data)); target_pc_write(target, 0x20000000); if(target_check_error(target)) return -1; -- cgit v1.2.3 From d7c30caa3eafcbaf832ddda7d0f2dce546ff5411 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Wed, 30 Jul 2014 21:15:43 +1200 Subject: Style clean up. --- src/lpc43xx.c | 241 +++++++++++++++++++++++++--------------------------------- 1 file changed, 105 insertions(+), 136 deletions(-) (limited to 'src') diff --git a/src/lpc43xx.c b/src/lpc43xx.c index b3a48a9..0376ecf 100644 --- a/src/lpc43xx.c +++ b/src/lpc43xx.c @@ -18,6 +18,7 @@ */ #include +#include #include "command.h" #include "general.h" #include "adiv5.h" @@ -73,11 +74,11 @@ #define CPU_CLK_KHZ 12000 struct flash_param { - uint16_t opcode; /* opcode to return to after calling the ROM */ - uint16_t pad0; - uint32_t command; /* IAP command */ + uint16_t opcode; /* opcode to return to after calling the ROM */ + uint16_t pad0; + uint32_t command; /* IAP command */ union { - uint32_t words[5]; /* command parameters */ + uint32_t words[5]; /* command parameters */ struct { uint32_t start_sector; uint32_t end_sector; @@ -105,11 +106,11 @@ struct flash_param { uint32_t cpu_clk_khz; } make_active; } params; - uint32_t result[5]; /* result data */ + uint32_t result[5]; /* result data */ } __attribute__((aligned(4))); struct flash_program { - struct flash_param p; + struct flash_param p; uint8_t data[IAP_PGM_CHUNKSIZE]; }; @@ -117,10 +118,13 @@ static bool lpc43xx_cmd_erase(target *target, int argc, const char *argv[]); static bool lpc43xx_cmd_reset(target *target, int argc, const char *argv[]); static bool lpc43xx_cmd_mkboot(target *target, int argc, const char *argv[]); static int lpc43xx_flash_init(struct target_s *target); -static void lpc43xx_iap_call(struct target_s *target, struct flash_param *param, unsigned param_len); -static int lpc43xx_flash_prepare(struct target_s *target, uint32_t addr, int len); +static void lpc43xx_iap_call(struct target_s *target, struct flash_param *param, + unsigned param_len); +static int lpc43xx_flash_prepare(struct target_s *target, + uint32_t addr, int len); static int lpc43xx_flash_erase(struct target_s *target, uint32_t addr, int len); -static int lpc43xx_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, int len); +static int lpc43xx_flash_write(struct target_s *target, + uint32_t dest, const uint8_t *src, int len); static void lpc43xx_set_internal_clock(struct target_s *target); const struct command_s lpc43xx_cmd_list[] = { @@ -163,47 +167,50 @@ bool lpc43xx_probe(struct target_s *target) cpuid = adiv5_ap_mem_read(adiv5_target_ap(target), ARM_CPUID); switch(chipid) { - case 0x4906002B: /* Parts with on-chip flash */ - switch (cpuid & 0xFF00FFF0) { - case 0x4100C240: - target->driver = "LPC43xx Cortex-M4"; - if (cpuid == 0x410FC241) - { - /* LPC4337 */ - target->xml_mem_map = lpc4337_xml_memory_map; - target->flash_erase = lpc43xx_flash_erase; - target->flash_write = lpc43xx_flash_write; - target_add_commands(target, lpc43xx_cmd_list, "LPC43xx"); - } - break; - case 0x4100C200: - target->driver = "LPC43xx Cortex-M0"; - break; - default: - target->driver = "LPC43xx "; - } - return true; - case 0x5906002B: /* Flashless parts */ - case 0x6906002B: - switch (cpuid & 0xFF00FFF0) { - case 0x4100C240: - target->driver = "LPC43xx Cortex-M4"; - break; - case 0x4100C200: - target->driver = "LPC43xx Cortex-M0"; - break; - default: - target->driver = "LPC43xx "; + case 0x4906002B: /* Parts with on-chip flash */ + switch (cpuid & 0xFF00FFF0) { + case 0x4100C240: + target->driver = "LPC43xx Cortex-M4"; + if (cpuid == 0x410FC241) + { + /* LPC4337 */ + target->xml_mem_map = lpc4337_xml_memory_map; + target->flash_erase = lpc43xx_flash_erase; + target->flash_write = lpc43xx_flash_write; + target_add_commands(target, lpc43xx_cmd_list, "LPC43xx"); } - return true; + break; + case 0x4100C200: + target->driver = "LPC43xx Cortex-M0"; + break; + default: + target->driver = "LPC43xx "; + } + return true; + case 0x5906002B: /* Flashless parts */ + case 0x6906002B: + switch (cpuid & 0xFF00FFF0) { + case 0x4100C240: + target->driver = "LPC43xx Cortex-M4"; + break; + case 0x4100C200: + target->driver = "LPC43xx Cortex-M0"; + break; + default: + target->driver = "LPC43xx "; + } + return true; } return false; } /* Reset all major systems _except_ debug */ -static bool lpc43xx_cmd_reset(target *target, int __attribute__((unused)) argc, const char __attribute__((unused)) *argv[]) +static bool lpc43xx_cmd_reset(target *target, int argc, const char *argv[]) { + (void)argc; + (void)argv; + /* Cortex-M4 Application Interrupt and Reset Control Register */ static const uint32_t AIRCR = 0xE000ED0C; /* Magic value key */ @@ -215,8 +222,11 @@ static bool lpc43xx_cmd_reset(target *target, int __attribute__((unused)) argc, return true; } -static bool lpc43xx_cmd_erase(target *target, int __attribute__((unused)) argc, const char __attribute__((unused)) *argv[]) +static bool lpc43xx_cmd_erase(target *target, int argc, const char *argv[]) { + (void)argc; + (void)argv; + uint32_t bank = 0; struct flash_program flash_pgm; @@ -264,9 +274,7 @@ static int lpc43xx_flash_init(struct target_s *target) flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS; lpc43xx_iap_call(target, &flash_pgm.p, sizeof(flash_pgm.p)); if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) - { return -1; - } return 0; } @@ -278,22 +286,14 @@ static int lpc43xx_flash_init(struct target_s *target) */ static int32_t flash_bank(uint32_t addr) { - int32_t retVal; - - if (addr >= FLASH_BANK_A_BASE && addr < (FLASH_BANK_A_BASE+FLASH_BANK_A_SIZE)) - { - retVal = 0; - } - else if (addr >= FLASH_BANK_B_BASE && addr < (FLASH_BANK_B_BASE+FLASH_BANK_B_SIZE)) - { - retVal = 1; - } - else - { - retVal = -1; - } - - return retVal; + if ((addr >= FLASH_BANK_A_BASE) && + (addr < (FLASH_BANK_A_BASE + FLASH_BANK_A_SIZE))) + return 0; + if ((addr >= FLASH_BANK_B_BASE) && + (addr < (FLASH_BANK_B_BASE + FLASH_BANK_B_SIZE))) + return 1; + + return -1; } /** @@ -301,36 +301,25 @@ static int32_t flash_bank(uint32_t addr) */ static int32_t sector_number(uint32_t addr) { - int32_t retVal = 0; int32_t bank = flash_bank(addr); - if (bank == 0) - { + switch (bank) { + case 0: addr = addr - FLASH_BANK_A_BASE; - } - else if (bank == 1) - { + break; + case 1: addr = addr - FLASH_BANK_B_BASE; - } - else - { - retVal = -1; + break; + default: + return -1; } - if (retVal != -1) - { - /* from 47.5 "Sector numbers" (page 1218) UM10503.pdf (Rev 1.6) */ - if (addr < FLASH_LARGE_SECTOR_OFFSET) - { - retVal = addr >> 13; - } - else - { - retVal = 8 + ((addr - FLASH_LARGE_SECTOR_OFFSET) >> 16); - } + /* from 47.5 "Sector numbers" (page 1218) UM10503.pdf (Rev 1.6) */ + if (addr < FLASH_LARGE_SECTOR_OFFSET) { + return addr >> 13; + } else { + return 8 + ((addr - FLASH_LARGE_SECTOR_OFFSET) >> 16); } - - return retVal; } static void lpc43xx_iap_call(struct target_s *target, struct flash_param *param, unsigned param_len) @@ -382,28 +371,21 @@ static int lpc43xx_flash_prepare(struct target_s *target, uint32_t addr, int len return 0; } - static int -lpc43xx_flash_erase(struct target_s *target, uint32_t addr, int len) +static int lpc43xx_flash_erase(struct target_s *target, uint32_t addr, int len) { struct flash_program flash_pgm; /* min block size */ if (addr % 8192) - { return -1; - } /* init */ if (lpc43xx_flash_init(target)) - { return -1; - } /* prepare... */ if (lpc43xx_flash_prepare(target, addr, len)) - { return -1; - } /* and now erase them */ flash_pgm.p.command = IAP_CMD_ERASE; @@ -437,7 +419,8 @@ static void lpc43xx_set_internal_clock(struct target_s *target) target_mem_write_words(target, 0x40050000 + 0x06C, &val2, sizeof(val2)); } -static int lpc43xx_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, int len) +static int lpc43xx_flash_write(struct target_s *target, + uint32_t dest, const uint8_t *src, int len) { unsigned first_chunk = dest / IAP_PGM_CHUNKSIZE; unsigned last_chunk = (dest + len - 1) / IAP_PGM_CHUNKSIZE; @@ -445,14 +428,10 @@ static int lpc43xx_flash_write(struct target_s *target, uint32_t dest, const uin unsigned chunk; struct flash_program flash_pgm; - for (chunk = first_chunk; chunk <= last_chunk; chunk++) - { - if (chunk == first_chunk) - { + for (chunk = first_chunk; chunk <= last_chunk; chunk++) { + if (chunk == first_chunk) { chunk_offset = dest % IAP_PGM_CHUNKSIZE; - } - else - { + } else { chunk_offset = 0; } @@ -473,7 +452,6 @@ static int lpc43xx_flash_write(struct target_s *target, uint32_t dest, const uin len -= copylen; src += copylen; } else { - /* interior chunk, must be aligned and full-sized */ memcpy(flash_pgm.data, src, IAP_PGM_CHUNKSIZE); len -= IAP_PGM_CHUNKSIZE; @@ -481,8 +459,7 @@ static int lpc43xx_flash_write(struct target_s *target, uint32_t dest, const uin } /* prepare... */ - if (lpc43xx_flash_prepare(target, chunk * IAP_PGM_CHUNKSIZE, IAP_PGM_CHUNKSIZE)) - { + if (lpc43xx_flash_prepare(target, chunk * IAP_PGM_CHUNKSIZE, IAP_PGM_CHUNKSIZE)) { return -1; } @@ -507,7 +484,7 @@ static int lpc43xx_flash_write(struct target_s *target, uint32_t dest, const uin return 0; } -/* +/* * Call Boot ROM code to make a flash bank bootable by computing and writing the * correct signature into the exception table near the start of the bank. * @@ -517,41 +494,33 @@ static int lpc43xx_flash_write(struct target_s *target, uint32_t dest, const uin static bool lpc43xx_cmd_mkboot(target *target, int argc, const char *argv[]) { /* Usage: mkboot 0 or mkboot 1 */ - if (argc == 2) - { - const long int bank = strtol(argv[1], NULL, 0); - - if (bank == 0 || bank == 1) - { - lpc43xx_flash_init(target); - struct flash_program flash_pgm; - - /* special command to compute/write magic vector for signature */ - flash_pgm.p.command = IAP_CMD_SET_ACTIVE_BANK; - flash_pgm.p.params.make_active.flash_bank = bank; - flash_pgm.p.params.make_active.cpu_clk_khz = CPU_CLK_KHZ; - flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS; - lpc43xx_iap_call(target, &flash_pgm.p, sizeof(flash_pgm)); - if (flash_pgm.p.result[0] == IAP_STATUS_CMD_SUCCESS) { - gdb_outf("Set bootable OK.\n"); - return true; - } - else - { - gdb_outf("Set bootable failed.\n"); - } - } - else - { - gdb_outf("Unexpected bank number, should be 0 or 1.\n"); - } - } - else - { + if (argc != 2) { gdb_outf("Expected bank argument 0 or 1.\n"); + return false; } + const long int bank = strtol(argv[1], NULL, 0); - return false; + if ((bank != 0) && (bank != 1)) { + gdb_outf("Unexpected bank number, should be 0 or 1.\n"); + return false; + } + + lpc43xx_flash_init(target); + struct flash_program flash_pgm; + + /* special command to compute/write magic vector for signature */ + flash_pgm.p.command = IAP_CMD_SET_ACTIVE_BANK; + flash_pgm.p.params.make_active.flash_bank = bank; + flash_pgm.p.params.make_active.cpu_clk_khz = CPU_CLK_KHZ; + flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS; + lpc43xx_iap_call(target, &flash_pgm.p, sizeof(flash_pgm)); + if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { + gdb_outf("Set bootable failed.\n"); + return false; + } + + gdb_outf("Set bootable OK.\n"); + return true; } -- cgit v1.2.3 From d265b7600166fc829fa74f7ffdb1fa8e2fb31e84 Mon Sep 17 00:00:00 2001 From: Hans Baier Date: Mon, 4 Aug 2014 17:19:58 +0700 Subject: Add support for STM32F401RE --- src/stm32f4.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/stm32f4.c b/src/stm32f4.c index cfbe9e3..892af41 100644 --- a/src/stm32f4.c +++ b/src/stm32f4.c @@ -82,7 +82,6 @@ static const char stm32f4_xml_memory_map[] = "" " " ""; - /* Flash Program ad Erase Controller Register Map */ #define FPEC_BASE 0x40023C00 #define FLASH_ACR (FPEC_BASE+0x00) @@ -169,11 +168,12 @@ bool stm32f4_probe(struct target_s *target) idcode = adiv5_ap_mem_read(adiv5_target_ap(target), DBGMCU_IDCODE); switch(idcode & 0xFFF) { case 0x411: /* Documented to be 0x413! This is what I read... */ - case 0x413: - case 0x423: /* F401 */ + case 0x413: /* F407VGT6 */ case 0x419: /* 427/437 */ - target->driver = stm32f4_driver_str; + case 0x423: /* F401 */ + case 0x433: /* F401RET6U */ target->xml_mem_map = stm32f4_xml_memory_map; + target->driver = stm32f4_driver_str; target->flash_erase = stm32f4_flash_erase; target->flash_write = stm32f4_flash_write; target_add_commands(target, stm32f4_cmd_list, "STM32F4"); -- cgit v1.2.3 From 84fc40085ea825e890d65ce4e5e4d87b51ea588d Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Wed, 6 Aug 2014 12:38:57 +1200 Subject: Send a null packet on end of USB transfer if last data packet is full. --- src/platforms/stm32/gdb_if.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'src') diff --git a/src/platforms/stm32/gdb_if.c b/src/platforms/stm32/gdb_if.c index 3ea7d14..28bc4c8 100644 --- a/src/platforms/stm32/gdb_if.c +++ b/src/platforms/stm32/gdb_if.c @@ -47,6 +47,18 @@ void gdb_if_putchar(unsigned char c, int flush) } while(usbd_ep_write_packet(usbdev, CDCACM_GDB_ENDPOINT, buffer_in, count_in) <= 0); + + if (flush && (count_in == CDCACM_PACKET_SIZE)) { + /* We need to send an empty packet for some hosts + * to accept this as a complete transfer. */ + /* libopencm3 needs a change for us to confirm when + * that transfer is complete, so we just send a packet + * containing a null byte for now. + */ + while (usbd_ep_write_packet(usbdev, CDCACM_GDB_ENDPOINT, + "\0", 1) <= 0); + } + count_in = 0; } } -- cgit v1.2.3 From 8a32b46f65ad8bc20107a26df9b7d3d9a356a5ee Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Fri, 8 Aug 2014 20:22:33 +1200 Subject: Fix build for non-native targets. --- src/command.c | 7 +++++++ src/platforms/native/platform.h | 5 ++++- 2 files changed, 11 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/command.c b/src/command.c index 0c97949..e817197 100644 --- a/src/command.c +++ b/src/command.c @@ -47,7 +47,9 @@ static bool cmd_swdp_scan(void); static bool cmd_targets(target *t); static bool cmd_morse(void); static bool cmd_connect_srst(target *t, int argc, const char **argv); +#ifdef PLATFORM_HAS_POWER_SWITCH static bool cmd_target_power(target *t, int argc, const char **argv); +#endif #ifdef PLATFORM_HAS_TRACESWO static bool cmd_traceswo(void); #endif @@ -60,7 +62,9 @@ const struct command_s cmd_list[] = { {"targets", (cmd_handler)cmd_targets, "Display list of available targets" }, {"morse", (cmd_handler)cmd_morse, "Display morse error message" }, {"connect_srst", (cmd_handler)cmd_connect_srst, "Configure connect under SRST: (enable|disable)" }, +#ifdef PLATFORM_HAS_POWER_SWITCH {"tpwr", (cmd_handler)cmd_target_power, "Supplies power to the target: (enable|disable)"}, +#endif #ifdef PLATFORM_HAS_TRACESWO {"traceswo", (cmd_handler)cmd_traceswo, "Start trace capture" }, #endif @@ -223,6 +227,8 @@ static bool cmd_connect_srst(target *t, int argc, const char **argv) connect_assert_srst = !strcmp(argv[1], "enable"); return true; } + +#ifdef PLATFORM_HAS_POWER_SWITCH static bool cmd_target_power(target *t, int argc, const char **argv) { (void)t; @@ -233,6 +239,7 @@ static bool cmd_target_power(target *t, int argc, const char **argv) platform_target_set_power(!strncmp(argv[1], "enable", strlen(argv[1]))); return true; } +#endif #ifdef PLATFORM_HAS_TRACESWO static bool cmd_traceswo(void) diff --git a/src/platforms/native/platform.h b/src/platforms/native/platform.h index 5ca0408..3bbcd17 100644 --- a/src/platforms/native/platform.h +++ b/src/platforms/native/platform.h @@ -39,6 +39,7 @@ #define INLINE_GPIO #define CDCACM_PACKET_SIZE 64 #define PLATFORM_HAS_TRACESWO +#define PLATFORM_HAS_POWER_SWITCH #define BOARD_IDENT "Black Magic Probe" #define BOARD_IDENT_DFU "Black Magic Probe (Upgrade)" #define BOARD_IDENT_UPD "Black Magic Probe (DFU Upgrade)" @@ -225,7 +226,6 @@ static inline uint16_t _gpio_get(uint32_t gpioport, uint16_t gpios) #define gpio_get _gpio_get #endif -#endif #define disconnect_usb() gpio_set_mode(USB_PU_PORT, GPIO_MODE_INPUT, 0, USB_PU_PIN); void assert_boot_pin(void); @@ -233,3 +233,6 @@ void setup_vbus_irq(void); void platform_srst_set_val(bool assert); bool platform_target_get_power(void); void platform_target_set_power(bool power); + +#endif + -- cgit v1.2.3 From 9d9ecb572e67adb7c7e6a01678d0bd735aa30aa4 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Wed, 27 Aug 2014 19:03:37 +1200 Subject: Assert SRST when scanning JTAG if configured. Closes #54. --- src/jtag_scan.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/jtag_scan.c b/src/jtag_scan.c index bfce1ec..6ca4603 100644 --- a/src/jtag_scan.c +++ b/src/jtag_scan.c @@ -114,6 +114,8 @@ int jtag_scan(const uint8_t *irlens) */ DEBUG("Resetting TAP\n"); jtagtap_init(); + if(connect_assert_srst) + jtagtap_srst(true); /* will be deasserted after attach */ jtagtap_reset(); if (irlens) { -- cgit v1.2.3 From 945a2802d526cd333dac882dbffc9f5608f645b4 Mon Sep 17 00:00:00 2001 From: Richard Eoin Meadows Date: Thu, 3 Jul 2014 22:03:11 +0100 Subject: Atmel SAMD20 support --- src/Makefile | 1 + src/cortexm.c | 1 + src/include/target.h | 1 + src/samd20.c | 586 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 589 insertions(+) create mode 100644 src/samd20.c (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 85b0337..62cc617 100644 --- a/src/Makefile +++ b/src/Makefile @@ -31,6 +31,7 @@ SRC = \ nrf51.c \ platform.c \ sam3x.c \ + samd20.c \ stm32f1.c \ stm32f4.c \ stm32l1.c \ diff --git a/src/cortexm.c b/src/cortexm.c index 8a9beb8..1142394 100644 --- a/src/cortexm.c +++ b/src/cortexm.c @@ -384,6 +384,7 @@ cortexm_probe(struct target_s *target) PROBE(lpc43xx_probe); PROBE(sam3x_probe); PROBE(nrf51_probe); + PROBE(samd20_probe); PROBE(lmi_probe); #undef PROBE diff --git a/src/include/target.h b/src/include/target.h index 03230a5..067b051 100644 --- a/src/include/target.h +++ b/src/include/target.h @@ -213,6 +213,7 @@ bool lpc11xx_probe(struct target_s *target); bool lpc43xx_probe(struct target_s *target); bool sam3x_probe(struct target_s *target); bool nrf51_probe(struct target_s *target); +bool samd20_probe(struct target_s *target); #endif diff --git a/src/samd20.c b/src/samd20.c new file mode 100644 index 0000000..e646a00 --- /dev/null +++ b/src/samd20.c @@ -0,0 +1,586 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2014 Richard Meadows + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * 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, see . + */ + +/* This file implements Atmel SAM D20 target specific functions for + * detecting the device, providing the XML memory map and Flash memory + * programming. + */ + +#include +#include +#include + +#include "general.h" +#include "jtagtap.h" +#include "adiv5.h" +#include "target.h" +#include "command.h" +#include "gdb_packet.h" + +static int samd20_flash_erase(struct target_s *target, uint32_t addr, int len); +static int samd20_flash_write(struct target_s *target, uint32_t dest, + const uint8_t *src, int len); + +static bool samd20_cmd_erase_all(target *t); +static bool samd20_cmd_lock_flash(target *t); +static bool samd20_cmd_unlock_flash(target *t); +static bool samd20_cmd_read_userrow(target *t); +static bool samd20_cmd_serial(target *t); +static bool samd20_cmd_mbist(target *t); + +const struct command_s samd20_cmd_list[] = { + {"erase_mass", (cmd_handler)samd20_cmd_erase_all, "Erase entire flash memory"}, + {"lock_flash", (cmd_handler)samd20_cmd_lock_flash, "Locks flash against spurious commands"}, + {"unlock_flash", (cmd_handler)samd20_cmd_unlock_flash, "Unlocks flash"}, + {"user_row", (cmd_handler)samd20_cmd_read_userrow, "Prints user row from flash"}, + {"serial", (cmd_handler)samd20_cmd_serial, "Prints serial number"}, + {"mbist", (cmd_handler)samd20_cmd_mbist, "Runs the built-in memory test"}, + {NULL, NULL, NULL} +}; + +/** + * 256KB Flash Max., 32KB RAM Max. The smallest unit of erase is the + * one row = 256 bytes. + */ +static const char samd20_xml_memory_map[] = "" +/* ""*/ + "" + " " + " 0x100" + " " + " " + ""; + +/* Non-Volatile Memory Controller (NVMC) Parameters */ +#define SAMD20_ROW_SIZE 256 +#define SAMD20_PAGE_SIZE 64 + +/* Non-Volatile Memory Controller (NVMC) Registers */ +#define SAMD20_NVMC 0x41004000 +#define SAMD20_NVMC_CMD (SAMD20_NVMC + 0x0) +#define SAMD20_NVMC_PARAM (SAMD20_NVMC + 0x08) +#define SAMD20_NVMC_INTFLAG (SAMD20_NVMC + 0x14) +#define SAMD20_NVMC_STATUS (SAMD20_NVMC + 0x18) +#define SAMD20_NVMC_ADDRESS (SAMD20_NVMC + 0x1C) + +/* Command Register (CMD) */ +#define SAMD20_CMD_KEY 0xA500 +#define SAMD20_CMD_ERASEROW 0x0002 +#define SAMD20_CMD_WRITEPAGE 0x0004 +#define SAMD20_CMD_ERASEAUXROW 0x0005 +#define SAMD20_CMD_WRITEAUXPAGE 0x0006 +#define SAMD20_CMD_LOCK 0x0040 +#define SAMD20_CMD_UNLOCK 0x0041 +#define SAMD20_CMD_PAGEBUFFERCLEAR 0x0044 + +/* Interrupt Flag Register (INTFLAG) */ +#define SAMD20_NVMC_READY (1 << 0) + +/* Non-Volatile Memory Calibration and Auxiliary Registers */ +#define SAMD20_NVM_USER_ROW_LOW 0x00804000 +#define SAMD20_NVM_USER_ROW_HIGH 0x00804004 +#define SAMD20_NVM_CALIBRATION 0x00806020 +#define SAMD20_NVM_SERIAL(n) (0x0080A00C + (0x30 * ((n + 3) / 4)) + \ + (0x4 * n)) + +/* Device Service Unit (DSU) Registers */ +#define SAMD20_DSU 0x41002000 +#define SAMD20_DSU_CTRLSTAT (SAMD20_DSU + 0x0) +#define SAMD20_DSU_ADDRESS (SAMD20_DSU + 0x4) +#define SAMD20_DSU_LENGTH (SAMD20_DSU + 0x8) +#define SAMD20_DSU_DID (SAMD20_DSU + 0x018) +#define SAMD20_DSU_PID(n) (SAMD20_DSU + 0x1FE0 + \ + (0x4 * (n % 4)) - (0x10 * (n / 4))) +#define SAMD20_DSU_CID(n) (SAMD20_DSU + 0x1FF0 + \ + (0x4 * (n % 4))) + +/* Control and Status Register (CTRLSTAT) */ +#define SAMD20_CTRL_CHIP_ERASE (1 << 4) +#define SAMD20_CTRL_MBIST (1 << 3) +#define SAMD20_CTRL_CRC (1 << 2) +#define SAMD20_STATUSA_FAIL (1 << 11) +#define SAMD20_STATUSA_CRSTEXT (1 << 9) +#define SAMD20_STATUSA_DONE (1 << 8) + +/* Device Identification Register (DID) */ +#define SAMD20_DID_MASK 0xFFBF0000 +#define SAMD20_DID_CONST_VALUE 0x10000000 +#define SAMD20_DID_DEVSEL_MASK 0x0F + +/* Peripheral ID */ +#define SAMD20_PID_MASK 0x00F7FFFF +#define SAMD20_PID_CONST_VALUE 0x0001FCD0 + +/* Component ID */ +#define SAMD20_CID_VALUE 0xB105100D + +#define CORTEXM_PPB_BASE 0xE0000000 + +#define CORTEXM_SCS_BASE (CORTEXM_PPB_BASE + 0xE000) + +#define CORTEXM_AIRCR (CORTEXM_SCS_BASE + 0xD0C) +#define CORTEXM_CFSR (CORTEXM_SCS_BASE + 0xD28) +#define CORTEXM_HFSR (CORTEXM_SCS_BASE + 0xD2C) +#define CORTEXM_DFSR (CORTEXM_SCS_BASE + 0xD30) +#define CORTEXM_CPACR (CORTEXM_SCS_BASE + 0xD88) +#define CORTEXM_DHCSR (CORTEXM_SCS_BASE + 0xDF0) +#define CORTEXM_DCRSR (CORTEXM_SCS_BASE + 0xDF4) +#define CORTEXM_DCRDR (CORTEXM_SCS_BASE + 0xDF8) +#define CORTEXM_DEMCR (CORTEXM_SCS_BASE + 0xDFC) + +/* Application Interrupt and Reset Control Register (AIRCR) */ +#define CORTEXM_AIRCR_VECTKEY (0x05FA << 16) +/* Bits 31:16 - Read as VECTKETSTAT, 0xFA05 */ +#define CORTEXM_AIRCR_ENDIANESS (1 << 15) +/* Bits 15:11 - Unused, reserved */ +#define CORTEXM_AIRCR_PRIGROUP (7 << 8) +/* Bits 7:3 - Unused, reserved */ +#define CORTEXM_AIRCR_SYSRESETREQ (1 << 2) +#define CORTEXM_AIRCR_VECTCLRACTIVE (1 << 1) +#define CORTEXM_AIRCR_VECTRESET (1 << 0) + +/* Debug Fault Status Register (DFSR) */ +/* Bits 31:5 - Reserved */ +#define CORTEXM_DFSR_RESETALL 0x1F +#define CORTEXM_DFSR_EXTERNAL (1 << 4) +#define CORTEXM_DFSR_VCATCH (1 << 3) +#define CORTEXM_DFSR_DWTTRAP (1 << 2) +#define CORTEXM_DFSR_BKPT (1 << 1) +#define CORTEXM_DFSR_HALTED (1 << 0) + +/* Debug Halting Control and Status Register (DHCSR) */ +/* This key must be written to bits 31:16 for write to take effect */ +#define CORTEXM_DHCSR_DBGKEY 0xA05F0000 +/* Bits 31:26 - Reserved */ +#define CORTEXM_DHCSR_S_RESET_ST (1 << 25) +#define CORTEXM_DHCSR_S_RETIRE_ST (1 << 24) +/* Bits 23:20 - Reserved */ +#define CORTEXM_DHCSR_S_LOCKUP (1 << 19) +#define CORTEXM_DHCSR_S_SLEEP (1 << 18) +#define CORTEXM_DHCSR_S_HALT (1 << 17) +#define CORTEXM_DHCSR_S_REGRDY (1 << 16) +/* Bits 15:6 - Reserved */ +#define CORTEXM_DHCSR_C_SNAPSTALL (1 << 5) /* v7m only */ +/* Bit 4 - Reserved */ +#define CORTEXM_DHCSR_C_MASKINTS (1 << 3) +#define CORTEXM_DHCSR_C_STEP (1 << 2) +#define CORTEXM_DHCSR_C_HALT (1 << 1) +#define CORTEXM_DHCSR_C_DEBUGEN (1 << 0) + +/* Utility */ +#define MINIMUM(a,b) ((a < b) ? a : b) + +/** + * Reads the SAM D20 Peripheral ID + */ +uint64_t samd20_read_pid(struct target_s *target) +{ + ADIv5_AP_t *ap = adiv5_target_ap(target); + uint64_t pid = 0; + uint8_t i, j; + + /* Five PID registers to read LSB first */ + for (i = 0, j = 0; i < 5; i++, j += 8) + pid |= (adiv5_ap_mem_read(ap, SAMD20_DSU_PID(i)) & 0xFF) << j; + + return pid; +} +/** + * Reads the SAM D20 Component ID + */ +uint32_t samd20_read_cid(struct target_s *target) +{ + ADIv5_AP_t *ap = adiv5_target_ap(target); + uint64_t cid = 0; + uint8_t i, j; + + /* Four CID registers to read LSB first */ + for (i = 0, j = 0; i < 4; i++, j += 8) + cid |= (adiv5_ap_mem_read(ap, SAMD20_DSU_CID(i)) & 0xFF) << j; + + return cid; +} + +/** + * Overloads the default cortexm reset function with a version that + * removes the target from extended reset where required. + */ +static void +samd20_reset(struct target_s *target) +{ + ADIv5_AP_t *ap = adiv5_target_ap(target); + + jtagtap_srst(true); + jtagtap_srst(false); + + /* Read DHCSR here to clear S_RESET_ST bit before reset */ + adiv5_ap_mem_read(ap, CORTEXM_DHCSR); + + /* Request system reset from NVIC: SRST doesn't work correctly */ + /* This could be VECTRESET: 0x05FA0001 (reset only core) + * or SYSRESETREQ: 0x05FA0004 (system reset) + */ + adiv5_ap_mem_write(ap, CORTEXM_AIRCR, + CORTEXM_AIRCR_VECTKEY | CORTEXM_AIRCR_SYSRESETREQ); + + /* Exit extended reset */ + if (adiv5_ap_mem_read(ap, SAMD20_DSU_CTRLSTAT) & + SAMD20_STATUSA_CRSTEXT) { + /* Write bit to clear from extended reset */ + adiv5_ap_mem_write(ap, SAMD20_DSU_CTRLSTAT, + SAMD20_STATUSA_CRSTEXT); + } + + /* Poll for release from reset */ + while(adiv5_ap_mem_read(ap, CORTEXM_DHCSR) & CORTEXM_DHCSR_S_RESET_ST); + + /* Reset DFSR flags */ + adiv5_ap_mem_write(ap, CORTEXM_DFSR, CORTEXM_DFSR_RESETALL); + + /* Clear any target errors */ + target_check_error(target); +} + +char variant_string[30]; +bool samd20_probe(struct target_s *target) +{ + ADIv5_AP_t *ap = adiv5_target_ap(target); + uint32_t cid = samd20_read_cid(target); + uint32_t pid = samd20_read_pid(target); + + /* Check the ARM Coresight Component and Perhiperal IDs */ + if (cid == SAMD20_CID_VALUE && + (pid & SAMD20_PID_MASK) == SAMD20_PID_CONST_VALUE) { + + /* Read the Device ID */ + uint32_t did = adiv5_ap_mem_read(ap, SAMD20_DSU_DID); + + /* If the Device ID matches */ + if ((did & SAMD20_DID_MASK) == SAMD20_DID_CONST_VALUE) { + + uint8_t devsel = did & SAMD20_DID_DEVSEL_MASK; + + /* Pin Variant */ + char pin_variant; + switch (devsel / 5) { + case 0: pin_variant = 'J'; break; + case 1: pin_variant = 'G'; break; + case 2: pin_variant = 'E'; break; + default: pin_variant = 'u'; break; + } + + /* Mem Variant */ + uint8_t mem_variant = 18 - (devsel % 5); + + /* Part String */ + sprintf(variant_string, "Atmel SAMD20%c%dA", + pin_variant, mem_variant); + + /* Setup Target */ + target->driver = variant_string; + target->reset = samd20_reset; + target->xml_mem_map = samd20_xml_memory_map; + target->flash_erase = samd20_flash_erase; + target->flash_write = samd20_flash_write; + target_add_commands(target, samd20_cmd_list, "SAMD20"); + + /* Release the target from extended reset to make attach possible */ + if (adiv5_ap_mem_read(ap, SAMD20_DSU_CTRLSTAT) & + SAMD20_STATUSA_CRSTEXT) { + + /* Write bit to clear from extended reset */ + adiv5_ap_mem_write(ap, SAMD20_DSU_CTRLSTAT, + SAMD20_STATUSA_CRSTEXT); + } + + return true; + } + } + + return false; +} + +/** + * Temporary (until next reset) flash memory locking / unlocking + */ +static void samd20_lock_current_address(struct target_s *target) +{ + ADIv5_AP_t *ap = adiv5_target_ap(target); + + /* Issue the unlock command */ + adiv5_ap_mem_write(ap, SAMD20_NVMC_CMD, SAMD20_CMD_KEY | SAMD20_CMD_LOCK); +} +static void samd20_unlock_current_address(struct target_s *target) +{ + ADIv5_AP_t *ap = adiv5_target_ap(target); + + /* Issue the unlock command */ + adiv5_ap_mem_write(ap, SAMD20_NVMC_CMD, SAMD20_CMD_KEY | SAMD20_CMD_UNLOCK); +} + +/** + * Erase flash row by row + */ +static int samd20_flash_erase(struct target_s *target, uint32_t addr, int len) +{ + ADIv5_AP_t *ap = adiv5_target_ap(target); + + addr &= ~(SAMD20_ROW_SIZE - 1); + len &= ~(SAMD20_ROW_SIZE - 1); + + + + + while (len) { + /* Write address of first word in row to erase it */ + /* Must be shifted right for 16-bit address, see Datasheet §20.8.8 Address */ + adiv5_ap_mem_write(ap, SAMD20_NVMC_ADDRESS, addr >> 1); + + /* Unlock */ + samd20_unlock_current_address(target); + + /* Issue the erase command */ + adiv5_ap_mem_write(ap, SAMD20_NVMC_CMD, SAMD20_CMD_KEY | SAMD20_CMD_ERASEROW); + /* Poll for NVM Ready */ + while ((adiv5_ap_mem_read(ap, SAMD20_NVMC_INTFLAG) & SAMD20_NVMC_READY) == 0) + if(target_check_error(target)) + return -1; + + /* Lock */ + samd20_lock_current_address(target); + + addr += SAMD20_ROW_SIZE; + len -= SAMD20_ROW_SIZE; + } + + return 0; +} + +/** + * Write flash page by page + */ +static int samd20_flash_write(struct target_s *target, uint32_t dest, + const uint8_t *src, int len) +{ + ADIv5_AP_t *ap = adiv5_target_ap(target); + + /* Find the size of our 32-bit data buffer */ + uint32_t offset = dest % 4; + uint32_t words = (offset + len + 3) / 4; + uint32_t data[words], i = 0; + + /* Populate the data buffer */ + memset((uint8_t *)data, 0xFF, words * 4); + memcpy((uint8_t *)data + offset, src, len); + + /* The address of the first word involved in the write */ + uint32_t addr = dest & ~0x3; + /* The address of the last word involved in the write */ + uint32_t end = (dest + len - 1) & ~0x3; + + /* The start address of the first page involved in the write */ + uint32_t first_page = dest & ~(SAMD20_PAGE_SIZE - 1); + /* The start address of the last page involved in the write */ + uint32_t last_page = (dest + len - 1) & ~(SAMD20_PAGE_SIZE - 1); + uint32_t end_of_this_page; + + + for (uint32_t page = first_page; page <= last_page; page += SAMD20_PAGE_SIZE) { + end_of_this_page = page + (SAMD20_PAGE_SIZE - 4); + + if (addr > page || (page == last_page && end < end_of_this_page)) { + + /* Partial, manual page write */ + for (; addr <= MINIMUM(end, end_of_this_page); addr += 4, i++) { + adiv5_ap_mem_write(ap, addr, data[i]); + } + + /* Unlock */ + samd20_unlock_current_address(target); + + /* Issue the write page command */ + adiv5_ap_mem_write(ap, SAMD20_NVMC_CMD, + SAMD20_CMD_KEY | SAMD20_CMD_WRITEPAGE); + } else { + /* Write first word to set address */ + adiv5_ap_mem_write(ap, addr, data[i]); addr += 4; i++; + + /* Unlock */ + samd20_unlock_current_address(target); + + /* Full, automatic page write */ + for (; addr < page + SAMD20_PAGE_SIZE; addr += 4, i++) { + adiv5_ap_mem_write(ap, addr, data[i]); + } + } + + /* Poll for NVM Ready */ + while ((adiv5_ap_mem_read(ap, SAMD20_NVMC_INTFLAG) & SAMD20_NVMC_READY) == 0) + if(target_check_error(target)) + return -1; + + /* Lock */ + samd20_lock_current_address(target); + } + + return 0; +} + +/** + * Uses the Device Service Unit to erase the entire flash + */ +static bool samd20_cmd_erase_all(target *t) +{ + ADIv5_AP_t *ap = adiv5_target_ap(t); + + /* Erase all */ + adiv5_ap_mem_write(ap, SAMD20_DSU_CTRLSTAT, SAMD20_CTRL_CHIP_ERASE); + + /* Poll for DSU Ready */ + while ((adiv5_ap_mem_read(ap, SAMD20_DSU_CTRLSTAT) & SAMD20_STATUSA_DONE) == 0) + if(target_check_error(t)) + return false; + + return true; +} + +/** + * Sets the NVM region lock bits in the User Row. This value is read + * at startup as the default value for the lock bits, and hence does + * not take effect until a reset. + * + * 0x0000 = Lock, 0xFFFF = Unlock (default) + */ +static bool samd20_set_flashlock(target *t, uint16_t value) +{ + ADIv5_AP_t *ap = adiv5_target_ap(t); + + uint32_t high = adiv5_ap_mem_read(ap, SAMD20_NVM_USER_ROW_HIGH); + uint32_t low = adiv5_ap_mem_read(ap, SAMD20_NVM_USER_ROW_LOW); + + /* Write address of a word in the row to erase it */ + /* Must be shifted right for 16-bit address, see Datasheet §20.8.8 Address */ + adiv5_ap_mem_write(ap, SAMD20_NVMC_ADDRESS, SAMD20_NVM_USER_ROW_LOW >> 1); + + /* Issue the erase command */ + adiv5_ap_mem_write(ap, SAMD20_NVMC_CMD, SAMD20_CMD_KEY | SAMD20_CMD_ERASEAUXROW); + + /* Poll for NVM Ready */ + while ((adiv5_ap_mem_read(ap, SAMD20_NVMC_INTFLAG) & SAMD20_NVMC_READY) == 0) + if(target_check_error(t)) + return -1; + + /* Modify the high byte of the user row */ + high = (high & 0x0000FFFF) | ((value << 16) & 0xFFFF0000); + + /* Write back */ + adiv5_ap_mem_write(ap, SAMD20_NVM_USER_ROW_LOW, low); + adiv5_ap_mem_write(ap, SAMD20_NVM_USER_ROW_HIGH, high); + + /* Issue the page write command */ + adiv5_ap_mem_write(ap, SAMD20_NVMC_CMD, + SAMD20_CMD_KEY | SAMD20_CMD_WRITEAUXPAGE); + + return true; +} +static bool samd20_cmd_lock_flash(target *t) +{ + return samd20_set_flashlock(t, 0x0000); +} +static bool samd20_cmd_unlock_flash(target *t) +{ + return samd20_set_flashlock(t, 0xFFFF); +} +static bool samd20_cmd_read_userrow(target *t) +{ + ADIv5_AP_t *ap = adiv5_target_ap(t); + + gdb_outf("User Row: 0x%08x%08x\n", + adiv5_ap_mem_read(ap, SAMD20_NVM_USER_ROW_HIGH), + adiv5_ap_mem_read(ap, SAMD20_NVM_USER_ROW_LOW)); + + return true; +} +/** + * Reads the 128-bit serial number from the NVM + */ +static bool samd20_cmd_serial(target *t) +{ + ADIv5_AP_t *ap = adiv5_target_ap(t); + + gdb_outf("Serial Number: 0x"); + + for (uint32_t i = 0; i < 4; i++) { + gdb_outf("%08x", adiv5_ap_mem_read(ap, SAMD20_NVM_SERIAL(i))); + } + + gdb_outf("\n"); + + return true; +} +/** + * Returns the size (in bytes) of the current SAM D20's flash memory. + */ +static uint32_t samd20_flash_size(target *t) +{ + ADIv5_AP_t *ap = adiv5_target_ap(t); + + /* Read the Device ID */ + uint32_t did = adiv5_ap_mem_read(ap, SAMD20_DSU_DID); + + /* Mask off the device select bits */ + uint8_t devsel = did & SAMD20_DID_DEVSEL_MASK; + + /* Shift the maximum flash size (256KB) down as appropriate */ + return (0x40000 >> (devsel % 5)); +} +/** + * Runs the Memory Built In Self Test (MBIST) + */ +static bool samd20_cmd_mbist(target *t) +{ + ADIv5_AP_t *ap = adiv5_target_ap(t); + + /* Write the memory parameters to the DSU */ + adiv5_ap_mem_write(ap, SAMD20_DSU_ADDRESS, 0); + adiv5_ap_mem_write(ap, SAMD20_DSU_LENGTH, samd20_flash_size(t)); + + /* Clear the fail bit */ + adiv5_ap_mem_write(ap, SAMD20_DSU_CTRLSTAT, SAMD20_STATUSA_FAIL); + + /* Write the MBIST command */ + adiv5_ap_mem_write(ap, SAMD20_DSU_CTRLSTAT, SAMD20_CTRL_MBIST); + + /* Poll for DSU Ready */ + while ((adiv5_ap_mem_read(ap, SAMD20_DSU_CTRLSTAT) & SAMD20_STATUSA_DONE) == 0) + if(target_check_error(t)) + return false; + + /* Test the fail bit in Status A */ + if (adiv5_ap_mem_read(ap, SAMD20_DSU_CTRLSTAT) & SAMD20_STATUSA_FAIL) { + gdb_outf("MBIST Fail @ 0x%08x\n", + adiv5_ap_mem_read(ap, SAMD20_DSU_ADDRESS)); + } else { + gdb_outf("MBIST Passed!\n"); + } + + return true; +} -- cgit v1.2.3 From 02812b6bf1b9caf7123c436749c020f30bd9edc2 Mon Sep 17 00:00:00 2001 From: Richard Eoin Meadows Date: Thu, 3 Jul 2014 22:39:01 +0100 Subject: Added notes about the datasheet and NVMCTRL Security Bit --- src/samd20.c | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'src') diff --git a/src/samd20.c b/src/samd20.c index e646a00..93e8be9 100644 --- a/src/samd20.c +++ b/src/samd20.c @@ -21,6 +21,13 @@ * detecting the device, providing the XML memory map and Flash memory * programming. */ +/* Refer to the SAM D20 Datasheet: + * http://www.atmel.com/Images/Atmel-42129-SAM-D20_Datasheet.pdf + * particularly Sections 12. DSU and 20. NVMCTRL + */ +/* TODO: Support for the NVMCTRL Security Bit. If this is set then the + * device will probably not even be detected. + */ #include #include -- cgit v1.2.3 From e75798f201a0e4e566f09066c96b0637addc23cb Mon Sep 17 00:00:00 2001 From: Richard Eoin Meadows Date: Sun, 6 Jul 2014 17:31:49 +0100 Subject: Optimised flash write, programming speed is now approx. 2x faster --- src/samd20.c | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/samd20.c b/src/samd20.c index 93e8be9..f8fc119 100644 --- a/src/samd20.c +++ b/src/samd20.c @@ -353,9 +353,6 @@ static int samd20_flash_erase(struct target_s *target, uint32_t addr, int len) addr &= ~(SAMD20_ROW_SIZE - 1); len &= ~(SAMD20_ROW_SIZE - 1); - - - while (len) { /* Write address of first word in row to erase it */ /* Must be shifted right for 16-bit address, see Datasheet §20.8.8 Address */ @@ -414,10 +411,16 @@ static int samd20_flash_write(struct target_s *target, uint32_t dest, end_of_this_page = page + (SAMD20_PAGE_SIZE - 4); if (addr > page || (page == last_page && end < end_of_this_page)) { + /* Setup write */ + adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw | + ADIV5_AP_CSW_SIZE_WORD | ADIV5_AP_CSW_ADDRINC_SINGLE); + adiv5_ap_write(ap, ADIV5_AP_TAR, addr); + adiv5_dp_write(ap->dp, ADIV5_DP_SELECT, + ((uint32_t)ap->apsel << 24)|(ADIV5_AP_DRW & 0xF0)); /* Partial, manual page write */ for (; addr <= MINIMUM(end, end_of_this_page); addr += 4, i++) { - adiv5_ap_mem_write(ap, addr, data[i]); + adiv5_dp_write_ap(ap->dp, ADIV5_AP_DRW, data[i]); } /* Unlock */ @@ -433,9 +436,16 @@ static int samd20_flash_write(struct target_s *target, uint32_t dest, /* Unlock */ samd20_unlock_current_address(target); + /* Set up write */ + adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw | + ADIV5_AP_CSW_SIZE_WORD | ADIV5_AP_CSW_ADDRINC_SINGLE); + adiv5_ap_write(ap, ADIV5_AP_TAR, addr); + adiv5_dp_write(ap->dp, ADIV5_DP_SELECT, + ((uint32_t)ap->apsel << 24)|(ADIV5_AP_DRW & 0xF0)); + /* Full, automatic page write */ for (; addr < page + SAMD20_PAGE_SIZE; addr += 4, i++) { - adiv5_ap_mem_write(ap, addr, data[i]); + adiv5_dp_write_ap(ap->dp, ADIV5_AP_DRW, data[i]); } } -- cgit v1.2.3 From 2a444ab1fba19ab21a25f61be3ff10005775334a Mon Sep 17 00:00:00 2001 From: Richard Eoin Meadows Date: Fri, 22 Aug 2014 21:47:47 +0100 Subject: Fixed SAM D20 support with reset attached. monitor connect_srst enable can be used to connect to targets that re-use the SWCLK pin --- src/samd20.c | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/samd20.c b/src/samd20.c index f8fc119..bdb2ba6 100644 --- a/src/samd20.c +++ b/src/samd20.c @@ -235,8 +235,21 @@ samd20_reset(struct target_s *target) { ADIv5_AP_t *ap = adiv5_target_ap(target); - jtagtap_srst(true); - jtagtap_srst(false); + /** + * SRST is not asserted here as it appears to reset the adiv5 + * logic, meaning that subsequent adiv5_* calls PLATFORM_FATAL_ERROR. + * + * This is ok as normally you can just connect the debugger and go, + * but if that's not possible (protection or SWCLK being used for + * something else) then having SWCLK low on reset should get you + * debug access (cold-plugging). TODO: Confirm this + * + * See the SAM D20 datasheet §12.6 Debug Operation for more + * details. + * + * jtagtap_srst(true); + * jtagtap_srst(false); + */ /* Read DHCSR here to clear S_RESET_ST bit before reset */ adiv5_ap_mem_read(ap, CORTEXM_DHCSR); @@ -309,13 +322,17 @@ bool samd20_probe(struct target_s *target) target->flash_write = samd20_flash_write; target_add_commands(target, samd20_cmd_list, "SAMD20"); - /* Release the target from extended reset to make attach possible */ - if (adiv5_ap_mem_read(ap, SAMD20_DSU_CTRLSTAT) & - SAMD20_STATUSA_CRSTEXT) { - - /* Write bit to clear from extended reset */ - adiv5_ap_mem_write(ap, SAMD20_DSU_CTRLSTAT, - SAMD20_STATUSA_CRSTEXT); + /* If we're not in reset here */ + if (!connect_assert_srst) { + /* We'll have to release the target from + * extended reset to make attach possible */ + if (adiv5_ap_mem_read(ap, SAMD20_DSU_CTRLSTAT) & + SAMD20_STATUSA_CRSTEXT) { + + /* Write bit to clear from extended reset */ + adiv5_ap_mem_write(ap, SAMD20_DSU_CTRLSTAT, + SAMD20_STATUSA_CRSTEXT); + } } return true; -- cgit v1.2.3 From 39a0b064afd6e7fdc89d2d5c3a7e1b6f4c94b320 Mon Sep 17 00:00:00 2001 From: Richard Eoin Meadows Date: Fri, 22 Aug 2014 21:56:35 +0100 Subject: Use external access DSU range --- src/samd20.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/samd20.c b/src/samd20.c index bdb2ba6..bad52b9 100644 --- a/src/samd20.c +++ b/src/samd20.c @@ -110,10 +110,11 @@ static const char samd20_xml_memory_map[] = "" /* Device Service Unit (DSU) Registers */ #define SAMD20_DSU 0x41002000 -#define SAMD20_DSU_CTRLSTAT (SAMD20_DSU + 0x0) -#define SAMD20_DSU_ADDRESS (SAMD20_DSU + 0x4) -#define SAMD20_DSU_LENGTH (SAMD20_DSU + 0x8) -#define SAMD20_DSU_DID (SAMD20_DSU + 0x018) +#define SAMD20_DSU_EXT_ACCESS (SAMD20_DSU + 0x100) +#define SAMD20_DSU_CTRLSTAT (SAMD20_DSU_EXT_ACCESS + 0x0) +#define SAMD20_DSU_ADDRESS (SAMD20_DSU_EXT_ACCESS + 0x4) +#define SAMD20_DSU_LENGTH (SAMD20_DSU_EXT_ACCESS + 0x8) +#define SAMD20_DSU_DID (SAMD20_DSU_EXT_ACCESS + 0x018) #define SAMD20_DSU_PID(n) (SAMD20_DSU + 0x1FE0 + \ (0x4 * (n % 4)) - (0x10 * (n / 4))) #define SAMD20_DSU_CID(n) (SAMD20_DSU + 0x1FF0 + \ -- cgit v1.2.3 From f4474557d03581a1df5cbab9deff48799b32ddfb Mon Sep 17 00:00:00 2001 From: Richard Eoin Meadows Date: Fri, 22 Aug 2014 22:15:20 +0100 Subject: SAM D20 MBIST shouldn't fail silently --- src/samd20.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/samd20.c b/src/samd20.c index bad52b9..2a9fc67 100644 --- a/src/samd20.c +++ b/src/samd20.c @@ -124,7 +124,9 @@ static const char samd20_xml_memory_map[] = "" #define SAMD20_CTRL_CHIP_ERASE (1 << 4) #define SAMD20_CTRL_MBIST (1 << 3) #define SAMD20_CTRL_CRC (1 << 2) +#define SAMD20_STATUSA_PERR (1 << 12) #define SAMD20_STATUSA_FAIL (1 << 11) +#define SAMD20_STATUSA_BERR (1 << 10) #define SAMD20_STATUSA_CRSTEXT (1 << 9) #define SAMD20_STATUSA_DONE (1 << 8) @@ -605,12 +607,20 @@ static bool samd20_cmd_mbist(target *t) adiv5_ap_mem_write(ap, SAMD20_DSU_CTRLSTAT, SAMD20_CTRL_MBIST); /* Poll for DSU Ready */ - while ((adiv5_ap_mem_read(ap, SAMD20_DSU_CTRLSTAT) & SAMD20_STATUSA_DONE) == 0) + uint32_t status; + while (((status = adiv5_ap_mem_read(ap, SAMD20_DSU_CTRLSTAT)) & + (SAMD20_STATUSA_DONE | SAMD20_STATUSA_PERR | SAMD20_STATUSA_FAIL)) == 0) if(target_check_error(t)) return false; + /* Test the protection error bit in Status A */ + if (status & SAMD20_STATUSA_PERR) { + gdb_outf("MBIST not run due to protection error.\n") + return true; + } + /* Test the fail bit in Status A */ - if (adiv5_ap_mem_read(ap, SAMD20_DSU_CTRLSTAT) & SAMD20_STATUSA_FAIL) { + if (status & SAMD20_STATUSA_FAIL) { gdb_outf("MBIST Fail @ 0x%08x\n", adiv5_ap_mem_read(ap, SAMD20_DSU_ADDRESS)); } else { -- cgit v1.2.3 From f4e20d0d04f1e250ac93acf5bfc02fb20e33ee61 Mon Sep 17 00:00:00 2001 From: Richard Eoin Meadows Date: Fri, 22 Aug 2014 22:52:24 +0100 Subject: Ooops - Semicolon from last commit :-) --- src/samd20.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/samd20.c b/src/samd20.c index 2a9fc67..73baf6f 100644 --- a/src/samd20.c +++ b/src/samd20.c @@ -615,7 +615,7 @@ static bool samd20_cmd_mbist(target *t) /* Test the protection error bit in Status A */ if (status & SAMD20_STATUSA_PERR) { - gdb_outf("MBIST not run due to protection error.\n") + gdb_outf("MBIST not run due to protection error.\n"); return true; } -- cgit v1.2.3 From 091389b982477bb96624b51f59930f304813bca8 Mon Sep 17 00:00:00 2001 From: Richard Eoin Meadows Date: Sun, 24 Aug 2014 15:25:59 +0100 Subject: SAMD20 prints die revision --- src/samd20.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/samd20.c b/src/samd20.c index 73baf6f..fec0180 100644 --- a/src/samd20.c +++ b/src/samd20.c @@ -134,6 +134,9 @@ static const char samd20_xml_memory_map[] = "" #define SAMD20_DID_MASK 0xFFBF0000 #define SAMD20_DID_CONST_VALUE 0x10000000 #define SAMD20_DID_DEVSEL_MASK 0x0F +#define SAMD20_DID_DEVSEL_POS 0 +#define SAMD20_DID_REVISION_MASK 0x0F +#define SAMD20_DID_REVISION_POS 8 /* Peripheral ID */ #define SAMD20_PID_MASK 0x00F7FFFF @@ -299,7 +302,10 @@ bool samd20_probe(struct target_s *target) /* If the Device ID matches */ if ((did & SAMD20_DID_MASK) == SAMD20_DID_CONST_VALUE) { - uint8_t devsel = did & SAMD20_DID_DEVSEL_MASK; + uint8_t devsel = (did >> SAMD20_DID_DEVSEL_POS) + & SAMD20_DID_DEVSEL_MASK; + uint8_t revision = (did >> SAMD20_DID_REVISION_POS) + & SAMD20_DID_REVISION_MASK; /* Pin Variant */ char pin_variant; @@ -313,9 +319,12 @@ bool samd20_probe(struct target_s *target) /* Mem Variant */ uint8_t mem_variant = 18 - (devsel % 5); + /* Revision */ + char revision_variant = 'A' + revision; + /* Part String */ - sprintf(variant_string, "Atmel SAMD20%c%dA", - pin_variant, mem_variant); + sprintf(variant_string, "Atmel SAMD20%c%dA (rev %c)", + pin_variant, mem_variant, revision_variant); /* Setup Target */ target->driver = variant_string; -- cgit v1.2.3 From 9fda010b32a6d1ffbfaaae98f63470d8bce33c0b Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Fri, 12 Sep 2014 12:24:43 +1200 Subject: Give up unwinding a fault if reading the stack fails. --- src/cortexm.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/cortexm.c b/src/cortexm.c index 1142394..8c2e54e 100644 --- a/src/cortexm.c +++ b/src/cortexm.c @@ -693,6 +693,8 @@ static int cortexm_fault_unwind(struct target_s *target) /* Read stack for pre-exception registers */ uint32_t sp = spsel ? regs[REG_PSP] : regs[REG_MSP]; target_mem_read_words(target, stack, sp, sizeof(stack)); + if (target_check_error(target)) + return 0; regs[REG_LR] = stack[5]; /* restore LR to pre-exception state */ regs[REG_PC] = stack[6]; /* restore PC to pre-exception state */ -- cgit v1.2.3 From c5abc9a0bdde15f168903911ea43a6df1c7650ca Mon Sep 17 00:00:00 2001 From: Allen Ibara Date: Tue, 9 Sep 2014 15:11:29 -0700 Subject: LPC43XX: Attempt to handle case of running WDT. If the WDT is running, it may reset while we are trying to flash. Since we can't disable it, we set a long period and attempt to pet it before each IAP call. --- src/lpc43xx.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 48 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/lpc43xx.c b/src/lpc43xx.c index 0376ecf..a739878 100644 --- a/src/lpc43xx.c +++ b/src/lpc43xx.c @@ -37,6 +37,12 @@ #define LPC43XX_ETBAHB_SRAM_BASE 0x2000C000 #define LPC43XX_ETBAHB_SRAM_SIZE (16*1024) +#define LPC43XX_WDT_MODE 0x40080000 +#define LPC43XX_WDT_CNT 0x40080004 +#define LPC43XX_WDT_FEED 0x40080008 +#define LPC43XX_WDT_PERIOD_MAX 0xFFFFFF +#define LPC43XX_WDT_PROTECT (1 << 4) + #define IAP_RAM_SIZE LPC43XX_ETBAHB_SRAM_SIZE #define IAP_RAM_BASE LPC43XX_ETBAHB_SRAM_BASE @@ -126,6 +132,8 @@ static int lpc43xx_flash_erase(struct target_s *target, uint32_t addr, int len); static int lpc43xx_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, int len); static void lpc43xx_set_internal_clock(struct target_s *target); +static void lpc43xx_wdt_set_period(struct target_s *target); +static void lpc43xx_wdt_pet(struct target_s *target); const struct command_s lpc43xx_cmd_list[] = { {"erase_mass", lpc43xx_cmd_erase, "Erase entire flash memory"}, @@ -264,11 +272,14 @@ static bool lpc43xx_cmd_erase(target *target, int argc, const char *argv[]) static int lpc43xx_flash_init(struct target_s *target) { - struct flash_program flash_pgm; + /* Deal with WDT */ + lpc43xx_wdt_set_period(target); /* Force internal clock */ lpc43xx_set_internal_clock(target); + struct flash_program flash_pgm; + /* Initialize flash IAP */ flash_pgm.p.command = IAP_CMD_INIT; flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS; @@ -327,6 +338,9 @@ static void lpc43xx_iap_call(struct target_s *target, struct flash_param *param, uint32_t regs[target->regs_size / sizeof(uint32_t)]; uint32_t iap_entry; + /* Pet WDT before each IAP call, if it is on */ + lpc43xx_wdt_pet(target); + target_mem_read_words(target, &iap_entry, IAP_ENTRYPOINT_LOCATION, sizeof(iap_entry)); /* fill out the remainder of the parameters and copy the structure to RAM */ @@ -524,3 +538,36 @@ static bool lpc43xx_cmd_mkboot(target *target, int argc, const char *argv[]) return true; } +static void lpc43xx_wdt_set_period(struct target_s *target) +{ + uint32_t wdt_mode = 0; + /* Check if WDT is on */ + target_mem_read_words(target, &wdt_mode, LPC43XX_WDT_MODE, sizeof(wdt_mode)); + + /* If WDT on, we can't disable it, but we may be able to set a long period */ + if (wdt_mode && !(wdt_mode & LPC43XX_WDT_PROTECT)) + { + const uint32_t wdt_period = LPC43XX_WDT_PERIOD_MAX; + + + target_mem_write_words(target, LPC43XX_WDT_CNT, &wdt_period, sizeof(wdt_period)); + } +} + +static void lpc43xx_wdt_pet(struct target_s *target) +{ + uint32_t wdt_mode = 0; + /* Check if WDT is on */ + target_mem_read_words(target, &wdt_mode, LPC43XX_WDT_MODE, sizeof(wdt_mode)); + + /* If WDT on, pet */ + if (wdt_mode) + { + const uint32_t feed1 = 0xAA;; + const uint32_t feed2 = 0x55;; + + + target_mem_write_words(target, LPC43XX_WDT_FEED, &feed1, sizeof(feed1)); + target_mem_write_words(target, LPC43XX_WDT_FEED, &feed2, sizeof(feed2)); + } +} -- cgit v1.2.3 From a5549d630c3c261e7d52cb245d945e54f011a3e7 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Thu, 16 Oct 2014 13:19:34 -0700 Subject: Whitespace cleanup. --- src/cortexm.c | 2 +- src/gdb_main.c | 2 +- src/platforms/f4discovery/platform.h | 39 ++++++++++--------- src/platforms/f4discovery/usbdfu.c | 6 +-- src/platforms/libftdi/swdptap.c | 9 +++-- src/platforms/native/platform.c | 26 ++++++------- src/platforms/native/platform.h | 58 ++++++++++++++-------------- src/platforms/native/usbdfu.c | 2 +- src/platforms/stlink/dfu_upgrade.c | 10 ++--- src/platforms/stlink/platform.c | 72 ++++++++++++++++++----------------- src/platforms/stlink/platform.h | 45 +++++++++++----------- src/platforms/stlink/usbdfu.c | 6 +-- src/platforms/stm32/cdcacm.c | 52 ++++++++++++------------- src/platforms/stm32/dfu_f4.c | 27 +++++++------ src/platforms/stm32/dfucore.c | 73 ++++++++++++++++++------------------ src/platforms/stm32/gdb_if.c | 44 +++++++++++----------- src/platforms/swlink/platform.c | 26 ++++++------- src/platforms/swlink/platform.h | 45 +++++++++++----------- src/platforms/swlink/usbdfu.c | 20 +++++----- 19 files changed, 287 insertions(+), 277 deletions(-) (limited to 'src') diff --git a/src/cortexm.c b/src/cortexm.c index 8c2e54e..3ac960c 100644 --- a/src/cortexm.c +++ b/src/cortexm.c @@ -970,7 +970,7 @@ static int cortexm_hostio_request(target *t) case SYS_OPEN:{ /* open */ /* Translate stupid fopen modes to open flags. * See DUI0471C, Table 8-3 */ - const uint32_t flags[] = { + const uint32_t flags[] = { FILEIO_O_RDONLY, /* r, rb */ FILEIO_O_RDWR, /* r+, r+b */ FILEIO_O_WRONLY | FILEIO_O_CREAT | FILEIO_O_TRUNC,/*w*/ diff --git a/src/gdb_main.c b/src/gdb_main.c index bd27d48..c99ebac 100644 --- a/src/gdb_main.c +++ b/src/gdb_main.c @@ -217,7 +217,7 @@ gdb_main(void) break; case 0x04: - case 'D': /* GDB 'detach' command. */ + case 'D': /* GDB 'detach' command. */ if(cur_target) target_detach(cur_target); last_target = cur_target; diff --git a/src/platforms/f4discovery/platform.h b/src/platforms/f4discovery/platform.h index bbf01e1..210ba62 100644 --- a/src/platforms/f4discovery/platform.h +++ b/src/platforms/f4discovery/platform.h @@ -38,10 +38,10 @@ #define INLINE_GPIO #define CDCACM_PACKET_SIZE 64 #define PLATFORM_HAS_TRACESWO -#define BOARD_IDENT "Black Magic Probe (F4Discovery), (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" -#define BOARD_IDENT_DFU "Black Magic (Upgrade) for F4Discovery, (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" -#define DFU_IDENT "Black Magic Firmware Upgrade (F4Discovery" -#define DFU_IFACE_STRING "@Internal Flash /0x08000000/1*016Ka,3*016Kg,1*064Kg,7*128Kg" +#define BOARD_IDENT "Black Magic Probe (F4Discovery), (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" +#define BOARD_IDENT_DFU "Black Magic (Upgrade) for F4Discovery, (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" +#define DFU_IDENT "Black Magic Firmware Upgrade (F4Discovery" +#define DFU_IFACE_STRING "@Internal Flash /0x08000000/1*016Ka,3*016Kg,1*064Kg,7*128Kg" extern usbd_device *usbdev; #define CDCACM_GDB_ENDPOINT 1 @@ -97,13 +97,16 @@ extern usbd_device *usbdev; #define LED_ERROR GPIO14 #define LED_BOOTLOADER GPIO15 -#define TMS_SET_MODE() gpio_mode_setup(TMS_PORT, GPIO_MODE_OUTPUT, \ - GPIO_PUPD_NONE, TMS_PIN); -#define SWDIO_MODE_FLOAT() gpio_mode_setup(SWDIO_PORT, GPIO_MODE_INPUT, \ - GPIO_PUPD_NONE, SWDIO_PIN); +#define TMS_SET_MODE() \ + gpio_mode_setup(TMS_PORT, GPIO_MODE_OUTPUT, \ + GPIO_PUPD_NONE, TMS_PIN); +#define SWDIO_MODE_FLOAT() \ + gpio_mode_setup(SWDIO_PORT, GPIO_MODE_INPUT, \ + GPIO_PUPD_NONE, SWDIO_PIN); -#define SWDIO_MODE_DRIVE() gpio_mode_setup(SWDIO_PORT, GPIO_MODE_OUTPUT, \ - GPIO_PUPD_NONE, SWDIO_PIN); +#define SWDIO_MODE_DRIVE() \ + gpio_mode_setup(SWDIO_PORT, GPIO_MODE_OUTPUT, \ + GPIO_PUPD_NONE, SWDIO_PIN); #define USB_DRIVER stm32f107_usb_driver @@ -121,7 +124,7 @@ extern usbd_device *usbdev; #define USBUSART USART3 #define USBUSART_CR1 USART3_CR1 #define USBUSART_IRQ NVIC_USART3_IRQ -#define USBUSART_CLK RCC_USART3 +#define USBUSART_CLK RCC_USART3 #define USBUSART_TX_PORT GPIOD #define USBUSART_TX_PIN GPIO8 #define USBUSART_RX_PORT GPIOD @@ -132,13 +135,13 @@ extern usbd_device *usbdev; #define USBUSART_TIM_IRQ NVIC_TIM4_IRQ #define USBUSART_TIM_ISR tim4_isr -#define UART_PIN_SETUP() do { \ - gpio_mode_setup(USBUSART_TX_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, \ - USBUSART_TX_PIN); \ - gpio_mode_setup(USBUSART_RX_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, \ - USBUSART_RX_PIN); \ - gpio_set_af(USBUSART_TX_PORT, GPIO_AF7, USBUSART_TX_PIN); \ - gpio_set_af(USBUSART_RX_PORT, GPIO_AF7, USBUSART_RX_PIN); \ +#define UART_PIN_SETUP() do { \ + gpio_mode_setup(USBUSART_TX_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, \ + USBUSART_TX_PIN); \ + gpio_mode_setup(USBUSART_RX_PORT, GPIO_MODE_AF, GPIO_PUPD_NONE, \ + USBUSART_RX_PIN); \ + gpio_set_af(USBUSART_TX_PORT, GPIO_AF7, USBUSART_TX_PIN); \ + gpio_set_af(USBUSART_RX_PORT, GPIO_AF7, USBUSART_RX_PIN); \ } while(0) #define TRACE_TIM TIM3 diff --git a/src/platforms/f4discovery/usbdfu.c b/src/platforms/f4discovery/usbdfu.c index b7af115..7070ade 100644 --- a/src/platforms/f4discovery/usbdfu.c +++ b/src/platforms/f4discovery/usbdfu.c @@ -27,7 +27,7 @@ void dfu_detach(void) { - /* USB device must detach, we just reset... */ + /* USB device must detach, we just reset... */ scb_reset_system(); } @@ -40,8 +40,8 @@ int main(void) dfu_protect_enable(); - /* Set up clock*/ - rcc_clock_setup_hse_3v3(&hse_8mhz_3v3[CLOCK_3V3_168MHZ]); + /* Set up clock*/ + rcc_clock_setup_hse_3v3(&hse_8mhz_3v3[CLOCK_3V3_168MHZ]); systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); systick_set_reload(2100000); diff --git a/src/platforms/libftdi/swdptap.c b/src/platforms/libftdi/swdptap.c index cd3582b..ef350de 100644 --- a/src/platforms/libftdi/swdptap.c +++ b/src/platforms/libftdi/swdptap.c @@ -60,16 +60,17 @@ int swdptap_init(void) void swdptap_reset(void) { - swdptap_turnaround(0); - /* 50 clocks with TMS high */ - for(int i = 0; i < 50; i++) swdptap_bit_out(1); + swdptap_turnaround(0); + /* 50 clocks with TMS high */ + for(int i = 0; i < 50; i++) + swdptap_bit_out(1); } static void swdptap_turnaround(uint8_t dir) { static uint8_t olddir = 0; - //DEBUG("%s", dir ? "\n-> ":"\n<- "); + /*DEBUG("%s", dir ? "\n-> ":"\n<- ");*/ platform_buffer_flush(); if(dir == olddir) return; diff --git a/src/platforms/native/platform.c b/src/platforms/native/platform.c index 66b84fa..2789d8c 100644 --- a/src/platforms/native/platform.c +++ b/src/platforms/native/platform.c @@ -110,14 +110,13 @@ int platform_init(void) : GPIO_CNF_OUTPUT_OPENDRAIN), SRST_PIN); - /* Enable internal pull-up on PWR_BR so that we don't drive - TPWR locally or inadvertently supply power to the target. */ - if (platform_hwversion () > 0) { - gpio_set (PWR_BR_PORT, PWR_BR_PIN); - gpio_set_mode(PWR_BR_PORT, GPIO_MODE_INPUT, - GPIO_CNF_INPUT_PULL_UPDOWN, - PWR_BR_PIN); - } + /* Enable internal pull-up on PWR_BR so that we don't drive + TPWR locally or inadvertently supply power to the target. */ + if (platform_hwversion () > 0) { + gpio_set (PWR_BR_PORT, PWR_BR_PIN); + gpio_set_mode(PWR_BR_PORT, GPIO_MODE_INPUT, + GPIO_CNF_INPUT_PULL_UPDOWN, PWR_BR_PIN); + } /* Setup heartbeat timer */ systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); @@ -134,15 +133,16 @@ int platform_init(void) gpio_set_mode(GPIOB, GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, GPIO0); } - - SCB_VTOR = 0x2000; // Relocate interrupt vector table here + /* Relocate interrupt vector table here */ + SCB_VTOR = 0x2000; cdcacm_init(); usbuart_init(); - // Set recovery point + /* Set recovery point */ if (setjmp(fatal_error_jmpbuf)) { - return 0; // Do nothing on failure + /* Do nothing on failure */ + return 0; } jtag_scan(NULL); @@ -162,7 +162,7 @@ bool platform_target_get_power(void) { if (platform_hwversion() > 0) { return gpio_get(PWR_BR_PORT, PWR_BR_PIN); } - return 1; // 1 = Unpowered + return 1; /* 1 = Unpowered */ } void platform_target_set_power(bool power) { diff --git a/src/platforms/native/platform.h b/src/platforms/native/platform.h index 3bbcd17..81a2a4b 100644 --- a/src/platforms/native/platform.h +++ b/src/platforms/native/platform.h @@ -41,11 +41,11 @@ #define PLATFORM_HAS_TRACESWO #define PLATFORM_HAS_POWER_SWITCH #define BOARD_IDENT "Black Magic Probe" -#define BOARD_IDENT_DFU "Black Magic Probe (Upgrade)" -#define BOARD_IDENT_UPD "Black Magic Probe (DFU Upgrade)" +#define BOARD_IDENT_DFU "Black Magic Probe (Upgrade)" +#define BOARD_IDENT_UPD "Black Magic Probe (DFU Upgrade)" #define DFU_IDENT "Black Magic Firmware Upgrade" -#define DFU_IFACE_STRING "@Internal Flash /0x08000000/8*001Ka,120*001Kg" -#define UPD_IFACE_STRING "@Internal Flash /0x08000000/8*001Kg" +#define DFU_IFACE_STRING "@Internal Flash /0x08000000/8*001Ka,120*001Kg" +#define UPD_IFACE_STRING "@Internal Flash /0x08000000/8*001Kg" extern usbd_device *usbdev; #define CDCACM_GDB_ENDPOINT 1 @@ -109,35 +109,35 @@ extern usbd_device *usbdev; #define LED_IDLE_RUN GPIO10 #define LED_ERROR GPIO11 -#define TMS_SET_MODE() \ - gpio_set_mode(TMS_PORT, GPIO_MODE_OUTPUT_50_MHZ, \ - GPIO_CNF_OUTPUT_PUSHPULL, TMS_PIN); -#define SWDIO_MODE_FLOAT() \ - gpio_set_mode(SWDIO_PORT, GPIO_MODE_INPUT, \ - GPIO_CNF_INPUT_FLOAT, SWDIO_PIN); -#define SWDIO_MODE_DRIVE() \ - gpio_set_mode(SWDIO_PORT, GPIO_MODE_OUTPUT_50_MHZ, \ - GPIO_CNF_OUTPUT_PUSHPULL, SWDIO_PIN); - -#define UART_PIN_SETUP() \ - gpio_set_mode(USBUSART_PORT, GPIO_MODE_OUTPUT_2_MHZ, \ - GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, USBUSART_TX_PIN); - -#define SRST_SET_VAL(x) \ - platform_srst_set_val(x) - -#define USB_DRIVER stm32f103_usb_driver -#define USB_IRQ NVIC_USB_LP_CAN_RX0_IRQ -#define USB_ISR usb_lp_can_rx0_isr +#define TMS_SET_MODE() \ + gpio_set_mode(TMS_PORT, GPIO_MODE_OUTPUT_50_MHZ, \ + GPIO_CNF_OUTPUT_PUSHPULL, TMS_PIN); +#define SWDIO_MODE_FLOAT() \ + gpio_set_mode(SWDIO_PORT, GPIO_MODE_INPUT, \ + GPIO_CNF_INPUT_FLOAT, SWDIO_PIN); +#define SWDIO_MODE_DRIVE() \ + gpio_set_mode(SWDIO_PORT, GPIO_MODE_OUTPUT_50_MHZ, \ + GPIO_CNF_OUTPUT_PUSHPULL, SWDIO_PIN); + +#define UART_PIN_SETUP() \ + gpio_set_mode(USBUSART_PORT, GPIO_MODE_OUTPUT_2_MHZ, \ + GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, USBUSART_TX_PIN); + +#define SRST_SET_VAL(x) \ + platform_srst_set_val(x) + +#define USB_DRIVER stm32f103_usb_driver +#define USB_IRQ NVIC_USB_LP_CAN_RX0_IRQ +#define USB_ISR usb_lp_can_rx0_isr /* Interrupt priorities. Low numbers are high priority. * For now USART1 preempts USB which may spin while buffer is drained. * TIM3 is used for traceswo capture and must be highest priority. */ -#define IRQ_PRI_USB (2 << 4) -#define IRQ_PRI_USBUSART (1 << 4) -#define IRQ_PRI_USBUSART_TIM (3 << 4) -#define IRQ_PRI_USB_VBUS (14 << 4) -#define IRQ_PRI_TRACE (0 << 4) +#define IRQ_PRI_USB (2 << 4) +#define IRQ_PRI_USBUSART (1 << 4) +#define IRQ_PRI_USBUSART_TIM (3 << 4) +#define IRQ_PRI_USB_VBUS (14 << 4) +#define IRQ_PRI_TRACE (0 << 4) #define USBUSART USART1 #define USBUSART_CR1 USART1_CR1 diff --git a/src/platforms/native/usbdfu.c b/src/platforms/native/usbdfu.c index 3aac079..39643da 100644 --- a/src/platforms/native/usbdfu.c +++ b/src/platforms/native/usbdfu.c @@ -29,7 +29,7 @@ uint32_t app_address = 0x08002000; void dfu_detach(void) { - /* USB device must detach, we just reset... */ + /* USB device must detach, we just reset... */ scb_reset_system(); } diff --git a/src/platforms/stlink/dfu_upgrade.c b/src/platforms/stlink/dfu_upgrade.c index b15117b..4a3648a 100644 --- a/src/platforms/stlink/dfu_upgrade.c +++ b/src/platforms/stlink/dfu_upgrade.c @@ -81,17 +81,17 @@ int main(void) rcc_clock_setup_in_hse_8mhz_out_72mhz(); - stlink_set_rev(); + stlink_set_rev(); systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); systick_set_reload(900000); - dfu_protect(UPD_MODE); + dfu_protect(UPD_MODE); - /* Handle USB disconnect/connect */ + /* Handle USB disconnect/connect */ /* Just in case: Disconnect USB cable by resetting USB Device - * and pulling USB_DP low - * Device will reconnect automatically as Pull-Up is hard wired*/ + * and pulling USB_DP low + * Device will reconnect automatically as Pull-Up is hard wired*/ rcc_periph_reset_pulse(RST_USB); rcc_periph_clock_enable(RCC_USB); rcc_periph_clock_enable(RCC_GPIOA); diff --git a/src/platforms/stlink/platform.c b/src/platforms/stlink/platform.c index cf2d954..494499c 100644 --- a/src/platforms/stlink/platform.c +++ b/src/platforms/stlink/platform.c @@ -49,22 +49,21 @@ uint16_t led_idle_run; int platform_hwversion(void) { static int hwversion = -1; - int i; + int i; if (hwversion == -1) { gpio_set_mode(GPIOC, GPIO_MODE_INPUT, - GPIO_CNF_INPUT_PULL_UPDOWN, - GPIO14 | GPIO13); + GPIO_CNF_INPUT_PULL_UPDOWN, GPIO14 | GPIO13); gpio_set(GPIOC, GPIO14 | GPIO13); - for (i = 0; i<10; i++) - hwversion = ~(gpio_get(GPIOC, GPIO14 | GPIO13) >> 13) & 3; - switch (hwversion) - { - case 0: - led_idle_run = GPIO8; - break; - default: - led_idle_run = GPIO9; - } + for (i = 0; i<10; i++) + hwversion = ~(gpio_get(GPIOC, GPIO14 | GPIO13) >> 13) & 3; + switch (hwversion) + { + case 0: + led_idle_run = GPIO8; + break; + default: + led_idle_run = GPIO9; + } } return hwversion; } @@ -82,30 +81,30 @@ int platform_init(void) rcc_periph_clock_enable(RCC_CRC); /* On Rev 1 unconditionally activate MCO on PORTA8 with HSE - * platform_hwversion() also needed to initialize led_idle_run! - */ - if (platform_hwversion() == 1) - { - RCC_CFGR &= ~( 0xf<< 24); - RCC_CFGR |= (RCC_CFGR_MCO_HSECLK << 24); - gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, - GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO8); - } + * platform_hwversion() also needed to initialize led_idle_run! + */ + if (platform_hwversion() == 1) + { + RCC_CFGR &= ~(0xf << 24); + RCC_CFGR |= (RCC_CFGR_MCO_HSECLK << 24); + gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_50_MHZ, + GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, GPIO8); + } /* Setup GPIO ports */ gpio_set_mode(TMS_PORT, GPIO_MODE_OUTPUT_50_MHZ, - GPIO_CNF_OUTPUT_PUSHPULL, TMS_PIN); + GPIO_CNF_OUTPUT_PUSHPULL, TMS_PIN); gpio_set_mode(TCK_PORT, GPIO_MODE_OUTPUT_50_MHZ, - GPIO_CNF_OUTPUT_PUSHPULL, TCK_PIN); + GPIO_CNF_OUTPUT_PUSHPULL, TCK_PIN); gpio_set_mode(TDI_PORT, GPIO_MODE_OUTPUT_50_MHZ, - GPIO_CNF_OUTPUT_PUSHPULL, TDI_PIN); + GPIO_CNF_OUTPUT_PUSHPULL, TDI_PIN); uint16_t srst_pin = platform_hwversion() == 0 ? - SRST_PIN_V1 : SRST_PIN_V2; + SRST_PIN_V1 : SRST_PIN_V2; gpio_set(SRST_PORT, srst_pin); gpio_set_mode(SRST_PORT, GPIO_MODE_OUTPUT_50_MHZ, - GPIO_CNF_OUTPUT_OPENDRAIN, srst_pin); + GPIO_CNF_OUTPUT_OPENDRAIN, srst_pin); gpio_set_mode(LED_PORT, GPIO_MODE_OUTPUT_2_MHZ, - GPIO_CNF_OUTPUT_PUSHPULL, led_idle_run); + GPIO_CNF_OUTPUT_PUSHPULL, led_idle_run); /* Setup heartbeat timer */ systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); @@ -117,13 +116,14 @@ int platform_init(void) usbuart_init(); - SCB_VTOR = 0x2000; // Relocate interrupt vector table here + SCB_VTOR = 0x2000; /* Relocate interrupt vector table here */ cdcacm_init(); - // Set recovery point + /* Set recovery point */ if (setjmp(fatal_error_jmpbuf)) { - return 0; // Do nothing on failure + /* Do nothing on failure */ + return 0; } jtag_scan(NULL); @@ -134,7 +134,7 @@ int platform_init(void) void platform_delay(uint32_t delay) { timeout_counter = delay; - while(timeout_counter); + while (timeout_counter); } void platform_srst_set_val(bool assert) @@ -177,7 +177,7 @@ void disconnect_usb(void) rcc_periph_clock_enable(RCC_GPIOA); gpio_clear(GPIOA, GPIO12); gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, - GPIO_CNF_OUTPUT_OPENDRAIN, GPIO12); + GPIO_CNF_OUTPUT_OPENDRAIN, GPIO12); } void assert_boot_pin(void) @@ -192,4 +192,8 @@ void assert_boot_pin(void) crl |= 0x80; GPIOA_CRL = crl; } -void setup_vbus_irq(void){}; + +void setup_vbus_irq(void) +{ +} + diff --git a/src/platforms/stlink/platform.h b/src/platforms/stlink/platform.h index 0780706..e56abd9 100644 --- a/src/platforms/stlink/platform.h +++ b/src/platforms/stlink/platform.h @@ -38,12 +38,12 @@ #define INLINE_GPIO #define CDCACM_PACKET_SIZE 64 -#define BOARD_IDENT "Black Magic Probe (STLINK), (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" -#define BOARD_IDENT_DFU "Black Magic (Upgrade) for STLink/Discovery, (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" -#define BOARD_IDENT_UPD "Black Magic (DFU Upgrade) for STLink/Discovery, (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" -#define DFU_IDENT "Black Magic Firmware Upgrade (STLINK)" -#define DFU_IFACE_STRING "@Internal Flash /0x08000000/8*001Ka,56*001Kg" -#define UPD_IFACE_STRING "@Internal Flash /0x08000000/8*001Kg" +#define BOARD_IDENT "Black Magic Probe (STLINK), (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" +#define BOARD_IDENT_DFU "Black Magic (Upgrade) for STLink/Discovery, (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" +#define BOARD_IDENT_UPD "Black Magic (DFU Upgrade) for STLink/Discovery, (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" +#define DFU_IDENT "Black Magic Firmware Upgrade (STLINK)" +#define DFU_IFACE_STRING "@Internal Flash /0x08000000/8*001Ka,56*001Kg" +#define UPD_IFACE_STRING "@Internal Flash /0x08000000/8*001Kg" extern usbd_device *usbdev; #define CDCACM_GDB_ENDPOINT 1 @@ -94,26 +94,26 @@ extern usbd_device *usbdev; #define LED_PORT_UART GPIOC #define LED_UART GPIO14 -#define TMS_SET_MODE() \ - gpio_set_mode(TMS_PORT, GPIO_MODE_OUTPUT_50_MHZ, \ - GPIO_CNF_OUTPUT_PUSHPULL, TMS_PIN); -#define SWDIO_MODE_FLOAT() \ - gpio_set_mode(SWDIO_PORT, GPIO_MODE_INPUT, \ - GPIO_CNF_INPUT_FLOAT, SWDIO_PIN); -#define SWDIO_MODE_DRIVE() \ - gpio_set_mode(SWDIO_PORT, GPIO_MODE_OUTPUT_50_MHZ, \ - GPIO_CNF_OUTPUT_PUSHPULL, SWDIO_PIN); +#define TMS_SET_MODE() \ + gpio_set_mode(TMS_PORT, GPIO_MODE_OUTPUT_50_MHZ, \ + GPIO_CNF_OUTPUT_PUSHPULL, TMS_PIN); +#define SWDIO_MODE_FLOAT() \ + gpio_set_mode(SWDIO_PORT, GPIO_MODE_INPUT, \ + GPIO_CNF_INPUT_FLOAT, SWDIO_PIN); +#define SWDIO_MODE_DRIVE() \ + gpio_set_mode(SWDIO_PORT, GPIO_MODE_OUTPUT_50_MHZ, \ + GPIO_CNF_OUTPUT_PUSHPULL, SWDIO_PIN); -#define UART_PIN_SETUP() \ - gpio_set_mode(USBUSART_PORT, GPIO_MODE_OUTPUT_2_MHZ, \ - GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, USBUSART_TX_PIN); +#define UART_PIN_SETUP() \ + gpio_set_mode(USBUSART_PORT, GPIO_MODE_OUTPUT_2_MHZ, \ + GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, USBUSART_TX_PIN); -#define SRST_SET_VAL(x) \ - platform_srst_set_val(x) +#define SRST_SET_VAL(x) \ + platform_srst_set_val(x) #define USB_DRIVER stm32f103_usb_driver -#define USB_IRQ NVIC_USB_LP_CAN_RX0_IRQ -#define USB_ISR usb_lp_can_rx0_isr +#define USB_IRQ NVIC_USB_LP_CAN_RX0_IRQ +#define USB_ISR usb_lp_can_rx0_isr /* Interrupt priorities. Low numbers are high priority. * For now USART2 preempts USB which may spin while buffer is drained. * TIM3 is used for traceswo capture and must be highest priority. @@ -209,3 +209,4 @@ static inline uint16_t _gpio_get(uint32_t gpioport, uint16_t gpios) void disconnect_usb(void); void assert_boot_pin(void); + diff --git a/src/platforms/stlink/usbdfu.c b/src/platforms/stlink/usbdfu.c index 843033b..b42ec20 100644 --- a/src/platforms/stlink/usbdfu.c +++ b/src/platforms/stlink/usbdfu.c @@ -106,10 +106,10 @@ int main(void) systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); systick_set_reload(900000); - /* Handle USB disconnect/connect */ + /* Handle USB disconnect/connect */ /* Just in case: Disconnect USB cable by resetting USB Device - * and pulling USB_DP low - * Device will reconnect automatically as Pull-Up is hard wired*/ + * and pulling USB_DP low + * Device will reconnect automatically as Pull-Up is hard wired*/ rcc_periph_reset_pulse(RST_USB); rcc_periph_clock_enable(RCC_USB); rcc_periph_clock_enable(RCC_GPIOA); diff --git a/src/platforms/stm32/cdcacm.c b/src/platforms/stm32/cdcacm.c index 010117f..ef7ff3b 100644 --- a/src/platforms/stm32/cdcacm.c +++ b/src/platforms/stm32/cdcacm.c @@ -51,20 +51,20 @@ static int cdcacm_gdb_dtr = 1; static const struct usb_device_descriptor dev = { - .bLength = USB_DT_DEVICE_SIZE, - .bDescriptorType = USB_DT_DEVICE, - .bcdUSB = 0x0200, - .bDeviceClass = 0xEF, /* Miscellaneous Device */ - .bDeviceSubClass = 2, /* Common Class */ - .bDeviceProtocol = 1, /* Interface Association */ - .bMaxPacketSize0 = 64, - .idVendor = 0x1D50, - .idProduct = 0x6018, - .bcdDevice = 0x0100, - .iManufacturer = 1, - .iProduct = 2, - .iSerialNumber = 3, - .bNumConfigurations = 1, + .bLength = USB_DT_DEVICE_SIZE, + .bDescriptorType = USB_DT_DEVICE, + .bcdUSB = 0x0200, + .bDeviceClass = 0xEF, /* Miscellaneous Device */ + .bDeviceSubClass = 2, /* Common Class */ + .bDeviceProtocol = 1, /* Interface Association */ + .bMaxPacketSize0 = 64, + .idVendor = 0x1D50, + .idProduct = 0x6018, + .bcdDevice = 0x0100, + .iManufacturer = 1, + .iProduct = 2, + .iSerialNumber = 3, + .bNumConfigurations = 1, }; /* This notification endpoint isn't implemented. According to CDC spec its @@ -412,7 +412,7 @@ static void dfu_detach_complete(usbd_device *dev, struct usb_setup_data *req) disconnect_usb(); /* Assert boot-request pin */ - assert_boot_pin(); + assert_boot_pin(); /* Reset core to enter bootloader */ scb_reset_core(); @@ -555,22 +555,22 @@ void USB_ISR(void) static char *get_dev_unique_id(char *s) { #if defined(STM32F4) - volatile uint32_t *unique_id_p = (volatile uint32_t *)0x1FFF7A10; + volatile uint32_t *unique_id_p = (volatile uint32_t *)0x1FFF7A10; #else - volatile uint32_t *unique_id_p = (volatile uint32_t *)0x1FFFF7E8; + volatile uint32_t *unique_id_p = (volatile uint32_t *)0x1FFFF7E8; #endif uint32_t unique_id = *unique_id_p + *(unique_id_p + 1) + *(unique_id_p + 2); - int i; - - /* Fetch serial number from chip's unique ID */ - for(i = 0; i < 8; i++) { - s[7-i] = ((unique_id >> (4*i)) & 0xF) + '0'; - } - for(i = 0; i < 8; i++) - if(s[i] > '9') - s[i] += 'A' - '9' - 1; + int i; + + /* Fetch serial number from chip's unique ID */ + for(i = 0; i < 8; i++) { + s[7-i] = ((unique_id >> (4*i)) & 0xF) + '0'; + } + for(i = 0; i < 8; i++) + if(s[i] > '9') + s[i] += 'A' - '9' - 1; s[8] = 0; return s; diff --git a/src/platforms/stm32/dfu_f4.c b/src/platforms/stm32/dfu_f4.c index 3d1e369..1065938 100644 --- a/src/platforms/stm32/dfu_f4.c +++ b/src/platforms/stm32/dfu_f4.c @@ -28,13 +28,17 @@ #include "usbdfu.h" -static uint32_t sector_addr[] = {0x8000000, 0x8004000, 0x8008000, 0x800c000, - 0x8010000, 0x8020000, 0x8040000, 0x8060000, - 0x8080000, 0x80a0000, 0x80c0000, 0x80e0000, - 0x8100000, 0}; -static uint16_t sector_erase_time[12]= {500, 500, 500, 500, - 1100, - 2600, 2600, 2600, 2600, 2600, 2600, 2600}; +static uint32_t sector_addr[] = { + 0x8000000, 0x8004000, 0x8008000, 0x800c000, + 0x8010000, 0x8020000, 0x8040000, 0x8060000, + 0x8080000, 0x80a0000, 0x80c0000, 0x80e0000, + 0x8100000, 0 +}; +static uint16_t sector_erase_time[12]= { + 500, 500, 500, 500, + 1100, 2600, 2600, 2600, + 2600, 2600, 2600, 2600 +}; static uint8_t sector_num = 0xff; /* Find the sector number for a given address*/ @@ -45,7 +49,7 @@ static void get_sector_num(uint32_t addr) if (addr < sector_addr[i+1]) break; i++; - } + } if (!sector_addr[i]) return; sector_num = i; @@ -61,9 +65,8 @@ void dfu_check_and_do_sector_erase(uint32_t addr) void dfu_flash_program_buffer(uint32_t baseaddr, void *buf, int len) { for(int i = 0; i < len; i += 4) - flash_program_word(baseaddr + i, - *(uint32_t*)(buf+i), - FLASH_PROGRAM_X32); + flash_program_word(baseaddr + i, *(uint32_t*)(buf+i), + FLASH_PROGRAM_X32); } uint32_t dfu_poll_timeout(uint8_t cmd, uint32_t addr, uint16_t blocknum) @@ -100,7 +103,7 @@ void dfu_jump_app_if_valid(void) SCB_VTOR = APP_ADDRESS & 0x1FFFFF; /* Max 2 MByte Flash*/ /* Initialise master stack pointer */ asm volatile ("msr msp, %0"::"g" - (*(volatile uint32_t*)APP_ADDRESS)); + (*(volatile uint32_t*)APP_ADDRESS)); /* Jump to application */ (*(void(**)())(APP_ADDRESS + 4))(); } diff --git a/src/platforms/stm32/dfucore.c b/src/platforms/stm32/dfucore.c index 85e5e87..77cef4e 100644 --- a/src/platforms/stm32/dfucore.c +++ b/src/platforms/stm32/dfucore.c @@ -50,20 +50,20 @@ static struct { } prog; const struct usb_device_descriptor dev = { - .bLength = USB_DT_DEVICE_SIZE, - .bDescriptorType = USB_DT_DEVICE, - .bcdUSB = 0x0200, - .bDeviceClass = 0, - .bDeviceSubClass = 0, - .bDeviceProtocol = 0, - .bMaxPacketSize0 = 64, - .idVendor = 0x1D50, - .idProduct = 0x6017, - .bcdDevice = 0x0100, - .iManufacturer = 1, - .iProduct = 2, - .iSerialNumber = 3, - .bNumConfigurations = 1, + .bLength = USB_DT_DEVICE_SIZE, + .bDescriptorType = USB_DT_DEVICE, + .bcdUSB = 0x0200, + .bDeviceClass = 0, + .bDeviceSubClass = 0, + .bDeviceProtocol = 0, + .bMaxPacketSize0 = 64, + .idVendor = 0x1D50, + .idProduct = 0x6017, + .bcdDevice = 0x0100, + .iManufacturer = 1, + .iProduct = 2, + .iSerialNumber = 3, + .bNumConfigurations = 1, }; const struct usb_dfu_descriptor dfu_function = { @@ -166,8 +166,7 @@ usbdfu_getstatus_complete(usbd_device *dev, struct usb_setup_data *req) flash_unlock(); if(prog.blocknum == 0) { uint32_t addr = get_le32(prog.buf + 1); - if (addr < app_address || - (addr >= max_address)) { + if ((addr < app_address) || (addr >= max_address)) { flash_lock(); usbd_ep_stall_set(dev, 0, 1); return; @@ -282,34 +281,34 @@ void dfu_main(void) static char *get_dev_unique_id(char *s) { #if defined(STM32F4) || defined(STM32F2) -#define UNIQUE_SERIAL_R 0x1FFF7A10 -#define FLASH_SIZE_R 0x1fff7A22 +# define UNIQUE_SERIAL_R 0x1FFF7A10 +# define FLASH_SIZE_R 0x1fff7A22 #elif defined(STM32F3) -#define UNIQUE_SERIAL_R 0x1FFFF7AC -#define FLASH_SIZE_R 0x1fff77cc +# define UNIQUE_SERIAL_R 0x1FFFF7AC +# define FLASH_SIZE_R 0x1fff77cc #elif defined(STM32L1) -#define UNIQUE_SERIAL_R 0x1ff80050 -#define FLASH_SIZE_R 0x1FF8004C +# define UNIQUE_SERIAL_R 0x1ff80050 +# define FLASH_SIZE_R 0x1FF8004C #else -#define UNIQUE_SERIAL_R 0x1FFFF7E8; -#define FLASH_SIZE_R 0x1ffff7e0 +# define UNIQUE_SERIAL_R 0x1FFFF7E8; +# define FLASH_SIZE_R 0x1ffff7e0 #endif - volatile uint32_t *unique_id_p = (volatile uint32_t *)UNIQUE_SERIAL_R; + volatile uint32_t *unique_id_p = (volatile uint32_t *)UNIQUE_SERIAL_R; uint32_t unique_id = *unique_id_p + *(unique_id_p + 1) + *(unique_id_p + 2); - int i; - - /* Calculated the upper flash limit from the exported data - in theparameter block*/ - max_address = (*(uint32_t *) FLASH_SIZE_R) <<10; - /* Fetch serial number from chip's unique ID */ - for(i = 0; i < 8; i++) { - s[7-i] = ((unique_id >> (4*i)) & 0xF) + '0'; - } - for(i = 0; i < 8; i++) - if(s[i] > '9') - s[i] += 'A' - '9' - 1; + int i; + + /* Calculated the upper flash limit from the exported data + in theparameter block*/ + max_address = (*(uint32_t *) FLASH_SIZE_R) <<10; + /* Fetch serial number from chip's unique ID */ + for(i = 0; i < 8; i++) { + s[7-i] = ((unique_id >> (4*i)) & 0xF) + '0'; + } + for(i = 0; i < 8; i++) + if(s[i] > '9') + s[i] += 'A' - '9' - 1; s[8] = 0; return s; diff --git a/src/platforms/stm32/gdb_if.c b/src/platforms/stm32/gdb_if.c index 28bc4c8..482effe 100644 --- a/src/platforms/stm32/gdb_if.c +++ b/src/platforms/stm32/gdb_if.c @@ -67,8 +67,8 @@ void gdb_usb_out_cb(usbd_device *dev, uint8_t ep) { (void)ep; usbd_ep_nak_set(dev, CDCACM_GDB_ENDPOINT, 1); - count_new = usbd_ep_read_packet(dev, CDCACM_GDB_ENDPOINT, - double_buffer_out, CDCACM_PACKET_SIZE); + count_new = usbd_ep_read_packet(dev, CDCACM_GDB_ENDPOINT, + double_buffer_out, CDCACM_PACKET_SIZE); if(!count_new) { usbd_ep_nak_set(dev, CDCACM_GDB_ENDPOINT, 0); } @@ -77,19 +77,19 @@ void gdb_usb_out_cb(usbd_device *dev, uint8_t ep) unsigned char gdb_if_getchar(void) { - while(!(out_ptr < count_out)) { + while (!(out_ptr < count_out)) { /* Detach if port closed */ - if(!cdcacm_get_dtr()) + if (!cdcacm_get_dtr()) return 0x04; - while(cdcacm_get_config() != 1); - if (count_new) { - memcpy(buffer_out, double_buffer_out,count_new); - count_out = count_new; - count_new = 0; - out_ptr = 0; - usbd_ep_nak_set(usbdev, CDCACM_GDB_ENDPOINT, 0); - } + while (cdcacm_get_config() != 1); + if (count_new) { + memcpy(buffer_out, double_buffer_out,count_new); + count_out = count_new; + count_new = 0; + out_ptr = 0; + usbd_ep_nak_set(usbdev, CDCACM_GDB_ENDPOINT, 0); + } } return buffer_out[out_ptr++]; @@ -99,19 +99,19 @@ unsigned char gdb_if_getchar_to(int timeout) { timeout_counter = timeout/100; - if(!(out_ptr < count_out)) do { + if (!(out_ptr < count_out)) do { /* Detach if port closed */ - if(!cdcacm_get_dtr()) + if (!cdcacm_get_dtr()) return 0x04; - while(cdcacm_get_config() != 1); - if (count_new) { - memcpy(buffer_out, double_buffer_out,count_new); - count_out = count_new; - count_new = 0; - out_ptr = 0; - usbd_ep_nak_set(usbdev, CDCACM_GDB_ENDPOINT, 0); - } + while (cdcacm_get_config() != 1); + if (count_new) { + memcpy(buffer_out, double_buffer_out,count_new); + count_out = count_new; + count_new = 0; + out_ptr = 0; + usbd_ep_nak_set(usbdev, CDCACM_GDB_ENDPOINT, 0); + } } while(timeout_counter && !(out_ptr < count_out)); if(out_ptr < count_out) diff --git a/src/platforms/swlink/platform.c b/src/platforms/swlink/platform.c index 74f8691..7b7446a 100644 --- a/src/platforms/swlink/platform.c +++ b/src/platforms/swlink/platform.c @@ -54,10 +54,10 @@ int platform_init(void) rcc_periph_clock_enable(RCC_CRC); /* Unmap JTAG Pins so we can reuse as GPIO */ - data = AFIO_MAPR; - data &= ~AFIO_MAPR_SWJ_MASK; - data |= AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_OFF; - AFIO_MAPR = data; + data = AFIO_MAPR; + data &= ~AFIO_MAPR_SWJ_MASK; + data |= AFIO_MAPR_SWJ_CFG_JTAG_OFF_SW_OFF; + AFIO_MAPR = data; /* Setup JTAG GPIO ports */ gpio_set_mode(TMS_PORT, GPIO_MODE_OUTPUT_10_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, TMS_PIN); @@ -69,21 +69,21 @@ int platform_init(void) gpio_set_mode(TDO_PORT, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, TDO_PIN); - gpio_set(NRST_PORT,NRST_PIN); + gpio_set(NRST_PORT,NRST_PIN); gpio_set_mode(NRST_PORT, GPIO_MODE_INPUT, GPIO_CNF_INPUT_PULL_UPDOWN, NRST_PIN); gpio_set_mode(LED_PORT, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, led_idle_run); - /* Remap TIM2 TIM2_REMAP[1] - * TIM2_CH1_ETR -> PA15 (TDI, set as output above) - * TIM2_CH2 -> PB3 (TDO) - */ - data = AFIO_MAPR; - data &= ~AFIO_MAPR_TIM2_REMAP_FULL_REMAP; - data |= AFIO_MAPR_TIM2_REMAP_PARTIAL_REMAP1; - AFIO_MAPR = data; + /* Remap TIM2 TIM2_REMAP[1] + * TIM2_CH1_ETR -> PA15 (TDI, set as output above) + * TIM2_CH2 -> PB3 (TDO) + */ + data = AFIO_MAPR; + data &= ~AFIO_MAPR_TIM2_REMAP_FULL_REMAP; + data |= AFIO_MAPR_TIM2_REMAP_PARTIAL_REMAP1; + AFIO_MAPR = data; /* Setup heartbeat timer */ systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); diff --git a/src/platforms/swlink/platform.h b/src/platforms/swlink/platform.h index fe3dc46..6683421 100644 --- a/src/platforms/swlink/platform.h +++ b/src/platforms/swlink/platform.h @@ -38,12 +38,12 @@ #define INLINE_GPIO #define CDCACM_PACKET_SIZE 64 -#define BOARD_IDENT "Black Magic Probe (SWLINK), (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" -#define BOARD_IDENT_DFU "Black Magic (Upgrade), STM8S Discovery, (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" -#define BOARD_IDENT_UPD "Black Magic (DFU Upgrade), STM8S Discovery, (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" -#define DFU_IDENT "Black Magic Firmware Upgrade (SWLINK)" -#define DFU_IFACE_STRING "@Internal Flash /0x08000000/8*001Ka,56*001Kg" -#define UPD_IFACE_STRING "@Internal Flash /0x08000000/8*001Kg" +#define BOARD_IDENT "Black Magic Probe (SWLINK), (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" +#define BOARD_IDENT_DFU "Black Magic (Upgrade), STM8S Discovery, (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" +#define BOARD_IDENT_UPD "Black Magic (DFU Upgrade), STM8S Discovery, (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" +#define DFU_IDENT "Black Magic Firmware Upgrade (SWLINK)" +#define DFU_IFACE_STRING "@Internal Flash /0x08000000/8*001Ka,56*001Kg" +#define UPD_IFACE_STRING "@Internal Flash /0x08000000/8*001Kg" extern usbd_device *usbdev; #define CDCACM_GDB_ENDPOINT 1 @@ -86,26 +86,25 @@ extern usbd_device *usbdev; #define LED_PORT_UART GPIOC #define LED_UART GPIO14 -#define TMS_SET_MODE() \ - gpio_set_mode(TMS_PORT, GPIO_MODE_OUTPUT_50_MHZ, \ - GPIO_CNF_OUTPUT_PUSHPULL, TMS_PIN); -#define SWDIO_MODE_FLOAT() \ - gpio_set_mode(SWDIO_PORT, GPIO_MODE_INPUT, \ - GPIO_CNF_INPUT_FLOAT, SWDIO_PIN); -#define SWDIO_MODE_DRIVE() \ - gpio_set_mode(SWDIO_PORT, GPIO_MODE_OUTPUT_50_MHZ, \ - GPIO_CNF_OUTPUT_PUSHPULL, SWDIO_PIN); - -#define UART_PIN_SETUP() do \ - { \ - AFIO_MAPR |= AFIO_MAPR_USART1_REMAP; \ - gpio_set_mode(USBUSART_PORT, GPIO_MODE_OUTPUT_2_MHZ, \ - GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, USBUSART_TX_PIN); \ - } while (0) +#define TMS_SET_MODE() \ + gpio_set_mode(TMS_PORT, GPIO_MODE_OUTPUT_50_MHZ, \ + GPIO_CNF_OUTPUT_PUSHPULL, TMS_PIN); +#define SWDIO_MODE_FLOAT() \ + gpio_set_mode(SWDIO_PORT, GPIO_MODE_INPUT, \ + GPIO_CNF_INPUT_FLOAT, SWDIO_PIN); +#define SWDIO_MODE_DRIVE() \ + gpio_set_mode(SWDIO_PORT, GPIO_MODE_OUTPUT_50_MHZ, \ + GPIO_CNF_OUTPUT_PUSHPULL, SWDIO_PIN); + +#define UART_PIN_SETUP() do { \ + AFIO_MAPR |= AFIO_MAPR_USART1_REMAP; \ + gpio_set_mode(USBUSART_PORT, GPIO_MODE_OUTPUT_2_MHZ, \ + GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, USBUSART_TX_PIN); \ +} while (0) #define USB_DRIVER stm32f103_usb_driver #define USB_IRQ NVIC_USB_LP_CAN_RX0_IRQ -#define USB_ISR usb_lp_can_rx0_isr +#define USB_ISR usb_lp_can_rx0_isr /* Interrupt priorities. Low numbers are high priority. * For now USART1 preempts USB which may spin while buffer is drained. * TIM2 is used for traceswo capture and must be highest priority. diff --git a/src/platforms/swlink/usbdfu.c b/src/platforms/swlink/usbdfu.c index f87ccf4..9360981 100644 --- a/src/platforms/swlink/usbdfu.c +++ b/src/platforms/swlink/usbdfu.c @@ -43,19 +43,19 @@ void dfu_detach(void) int main(void) { /* Check the force bootloader pin*/ - uint16_t pin_b; + uint16_t pin_b; rcc_periph_clock_enable(RCC_GPIOA); rcc_periph_clock_enable(RCC_GPIOB); /* Switch PB5 (SWIM_RST_IN) up */ gpio_set(GPIOB, GPIO5); gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_2_MHZ, - GPIO_CNF_OUTPUT_PUSHPULL, GPIO5); + GPIO_CNF_OUTPUT_PUSHPULL, GPIO5); gpio_set(GPIOB, GPIO5); - pin_b = gpio_get(GPIOB, GPIO6); + pin_b = gpio_get(GPIOB, GPIO6); /* Check state on PB6 ((SWIM_RST) and release PB5*/ - pin_b = gpio_get(GPIOB, GPIO6); + pin_b = gpio_get(GPIOB, GPIO6); gpio_set_mode(GPIOB, GPIO_MODE_INPUT, - GPIO_CNF_INPUT_FLOAT, GPIO5); + GPIO_CNF_INPUT_FLOAT, GPIO5); if(((GPIOA_CRL & 0x40) == 0x40) && pin_b) dfu_jump_app_if_valid(); @@ -65,10 +65,10 @@ int main(void) systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); systick_set_reload(900000); - /* Handle USB disconnect/connect */ + /* Handle USB disconnect/connect */ /* Just in case: Disconnect USB cable by resetting USB Device - * and pulling USB_DP low - * Device will reconnect automatically as Pull-Up is hard wired*/ + * and pulling USB_DP low + * Device will reconnect automatically as Pull-Up is hard wired*/ rcc_periph_reset_pulse(RST_USB); rcc_periph_clock_enable(RCC_USB); rcc_periph_clock_enable(RCC_GPIOA); @@ -76,7 +76,7 @@ int main(void) gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO12); - /* Handle LED*/ + /* Handle LED*/ gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO8); @@ -90,5 +90,5 @@ int main(void) void sys_tick_handler(void) { - gpio_toggle(GPIOA, GPIO8); + gpio_toggle(GPIOA, GPIO8); } -- cgit v1.2.3 From f85a8c4ebb2ae4b45231813d06dd26d13eb2e6de Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Thu, 16 Oct 2014 13:40:47 -0700 Subject: Fix build for f4discovery by defining platform_hwversion(). --- src/platforms/f4discovery/platform.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/platforms/f4discovery/platform.h b/src/platforms/f4discovery/platform.h index 210ba62..7d6e92e 100644 --- a/src/platforms/f4discovery/platform.h +++ b/src/platforms/f4discovery/platform.h @@ -182,8 +182,11 @@ extern const char *morse_msg; int platform_init(void); void morse(const char *msg, char repeat); const char *platform_target_voltage(void); -int platform_hwversion(void); void platform_delay(uint32_t delay); +static inline int platform_hwversion(void) +{ + return 0; +} /* */ void cdcacm_init(void); @@ -226,3 +229,4 @@ static inline uint16_t _gpio_get(uint32_t gpioport, uint16_t gpios) #define disconnect_usb() do {usbd_disconnect(usbdev,1); nvic_disable_irq(USB_IRQ);} while(0) void assert_boot_pin(void); #define setup_vbus_irq() + -- cgit v1.2.3 From fd9eef821e7451fcb1d7839f9d1d21c098787327 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Thu, 16 Oct 2014 13:48:28 -0700 Subject: Revert USB double buffered OUT handling on STM32F1. This introduced a bug where the endpoint can get stuck, forever sending NAK. --- src/platforms/stm32/cdcacm.c | 13 +++++++++---- src/platforms/stm32/gdb_if.c | 46 +++++++++++++++++++++++++++----------------- 2 files changed, 37 insertions(+), 22 deletions(-) (limited to 'src') diff --git a/src/platforms/stm32/cdcacm.c b/src/platforms/stm32/cdcacm.c index ef7ff3b..9694cf0 100644 --- a/src/platforms/stm32/cdcacm.c +++ b/src/platforms/stm32/cdcacm.c @@ -485,17 +485,22 @@ static void cdcacm_set_config(usbd_device *dev, uint16_t wValue) configured = wValue; /* GDB interface */ +#ifdef STM32F4 usbd_ep_setup(dev, 0x01, USB_ENDPOINT_ATTR_BULK, - CDCACM_PACKET_SIZE, gdb_usb_out_cb); + CDCACM_PACKET_SIZE, gdb_usb_out_cb); +#else + usbd_ep_setup(dev, 0x01, USB_ENDPOINT_ATTR_BULK, + CDCACM_PACKET_SIZE, NULL); +#endif usbd_ep_setup(dev, 0x81, USB_ENDPOINT_ATTR_BULK, - CDCACM_PACKET_SIZE, NULL); + CDCACM_PACKET_SIZE, NULL); usbd_ep_setup(dev, 0x82, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL); /* Serial interface */ usbd_ep_setup(dev, 0x03, USB_ENDPOINT_ATTR_BULK, - CDCACM_PACKET_SIZE, usbuart_usb_out_cb); + CDCACM_PACKET_SIZE, usbuart_usb_out_cb); usbd_ep_setup(dev, 0x83, USB_ENDPOINT_ATTR_BULK, - CDCACM_PACKET_SIZE, usbuart_usb_in_cb); + CDCACM_PACKET_SIZE, usbuart_usb_in_cb); usbd_ep_setup(dev, 0x84, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL); #if defined(PLATFORM_HAS_TRACESWO) diff --git a/src/platforms/stm32/gdb_if.c b/src/platforms/stm32/gdb_if.c index 482effe..c8208b3 100644 --- a/src/platforms/stm32/gdb_if.c +++ b/src/platforms/stm32/gdb_if.c @@ -28,12 +28,14 @@ #include "gdb_if.h" static uint32_t count_out; -static uint32_t count_new; static uint32_t count_in; static uint32_t out_ptr; static uint8_t buffer_out[CDCACM_PACKET_SIZE]; -static uint8_t double_buffer_out[CDCACM_PACKET_SIZE]; static uint8_t buffer_in[CDCACM_PACKET_SIZE]; +#ifdef STM32F4 +static volatile uint32_t count_new; +static uint8_t double_buffer_out[CDCACM_PACKET_SIZE]; +#endif void gdb_if_putchar(unsigned char c, int flush) { @@ -63,6 +65,7 @@ void gdb_if_putchar(unsigned char c, int flush) } } +#ifdef STM32F4 void gdb_usb_out_cb(usbd_device *dev, uint8_t ep) { (void)ep; @@ -73,6 +76,27 @@ void gdb_usb_out_cb(usbd_device *dev, uint8_t ep) usbd_ep_nak_set(dev, CDCACM_GDB_ENDPOINT, 0); } } +#endif + +static void gdb_if_update_buf(void) +{ + while (cdcacm_get_config() != 1); +#ifdef STM32F4 + asm volatile ("cpsid i; isb"); + if (count_new) { + memcpy(buffer_out, double_buffer_out, count_new); + count_out = count_new; + count_new = 0; + out_ptr = 0; + usbd_ep_nak_set(usbdev, CDCACM_GDB_ENDPOINT, 0); + } + asm volatile ("cpsie i; isb"); +#else + count_out = usbd_ep_read_packet(usbdev, CDCACM_GDB_ENDPOINT, + buffer_out, CDCACM_PACKET_SIZE); + out_ptr = 0; +#endif +} unsigned char gdb_if_getchar(void) { @@ -82,14 +106,7 @@ unsigned char gdb_if_getchar(void) if (!cdcacm_get_dtr()) return 0x04; - while (cdcacm_get_config() != 1); - if (count_new) { - memcpy(buffer_out, double_buffer_out,count_new); - count_out = count_new; - count_new = 0; - out_ptr = 0; - usbd_ep_nak_set(usbdev, CDCACM_GDB_ENDPOINT, 0); - } + gdb_if_update_buf(); } return buffer_out[out_ptr++]; @@ -104,14 +121,7 @@ unsigned char gdb_if_getchar_to(int timeout) if (!cdcacm_get_dtr()) return 0x04; - while (cdcacm_get_config() != 1); - if (count_new) { - memcpy(buffer_out, double_buffer_out,count_new); - count_out = count_new; - count_new = 0; - out_ptr = 0; - usbd_ep_nak_set(usbdev, CDCACM_GDB_ENDPOINT, 0); - } + gdb_if_update_buf(); } while(timeout_counter && !(out_ptr < count_out)); if(out_ptr < count_out) -- cgit v1.2.3 From 94342996131b5a15fc7ef2e61172a771e54b977c Mon Sep 17 00:00:00 2001 From: Vegard Storheil Eriksen Date: Tue, 21 Oct 2014 00:12:50 +0200 Subject: Add support for halfword memory accesses. --- src/adiv5.c | 67 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/arm7tdmi.c | 2 ++ src/gdb_main.c | 4 ++++ src/include/target.h | 11 +++++++++ 4 files changed, 84 insertions(+) (limited to 'src') diff --git a/src/adiv5.c b/src/adiv5.c index 45bf94f..e7f45c9 100644 --- a/src/adiv5.c +++ b/src/adiv5.c @@ -46,6 +46,8 @@ static int ap_check_error(struct target_s *target); static int ap_mem_read_words(struct target_s *target, uint32_t *dest, uint32_t src, int len); static int ap_mem_write_words(struct target_s *target, uint32_t dest, const uint32_t *src, int len); +static int ap_mem_read_halfwords(struct target_s *target, uint16_t *dest, uint32_t src, int len); +static int ap_mem_write_halfwords(struct target_s *target, uint32_t dest, const uint16_t *src, int len); static int ap_mem_read_bytes(struct target_s *target, uint8_t *dest, uint32_t src, int len); static int ap_mem_write_bytes(struct target_s *target, uint32_t dest, const uint8_t *src, int len); @@ -152,6 +154,8 @@ void adiv5_dp_init(ADIv5_DP_t *dp) t->mem_read_words = ap_mem_read_words; t->mem_write_words = ap_mem_write_words; + t->mem_read_halfwords = ap_mem_read_halfwords; + t->mem_write_halfwords = ap_mem_write_halfwords; t->mem_read_bytes = ap_mem_read_bytes; t->mem_write_bytes = ap_mem_write_bytes; @@ -219,6 +223,42 @@ ap_mem_read_words(struct target_s *target, uint32_t *dest, uint32_t src, int len return 0; } +static int +ap_mem_read_halfwords(struct target_s *target, uint16_t *dest, uint32_t src, int len) +{ + ADIv5_AP_t *ap = adiv5_target_ap(target); + uint32_t tmp; + uint32_t osrc = src; + + len >>= 1; + + adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw | + ADIV5_AP_CSW_SIZE_HALFWORD | ADIV5_AP_CSW_ADDRINC_SINGLE); + adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP, ADIV5_LOW_WRITE, + ADIV5_AP_TAR, src); + adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP, ADIV5_LOW_READ, + ADIV5_AP_DRW, 0); + while(--len) { + tmp = adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP, ADIV5_LOW_READ, + ADIV5_AP_DRW, 0); + *dest++ = (tmp >> ((src & 0x2) << 3) & 0xFFFF); + + src += 2; + /* Check for 10 bit address overflow */ + if ((src ^ osrc) & 0xfffffc00) { + osrc = src; + adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP, + ADIV5_LOW_WRITE, ADIV5_AP_TAR, src); + adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP, + ADIV5_LOW_READ, ADIV5_AP_DRW, 0); + } + } + tmp = adiv5_dp_low_access(ap->dp, 0, 1, ADIV5_DP_RDBUFF, 0); + *dest++ = (tmp >> ((src & 0x2) << 3) & 0xFFFF); + + return 0; +} + static int ap_mem_read_bytes(struct target_s *target, uint8_t *dest, uint32_t src, int len) { @@ -280,6 +320,33 @@ ap_mem_write_words(struct target_s *target, uint32_t dest, const uint32_t *src, return 0; } +static int +ap_mem_write_halfwords(struct target_s *target, uint32_t dest, const uint16_t *src, int len) +{ + ADIv5_AP_t *ap = adiv5_target_ap(target); + uint32_t odest = dest; + + len >>= 1; + + adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw | + ADIV5_AP_CSW_SIZE_HALFWORD | ADIV5_AP_CSW_ADDRINC_SINGLE); + adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP, ADIV5_LOW_WRITE, + ADIV5_AP_TAR, dest); + while(len--) { + uint32_t tmp = (uint32_t)*src++ << ((dest & 2) << 3); + adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP, ADIV5_LOW_WRITE, + ADIV5_AP_DRW, tmp); + dest += 2; + /* Check for 10 bit address overflow */ + if ((dest ^ odest) & 0xfffffc00) { + odest = dest; + adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP, + ADIV5_LOW_WRITE, ADIV5_AP_TAR, dest); + } + } + return 0; +} + static int ap_mem_write_bytes(struct target_s *target, uint32_t dest, const uint8_t *src, int len) { diff --git a/src/arm7tdmi.c b/src/arm7tdmi.c index 26c5233..1c7b443 100644 --- a/src/arm7tdmi.c +++ b/src/arm7tdmi.c @@ -129,6 +129,8 @@ void arm7tdmi_jtag_handler(jtag_dev_t *dev) t->check_error = (void *)do_nothing; t->mem_read_words = (void *)do_nothing; t->mem_write_words = (void *)do_nothing; + t->mem_read_halfwords = (void *)do_nothing; + t->mem_write_halfwords = (void *)do_nothing; t->mem_read_bytes = (void *)do_nothing; t->mem_write_bytes = (void *)do_nothing; t->regs_size = 16 * sizeof(uint32_t); diff --git a/src/gdb_main.c b/src/gdb_main.c index c99ebac..dc56a59 100644 --- a/src/gdb_main.c +++ b/src/gdb_main.c @@ -101,6 +101,8 @@ gdb_main(void) uint8_t mem[len]; if(((addr & 3) == 0) && ((len & 3) == 0)) target_mem_read_words(cur_target, (void*)mem, addr, len); + else if(((addr & 1) == 0) && ((len & 1) == 0)) + target_mem_read_halfwords(cur_target, (void*)mem, addr, len); else target_mem_read_bytes(cur_target, (void*)mem, addr, len); if(target_check_error(cur_target)) @@ -127,6 +129,8 @@ gdb_main(void) unhexify(mem, pbuf + hex, len); if(((addr & 3) == 0) && ((len & 3) == 0)) target_mem_write_words(cur_target, addr, (void*)mem, len); + else if(((addr & 1) == 0) && ((len & 1) == 0)) + target_mem_write_halfwords(cur_target, addr, (void*)mem, len); else target_mem_write_bytes(cur_target, addr, (void*)mem, len); if(target_check_error(cur_target)) diff --git a/src/include/target.h b/src/include/target.h index 067b051..f28f2f8 100644 --- a/src/include/target.h +++ b/src/include/target.h @@ -56,6 +56,12 @@ target *target_attach(target *t, target_destroy_callback destroy_cb); #define target_mem_write_words(target, dest, src, len) \ (target)->mem_write_words((target), (dest), (src), (len)) +#define target_mem_read_halfwords(target, dest, src, len) \ + (target)->mem_read_halfwords((target), (dest), (src), (len)) + +#define target_mem_write_halfwords(target, dest, src, len) \ + (target)->mem_write_halfwords((target), (dest), (src), (len)) + #define target_mem_read_bytes(target, dest, src, len) \ (target)->mem_read_bytes((target), (dest), (src), (len)) @@ -136,6 +142,11 @@ struct target_s { int (*mem_write_words)(struct target_s *target, uint32_t dest, const uint32_t *src, int len); + int (*mem_read_halfwords)(struct target_s *target, uint16_t *dest, uint32_t src, + int len); + int (*mem_write_halfwords)(struct target_s *target, uint32_t dest, + const uint16_t *src, int len); + int (*mem_read_bytes)(struct target_s *target, uint8_t *dest, uint32_t src, int len); int (*mem_write_bytes)(struct target_s *target, uint32_t dest, -- cgit v1.2.3 From 346258934b99c0ea50acfb5ea05fdf0537b3194a Mon Sep 17 00:00:00 2001 From: Fredrik Ahlberg Date: Sun, 23 Nov 2014 22:59:16 +0100 Subject: Added support for TI TM4C123 Launchpad --- src/lmi.c | 20 +- src/platforms/launchpad-icdi/Makefile.inc | 23 ++ src/platforms/launchpad-icdi/platform.c | 86 +++++ src/platforms/launchpad-icdi/platform.h | 137 +++++++ src/platforms/tm4c/cdcacm.c | 577 ++++++++++++++++++++++++++++++ src/platforms/tm4c/gdb_if.c | 100 ++++++ src/platforms/tm4c/jtagtap.c | 58 +++ src/platforms/tm4c/swdptap.c | 125 +++++++ src/platforms/tm4c/tm4c.ld | 29 ++ src/platforms/tm4c/traceswo.c | 165 +++++++++ src/platforms/tm4c/usbuart.c | 182 ++++++++++ 11 files changed, 1501 insertions(+), 1 deletion(-) create mode 100644 src/platforms/launchpad-icdi/Makefile.inc create mode 100644 src/platforms/launchpad-icdi/platform.c create mode 100644 src/platforms/launchpad-icdi/platform.h create mode 100644 src/platforms/tm4c/cdcacm.c create mode 100644 src/platforms/tm4c/gdb_if.c create mode 100644 src/platforms/tm4c/jtagtap.c create mode 100644 src/platforms/tm4c/swdptap.c create mode 100644 src/platforms/tm4c/tm4c.ld create mode 100644 src/platforms/tm4c/traceswo.c create mode 100644 src/platforms/tm4c/usbuart.c (limited to 'src') diff --git a/src/lmi.c b/src/lmi.c index cb620c0..a08819e 100644 --- a/src/lmi.c +++ b/src/lmi.c @@ -38,7 +38,7 @@ static int lmi_flash_erase(struct target_s *target, uint32_t addr, int len); static int lmi_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, int len); -static const char lmi_driver_str[] = "LuminaryMicro Stellaris"; +static const char lmi_driver_str[] = "TI Stellaris/Tiva"; static const char lmi_xml_memory_map[] = "" /* "" " " ""; +static const char tm4c123gh6pm_xml_memory_map[] = "" +/* ""*/ + "" + " " + " 0x400" + " " + " " + ""; + uint16_t lmi_flash_write_stub[] = { // _start: @@ -100,6 +111,13 @@ bool lmi_probe(struct target_s *target) target->flash_erase = lmi_flash_erase; target->flash_write = lmi_flash_write; return true; + + case 0x10A1: /* TM4C123GH6PM */ + target->driver = lmi_driver_str; + target->xml_mem_map = tm4c123gh6pm_xml_memory_map; + target->flash_erase = lmi_flash_erase; + target->flash_write = lmi_flash_write; + return true; } return false; } diff --git a/src/platforms/launchpad-icdi/Makefile.inc b/src/platforms/launchpad-icdi/Makefile.inc new file mode 100644 index 0000000..8a0f9a3 --- /dev/null +++ b/src/platforms/launchpad-icdi/Makefile.inc @@ -0,0 +1,23 @@ +CROSS_COMPILE ?= arm-none-eabi- +CC = $(CROSS_COMPILE)gcc +OBJCOPY = $(CROSS_COMPILE)objcopy + +INCLUDES = -I../libopencm3/include + +CPU_FLAGS = -mcpu=cortex-m4 -mthumb -mfpu=fpv4-sp-d16 -mfloat-abi=hard +CFLAGS += $(INCLUDES) $(CPU_FLAGS) -DTARGET_IS_BLIZZARD_RB1 -DLM4F -DPART_TM4C123GH6PM + +LINKER_SCRIPT="platforms/tm4c/tm4c.ld" +LDFLAGS = -nostartfiles -lc $(CPU_FLAGS) -nodefaultlibs -T$(LINKER_SCRIPT) -Wl,--gc-sections \ + -L../libopencm3/lib -lopencm3_lm4f -lnosys -lm -lgcc + +VPATH += platforms/tm4c + +SRC += cdcacm.c \ + usbuart.c \ + traceswo.o + +all: blackmagic.bin + +blackmagic.bin: blackmagic + $(OBJCOPY) -O binary $^ $@ diff --git a/src/platforms/launchpad-icdi/platform.c b/src/platforms/launchpad-icdi/platform.c new file mode 100644 index 0000000..848271e --- /dev/null +++ b/src/platforms/launchpad-icdi/platform.c @@ -0,0 +1,86 @@ +#include "platform.h" +#include "gdb_if.h" +#include "usbuart.h" + +#include +#include +#include +#include + +#define SYSTICKHZ 100 +#define SYSTICKMS (1000 / SYSTICKHZ) + +#define PLL_DIV_80MHZ 5 +#define PLL_DIV_25MHZ 16 + +extern void trace_tick(void); + +jmp_buf fatal_error_jmpbuf; +uint8_t running_status; +volatile uint32_t timeout_counter; + +const char *morse_msg; + +void morse(const char *msg, char repeat) +{ + (void) msg; + (void) repeat; +} + +void sys_tick_handler(void) +{ + if(timeout_counter) + timeout_counter--; + trace_tick(); +} + +int +platform_init(void) +{ + int i; + for(i=0; i<1000000; i++); + + rcc_sysclk_config(OSCSRC_MOSC, XTAL_16M, PLL_DIV_80MHZ); + + // Enable all JTAG ports and set pins to output + periph_clock_enable(RCC_GPIOA); + periph_clock_enable(RCC_GPIOB); + + gpio_enable_ahb_aperture(); + + gpio_mode_setup(TMS_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, TMS_PIN); + gpio_mode_setup(TCK_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, TCK_PIN); + gpio_mode_setup(TDI_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, TDI_PIN); + gpio_mode_setup(TDO_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, TDO_PIN); + gpio_mode_setup(SRST_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, SRST_PIN); + gpio_set_output_config(SRST_PORT, GPIO_OTYPE_OD, GPIO_DRIVE_2MA, SRST_PIN); + gpio_set(SRST_PORT, SRST_PIN); + + systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); + systick_set_reload(rcc_get_system_clock_frequency() / (SYSTICKHZ * 8)); + + systick_interrupt_enable(); + systick_counter_enable(); + + nvic_enable_irq(NVIC_SYSTICK_IRQ); + nvic_enable_irq(NVIC_UART0_IRQ); + + usbuart_init(); + cdcacm_init(); + + //jtag_scan(NULL); + + return 0; +} + +void platform_delay(uint32_t delay) +{ + timeout_counter = delay * 10; + while(timeout_counter); +} + +const char *platform_target_voltage(void) +{ + return "not supported"; +} + diff --git a/src/platforms/launchpad-icdi/platform.h b/src/platforms/launchpad-icdi/platform.h new file mode 100644 index 0000000..7f5d55f --- /dev/null +++ b/src/platforms/launchpad-icdi/platform.h @@ -0,0 +1,137 @@ +#ifndef __PLATFORM_H +#define __PLATFORM_H + +#include + +#include +#include + +#include +#include + +#include "gdb_packet.h" + +#define CDCACM_PACKET_SIZE 64 +#define BOARD_IDENT "Black Magic Probe (Launchpad ICDI), (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" +#define BOARD_IDENT_DFU "Black Magic (Upgrade) for Launchpad, (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" +#define DFU_IDENT "Black Magic Firmware Upgrade (Launchpad)" +#define DFU_IFACE_STRING "lolwut" + +extern usbd_device *usbdev; +#define CDCACM_GDB_ENDPOINT 1 +#define CDCACM_UART_ENDPOINT 3 + +extern jmp_buf fatal_error_jmpbuf; +extern uint8_t running_status; +extern const char *morse_msg; +extern volatile uint32_t timeout_counter; + +#define TMS_PORT GPIOA_BASE +#define TMS_PIN GPIO3 + +#define TCK_PORT GPIOA_BASE +#define TCK_PIN GPIO2 + +#define TDI_PORT GPIOA_BASE +#define TDI_PIN GPIO5 + +#define TDO_PORT GPIOA_BASE +#define TDO_PIN GPIO4 + +#define SWO_PORT GPIOD_BASE +#define SWO_PIN GPIO6 + +#define SWDIO_PORT TMS_PORT +#define SWDIO_PIN TMS_PIN + +#define SWCLK_PORT TCK_PORT +#define SWCLK_PIN TCK_PIN + +#define SRST_PORT GPIOA_BASE +#define SRST_PIN GPIO6 + +#define TMS_SET_MODE() { \ + gpio_mode_setup(TMS_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, TMS_PIN); \ + gpio_set_output_config(TMS_PORT, GPIO_OTYPE_PP, GPIO_DRIVE_2MA, TMS_PIN); \ +} + +#define SWDIO_MODE_FLOAT() { \ + gpio_mode_setup(SWDIO_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, SWDIO_PIN); \ +} + +#define SWDIO_MODE_DRIVE() { \ + gpio_mode_setup(SWDIO_PORT, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, SWDIO_PIN); \ + gpio_set_output_config(SWDIO_PORT, GPIO_OTYPE_PP, GPIO_DRIVE_2MA, SWDIO_PIN); \ +} + +extern usbd_driver lm4f_usb_driver; +#define USB_DRIVER lm4f_usb_driver +#define USB_IRQ NVIC_USB0_IRQ +#define USB_ISR usb0_isr + +#define IRQ_PRI_USB (2 << 4) + +#define USBUART UART0 +#define USBUART_CLK RCC_UART0 +#define USBUART_IRQ NVIC_UART0_IRQ +#define USBUART_ISR uart0_isr +#define UART_PIN_SETUP() do { \ + periph_clock_enable(RCC_GPIOA); \ + __asm__("nop"); __asm__("nop"); __asm__("nop"); \ + gpio_set_af(GPIOA_BASE, 0x1, GPIO0 | GPIO1); \ + gpio_mode_setup(GPIOA_BASE, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO0); \ + gpio_mode_setup(GPIOA_BASE, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO1); \ + } while (0) + +#define TRACEUART UART2 +#define TRACEUART_CLK RCC_UART2 +#define TRACEUART_IRQ NVIC_UART2_IRQ +#define TRACEUART_ISR uart2_isr + +/* Use newlib provided integer only stdio functions */ +#define sscanf siscanf +#define sprintf siprintf +#define vasprintf vasiprintf + +#define DEBUG(...) + +#define SET_RUN_STATE(state) {running_status = (state);} +#define SET_IDLE_STATE(state) {} +#define SET_ERROR_STATE(state) SET_IDLE_STATE(state) + +#define PLATFORM_SET_FATAL_ERROR_RECOVERY() {setjmp(fatal_error_jmpbuf);} +#define PLATFORM_FATAL_ERROR(error) { \ + if( running_status ) gdb_putpacketz("X1D"); \ + else gdb_putpacketz("EFF"); \ + running_status = 0; \ + target_list_free(); \ + morse("TARGET LOST.", 1); \ + longjmp(fatal_error_jmpbuf, (error)); \ +} + +#define PLATFORM_HAS_TRACESWO + +int platform_init(void); +void morse(const char *msg, char repeat); + +inline static void gpio_set_val(uint32_t port, uint8_t pin, uint8_t val) { + gpio_write(port, pin, val == 0 ? 0 : 0xff); +} + +inline static uint8_t gpio_get(uint32_t port, uint8_t pin) { + return !(gpio_read(port, pin) == 0); +} + +void platform_delay(uint32_t delay); +const char *platform_target_voltage(void); + +/* */ +void cdcacm_init(void); +/* Returns current usb configuration, or 0 if not configured. */ +int cdcacm_get_config(void); +int cdcacm_get_dtr(void); + +#define disconnect_usb() do { usbd_disconnect(usbdev,1); nvic_disable_irq(USB_IRQ);} while(0) +#define setup_vbus_irq() + +#endif diff --git a/src/platforms/tm4c/cdcacm.c b/src/platforms/tm4c/cdcacm.c new file mode 100644 index 0000000..041d85b --- /dev/null +++ b/src/platforms/tm4c/cdcacm.c @@ -0,0 +1,577 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2011 Black Sphere Technologies Ltd. + * Written by Gareth McMullin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * 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, see . + */ + +/* This file implements a the USB Communications Device Class - Abstract + * Control Model (CDC-ACM) as defined in CDC PSTN subclass 1.2. + * A Device Firmware Upgrade (DFU 1.1) class interface is provided for + * field firmware upgrade. + * + * The device's unique id is used as the USB serial number string. + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "platform.h" +#include "gdb_if.h" +#if defined(PLATFORM_HAS_TRACESWO) +#include +#endif +#include + +#define DFU_IF_NO 4 + +usbd_device * usbdev; + +static char *get_dev_unique_id(char *serial_no); + +static int configured; +static int cdcacm_gdb_dtr = 1; + + +static const struct usb_device_descriptor dev = { + .bLength = USB_DT_DEVICE_SIZE, + .bDescriptorType = USB_DT_DEVICE, + .bcdUSB = 0x0200, + .bDeviceClass = 0xEF, /* Miscellaneous Device */ + .bDeviceSubClass = 2, /* Common Class */ + .bDeviceProtocol = 1, /* Interface Association */ + .bMaxPacketSize0 = 64, + .idVendor = 0x1D50, + .idProduct = 0x6018, + .bcdDevice = 0x0100, + .iManufacturer = 1, + .iProduct = 2, + .iSerialNumber = 3, + .bNumConfigurations = 1, +}; + +/* This notification endpoint isn't implemented. According to CDC spec its + * optional, but its absence causes a NULL pointer dereference in Linux cdc_acm + * driver. */ +static const struct usb_endpoint_descriptor gdb_comm_endp[] = {{ + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 0x82, + .bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT, + .wMaxPacketSize = 16, + .bInterval = 255, +}}; + +static const struct usb_endpoint_descriptor gdb_data_endp[] = {{ + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 0x01, + .bmAttributes = USB_ENDPOINT_ATTR_BULK, + .wMaxPacketSize = CDCACM_PACKET_SIZE, + .bInterval = 1, +}, { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 0x81, + .bmAttributes = USB_ENDPOINT_ATTR_BULK, + .wMaxPacketSize = CDCACM_PACKET_SIZE, + .bInterval = 1, +}}; + +static const struct { + struct usb_cdc_header_descriptor header; + struct usb_cdc_call_management_descriptor call_mgmt; + struct usb_cdc_acm_descriptor acm; + struct usb_cdc_union_descriptor cdc_union; +} __attribute__((packed)) gdb_cdcacm_functional_descriptors = { + .header = { + .bFunctionLength = sizeof(struct usb_cdc_header_descriptor), + .bDescriptorType = CS_INTERFACE, + .bDescriptorSubtype = USB_CDC_TYPE_HEADER, + .bcdCDC = 0x0110, + }, + .call_mgmt = { + .bFunctionLength = + sizeof(struct usb_cdc_call_management_descriptor), + .bDescriptorType = CS_INTERFACE, + .bDescriptorSubtype = USB_CDC_TYPE_CALL_MANAGEMENT, + .bmCapabilities = 0, + .bDataInterface = 1, + }, + .acm = { + .bFunctionLength = sizeof(struct usb_cdc_acm_descriptor), + .bDescriptorType = CS_INTERFACE, + .bDescriptorSubtype = USB_CDC_TYPE_ACM, + .bmCapabilities = 2, /* SET_LINE_CODING supported */ + }, + .cdc_union = { + .bFunctionLength = sizeof(struct usb_cdc_union_descriptor), + .bDescriptorType = CS_INTERFACE, + .bDescriptorSubtype = USB_CDC_TYPE_UNION, + .bControlInterface = 0, + .bSubordinateInterface0 = 1, + } +}; + +static const struct usb_interface_descriptor gdb_comm_iface[] = {{ + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 0, + .bAlternateSetting = 0, + .bNumEndpoints = 1, + .bInterfaceClass = USB_CLASS_CDC, + .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, + .bInterfaceProtocol = USB_CDC_PROTOCOL_AT, + .iInterface = 4, + + .endpoint = gdb_comm_endp, + + .extra = &gdb_cdcacm_functional_descriptors, + .extralen = sizeof(gdb_cdcacm_functional_descriptors) +}}; + +static const struct usb_interface_descriptor gdb_data_iface[] = {{ + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 1, + .bAlternateSetting = 0, + .bNumEndpoints = 2, + .bInterfaceClass = USB_CLASS_DATA, + .bInterfaceSubClass = 0, + .bInterfaceProtocol = 0, + .iInterface = 0, + + .endpoint = gdb_data_endp, +}}; + +static const struct usb_iface_assoc_descriptor gdb_assoc = { + .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE, + .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, + .bFirstInterface = 0, + .bInterfaceCount = 2, + .bFunctionClass = USB_CLASS_CDC, + .bFunctionSubClass = USB_CDC_SUBCLASS_ACM, + .bFunctionProtocol = USB_CDC_PROTOCOL_AT, + .iFunction = 0, +}; + +/* Serial ACM interface */ +static const struct usb_endpoint_descriptor uart_comm_endp[] = {{ + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 0x84, + .bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT, + .wMaxPacketSize = 16, + .bInterval = 255, +}}; + +static const struct usb_endpoint_descriptor uart_data_endp[] = {{ + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 0x03, + .bmAttributes = USB_ENDPOINT_ATTR_BULK, + .wMaxPacketSize = CDCACM_PACKET_SIZE, + .bInterval = 1, +}, { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 0x83, + .bmAttributes = USB_ENDPOINT_ATTR_BULK, + .wMaxPacketSize = CDCACM_PACKET_SIZE, + .bInterval = 1, +}}; + +static const struct { + struct usb_cdc_header_descriptor header; + struct usb_cdc_call_management_descriptor call_mgmt; + struct usb_cdc_acm_descriptor acm; + struct usb_cdc_union_descriptor cdc_union; +} __attribute__((packed)) uart_cdcacm_functional_descriptors = { + .header = { + .bFunctionLength = sizeof(struct usb_cdc_header_descriptor), + .bDescriptorType = CS_INTERFACE, + .bDescriptorSubtype = USB_CDC_TYPE_HEADER, + .bcdCDC = 0x0110, + }, + .call_mgmt = { + .bFunctionLength = + sizeof(struct usb_cdc_call_management_descriptor), + .bDescriptorType = CS_INTERFACE, + .bDescriptorSubtype = USB_CDC_TYPE_CALL_MANAGEMENT, + .bmCapabilities = 0, + .bDataInterface = 3, + }, + .acm = { + .bFunctionLength = sizeof(struct usb_cdc_acm_descriptor), + .bDescriptorType = CS_INTERFACE, + .bDescriptorSubtype = USB_CDC_TYPE_ACM, + .bmCapabilities = 2, /* SET_LINE_CODING supported*/ + }, + .cdc_union = { + .bFunctionLength = sizeof(struct usb_cdc_union_descriptor), + .bDescriptorType = CS_INTERFACE, + .bDescriptorSubtype = USB_CDC_TYPE_UNION, + .bControlInterface = 2, + .bSubordinateInterface0 = 3, + } +}; + +static const struct usb_interface_descriptor uart_comm_iface[] = {{ + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 2, + .bAlternateSetting = 0, + .bNumEndpoints = 1, + .bInterfaceClass = USB_CLASS_CDC, + .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, + .bInterfaceProtocol = USB_CDC_PROTOCOL_AT, + .iInterface = 5, + + .endpoint = uart_comm_endp, + + .extra = &uart_cdcacm_functional_descriptors, + .extralen = sizeof(uart_cdcacm_functional_descriptors) +}}; + +static const struct usb_interface_descriptor uart_data_iface[] = {{ + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 3, + .bAlternateSetting = 0, + .bNumEndpoints = 2, + .bInterfaceClass = USB_CLASS_DATA, + .bInterfaceSubClass = 0, + .bInterfaceProtocol = 0, + .iInterface = 0, + + .endpoint = uart_data_endp, +}}; + +static const struct usb_iface_assoc_descriptor uart_assoc = { + .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE, + .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, + .bFirstInterface = 2, + .bInterfaceCount = 2, + .bFunctionClass = USB_CLASS_CDC, + .bFunctionSubClass = USB_CDC_SUBCLASS_ACM, + .bFunctionProtocol = USB_CDC_PROTOCOL_AT, + .iFunction = 0, +}; + +const struct usb_dfu_descriptor dfu_function = { + .bLength = sizeof(struct usb_dfu_descriptor), + .bDescriptorType = DFU_FUNCTIONAL, + .bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_WILL_DETACH, + .wDetachTimeout = 255, + .wTransferSize = 1024, + .bcdDFUVersion = 0x011A, +}; + +const struct usb_interface_descriptor dfu_iface = { + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = DFU_IF_NO, + .bAlternateSetting = 0, + .bNumEndpoints = 0, + .bInterfaceClass = 0xFE, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 1, + .iInterface = 6, + + .extra = &dfu_function, + .extralen = sizeof(dfu_function), +}; + +static const struct usb_iface_assoc_descriptor dfu_assoc = { + .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE, + .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, + .bFirstInterface = 4, + .bInterfaceCount = 1, + .bFunctionClass = 0xFE, + .bFunctionSubClass = 1, + .bFunctionProtocol = 1, + .iFunction = 6, +}; + +#if defined(PLATFORM_HAS_TRACESWO) +static const struct usb_endpoint_descriptor trace_endp[] = {{ + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 0x85, + .bmAttributes = USB_ENDPOINT_ATTR_BULK, + .wMaxPacketSize = 64, + .bInterval = 0, +}}; + +const struct usb_interface_descriptor trace_iface = { + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 5, + .bAlternateSetting = 0, + .bNumEndpoints = 1, + .bInterfaceClass = 0xFF, + .bInterfaceSubClass = 0xFF, + .bInterfaceProtocol = 0xFF, + .iInterface = 7, + + .endpoint = trace_endp, +}; + +static const struct usb_iface_assoc_descriptor trace_assoc = { + .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE, + .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, + .bFirstInterface = 5, + .bInterfaceCount = 1, + .bFunctionClass = 0xFF, + .bFunctionSubClass = 0xFF, + .bFunctionProtocol = 0xFF, + .iFunction = 7, +}; +#endif + +static const struct usb_interface ifaces[] = {{ + .num_altsetting = 1, + .iface_assoc = &gdb_assoc, + .altsetting = gdb_comm_iface, +}, { + .num_altsetting = 1, + .altsetting = gdb_data_iface, +}, { + .num_altsetting = 1, + .iface_assoc = &uart_assoc, + .altsetting = uart_comm_iface, +}, { + .num_altsetting = 1, + .altsetting = uart_data_iface, +}, { + .num_altsetting = 1, + .iface_assoc = &dfu_assoc, + .altsetting = &dfu_iface, +#if defined(PLATFORM_HAS_TRACESWO) +}, { + .num_altsetting = 1, + .iface_assoc = &trace_assoc, + .altsetting = &trace_iface, +#endif +}}; + +static const struct usb_config_descriptor config = { + .bLength = USB_DT_CONFIGURATION_SIZE, + .bDescriptorType = USB_DT_CONFIGURATION, + .wTotalLength = 0, +#if defined(PLATFORM_HAS_TRACESWO) + .bNumInterfaces = 6, +#else + .bNumInterfaces = 5, +#endif + .bConfigurationValue = 1, + .iConfiguration = 0, + .bmAttributes = 0x80, + .bMaxPower = 0x32, + + .interface = ifaces, +}; + +char serial_no[9]; + +static const char *usb_strings[] = { + "Black Sphere Technologies", + BOARD_IDENT, + serial_no, + "Black Magic GDB Server", + "Black Magic UART Port", + DFU_IDENT, +#if defined(PLATFORM_HAS_TRACESWO) + "Black Magic Trace Capture", +#endif +}; + +static void dfu_detach_complete(usbd_device *dev, struct usb_setup_data *req) +{ + (void)dev; + (void)req; + + /* Disconnect USB cable */ + disconnect_usb(); + + /* Assert boot-request pin */ + //assert_boot_pin(); + + /* Reset core to enter bootloader */ + scb_reset_core(); +} + +static int cdcacm_control_request(usbd_device *dev, + struct usb_setup_data *req, uint8_t **buf, uint16_t *len, + void (**complete)(usbd_device *dev, struct usb_setup_data *req)) +{ + (void)dev; + (void)complete; + (void)buf; + (void)len; + + switch(req->bRequest) { + case USB_CDC_REQ_SET_CONTROL_LINE_STATE: + /* Ignore if not for GDB interface */ + if(req->wIndex != 0) + return 1; + + cdcacm_gdb_dtr = req->wValue & 1; + + return 1; + case USB_CDC_REQ_SET_LINE_CODING: + if(*len < sizeof(struct usb_cdc_line_coding)) + return 0; + + switch(req->wIndex) { + case 2: + usbuart_set_line_coding((struct usb_cdc_line_coding*)*buf); + case 0: + return 1; /* Ignore on GDB Port */ + default: + return 0; + } + case DFU_GETSTATUS: + if(req->wIndex == DFU_IF_NO) { + (*buf)[0] = DFU_STATUS_OK; + (*buf)[1] = 0; + (*buf)[2] = 0; + (*buf)[3] = 0; + (*buf)[4] = STATE_APP_IDLE; + (*buf)[5] = 0; /* iString not used here */ + *len = 6; + + return 1; + } + case DFU_DETACH: + if(req->wIndex == DFU_IF_NO) { + *complete = dfu_detach_complete; + return 1; + } + return 0; + } + return 0; +} + +int cdcacm_get_config(void) +{ + return configured; +} + +int cdcacm_get_dtr(void) +{ + return cdcacm_gdb_dtr; +} + +static void cdcacm_set_config(usbd_device *dev, uint16_t wValue) +{ + configured = wValue; + + /* GDB interface */ + usbd_ep_setup(dev, 0x01, USB_ENDPOINT_ATTR_BULK, + CDCACM_PACKET_SIZE, gdb_usb_out_cb); + usbd_ep_setup(dev, 0x81, USB_ENDPOINT_ATTR_BULK, + CDCACM_PACKET_SIZE, NULL); + usbd_ep_setup(dev, 0x82, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL); + + /* Serial interface */ + usbd_ep_setup(dev, 0x03, USB_ENDPOINT_ATTR_BULK, + CDCACM_PACKET_SIZE, usbuart_usb_out_cb); + usbd_ep_setup(dev, 0x83, USB_ENDPOINT_ATTR_BULK, + CDCACM_PACKET_SIZE, usbuart_usb_in_cb); + usbd_ep_setup(dev, 0x84, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL); + +#if defined(PLATFORM_HAS_TRACESWO) + /* Trace interface */ + usbd_ep_setup(dev, 0x85, USB_ENDPOINT_ATTR_BULK, + 64, trace_buf_drain); +#endif + + usbd_register_control_callback(dev, + USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE, + USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, + cdcacm_control_request); + + /* Notify the host that DCD is asserted. + * Allows the use of /dev/tty* devices on *BSD/MacOS + */ + char buf[10]; + struct usb_cdc_notification *notif = (void*)buf; + /* We echo signals back to host as notification */ + notif->bmRequestType = 0xA1; + notif->bNotification = USB_CDC_NOTIFY_SERIAL_STATE; + notif->wValue = 0; + notif->wIndex = 0; + notif->wLength = 2; + buf[8] = 3; /* DCD | DSR */ + buf[9] = 0; + usbd_ep_write_packet(dev, 0x82, buf, 10); + notif->wIndex = 2; + usbd_ep_write_packet(dev, 0x84, buf, 10); +} + +/* We need a special large control buffer for this device: */ +uint8_t usbd_control_buffer[256]; + +void cdcacm_init(void) +{ + get_dev_unique_id(serial_no); + + periph_clock_enable(RCC_GPIOD); + __asm__("nop"); __asm__("nop"); __asm__("nop"); + gpio_mode_setup(GPIOD_BASE, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO4|GPIO5); + + usbdev = usbd_init(&USB_DRIVER, &dev, &config, usb_strings, + sizeof(usb_strings)/sizeof(char *), + usbd_control_buffer, sizeof(usbd_control_buffer)); + + usbd_register_set_config_callback(usbdev, cdcacm_set_config); + + usb_enable_interrupts(USB_INT_RESET|USB_INT_DISCON|USB_INT_RESUME|USB_INT_SUSPEND, + 0xff, 0xff); + nvic_set_priority(USB_IRQ, IRQ_PRI_USB); + nvic_enable_irq(USB_IRQ); + setup_vbus_irq(); +} + +void USB_ISR(void) +{ + usbd_poll(usbdev); +} + +static char *get_dev_unique_id(char *s) +{ + /* FIXME: Store a unique serial number somewhere and retreive here */ + uint32_t unique_id = 1; + int i; + + /* Fetch serial number from chip's unique ID */ + for(i = 0; i < 8; i++) { + s[7-i] = ((unique_id >> (4*i)) & 0xF) + '0'; + } + for(i = 0; i < 8; i++) + if(s[i] > '9') + s[i] += 'A' - '9' - 1; + s[8] = 0; + + return s; +} diff --git a/src/platforms/tm4c/gdb_if.c b/src/platforms/tm4c/gdb_if.c new file mode 100644 index 0000000..b14bbd3 --- /dev/null +++ b/src/platforms/tm4c/gdb_if.c @@ -0,0 +1,100 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2011 Black Sphere Technologies Ltd. + * Written by Gareth McMullin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * 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, see . + */ + +/* This file implements a transparent channel over which the GDB Remote + * Serial Debugging protocol is implemented. This implementation for STM32 + * uses the USB CDC-ACM device bulk endpoints to implement the channel. + */ +#include "platform.h" +#include + +#include "gdb_if.h" + +static volatile uint32_t head_out, tail_out; +static volatile uint32_t count_in; +static volatile uint8_t buffer_out[16*CDCACM_PACKET_SIZE]; +static volatile uint8_t buffer_in[CDCACM_PACKET_SIZE]; + +void gdb_if_putchar(unsigned char c, int flush) +{ + buffer_in[count_in++] = c; + if(flush || (count_in == CDCACM_PACKET_SIZE)) { + /* Refuse to send if USB isn't configured, and + * don't bother if nobody's listening */ + if((cdcacm_get_config() != 1) || !cdcacm_get_dtr()) { + count_in = 0; + return; + } + while(usbd_ep_write_packet(usbdev, CDCACM_GDB_ENDPOINT, + (uint8_t *)buffer_in, count_in) <= 0); + count_in = 0; + } +} + +void gdb_usb_out_cb(usbd_device *dev, uint8_t ep) +{ + (void)ep; + static uint8_t buf[CDCACM_PACKET_SIZE]; + + usbd_ep_nak_set(dev, CDCACM_GDB_ENDPOINT, 1); + uint32_t count = usbd_ep_read_packet(dev, CDCACM_GDB_ENDPOINT, + (uint8_t *)buf, CDCACM_PACKET_SIZE); + + + uint32_t idx; + for (idx=0; idx ":"\n<- "); + + /* Don't turnaround if direction not changing */ + if(dir == olddir) return; + olddir = dir; + + if(dir) + SWDIO_MODE_FLOAT(); + gpio_set(SWCLK_PORT, SWCLK_PIN); + gpio_clear(SWCLK_PORT, SWCLK_PIN); + if(!dir) + SWDIO_MODE_DRIVE(); +} + +static uint8_t swdptap_bit_in(void) +{ + uint16_t ret; + + ret = gpio_get(SWDIO_PORT, SWDIO_PIN); + gpio_set(SWCLK_PORT, SWCLK_PIN); + gpio_clear(SWCLK_PORT, SWCLK_PIN); + + DEBUG("%d", ret?1:0); + + return ret != 0; +} + +static void swdptap_bit_out(uint8_t val) +{ + DEBUG("%d", val); + + gpio_set_val(SWDIO_PORT, SWDIO_PIN, val); + gpio_set(SWCLK_PORT, SWCLK_PIN); + gpio_clear(SWCLK_PORT, SWCLK_PIN); +} + +int +swdptap_init(void) +{ + swdptap_reset(); + swdptap_seq_out(0xE79E, 16); /* 0b0111100111100111 */ + swdptap_reset(); + swdptap_seq_out(0, 16); + + return 0; +} + +void +swdptap_reset(void) +{ + swdptap_turnaround(0); + /* 50 clocks with TMS high */ + for(int i = 0; i < 50; i++) swdptap_bit_out(1); +} + +uint32_t +swdptap_seq_in(int ticks) +{ + uint32_t index = 1; + uint32_t ret = 0; + + swdptap_turnaround(1); + + while(ticks--) { + if(swdptap_bit_in()) ret |= index; + index <<= 1; + } + + return ret; +} + +uint8_t +swdptap_seq_in_parity(uint32_t *ret, int ticks) +{ + uint32_t index = 1; + uint8_t parity = 0; + *ret = 0; + + swdptap_turnaround(1); + + while(ticks--) { + if(swdptap_bit_in()) { + *ret |= index; + parity ^= 1; + } + index <<= 1; + } + if(swdptap_bit_in()) parity ^= 1; + + return parity; +} + +void +swdptap_seq_out(uint32_t MS, int ticks) +{ + swdptap_turnaround(0); + + while(ticks--) { + swdptap_bit_out(MS & 1); + MS >>= 1; + } +} + +void +swdptap_seq_out_parity(uint32_t MS, int ticks) +{ + uint8_t parity = 0; + + swdptap_turnaround(0); + + while(ticks--) { + swdptap_bit_out(MS & 1); + parity ^= MS; + MS >>= 1; + } + swdptap_bit_out(parity & 1); +} diff --git a/src/platforms/tm4c/tm4c.ld b/src/platforms/tm4c/tm4c.ld new file mode 100644 index 0000000..8fe93a4 --- /dev/null +++ b/src/platforms/tm4c/tm4c.ld @@ -0,0 +1,29 @@ +/* + * This file is part of the libopenstm32 project. + * + * Copyright (C) 2010 Thomas Otto + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * 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, see . + */ + +/* Define memory regions. */ +MEMORY +{ + rom (rx) : ORIGIN = 0x00000000, LENGTH = 256K + ram (rwx) : ORIGIN = 0x20000000, LENGTH = 32K +} + +/* Include the common ld script from libopenstm32. */ +INCLUDE libopencm3_lm4f.ld + diff --git a/src/platforms/tm4c/traceswo.c b/src/platforms/tm4c/traceswo.c new file mode 100644 index 0000000..eb63139 --- /dev/null +++ b/src/platforms/tm4c/traceswo.c @@ -0,0 +1,165 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2012 Black Sphere Technologies Ltd. + * Written by Gareth McMullin + * + * Copyright (C) 2014 Fredrik Ahlberg + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * 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, see . + */ + +/* This file implements capture of the TRACESWO output. + * + * ARM DDI 0403D - ARMv7M Architecture Reference Manual + * ARM DDI 0337I - Cortex-M3 Technical Reference Manual + * ARM DDI 0314H - CoreSight Components Technical Reference Manual + */ + +#include "general.h" + +#include +#include +#include + +#include + +#include + +#include +#include "platform.h" + +void traceswo_init(void) +{ + periph_clock_enable(RCC_GPIOD); + periph_clock_enable(TRACEUART_CLK); + __asm__("nop"); __asm__("nop"); __asm__("nop"); + + gpio_mode_setup(SWO_PORT, GPIO_MODE_INPUT, GPIO_PUPD_NONE, SWO_PIN); + gpio_set_af(SWO_PORT, 1, SWO_PIN); /* U2RX */ + + uart_disable(TRACEUART); + + /* Setup UART parameters. */ + uart_clock_from_sysclk(TRACEUART); + uart_set_baudrate(TRACEUART, 800000); + uart_set_databits(TRACEUART, 8); + uart_set_stopbits(TRACEUART, 1); + uart_set_parity(TRACEUART, UART_PARITY_NONE); + + // Enable FIFO + uart_enable_fifo(TRACEUART); + + // Set FIFO interrupt trigger levels to 4/8 full for RX buffer and + // 7/8 empty (1/8 full) for TX buffer + uart_set_fifo_trigger_levels(TRACEUART, UART_FIFO_RX_TRIG_1_2, UART_FIFO_TX_TRIG_7_8); + + uart_clear_interrupt_flag(TRACEUART, UART_INT_RX | UART_INT_RT); + + /* Enable interrupts */ + uart_enable_interrupts(TRACEUART, UART_INT_RX | UART_INT_RT); + + /* Finally enable the USART. */ + uart_enable(TRACEUART); + + nvic_set_priority(TRACEUART_IRQ, 0); + nvic_enable_irq(TRACEUART_IRQ); + + /* Un-stall USB endpoint */ + usbd_ep_stall_set(usbdev, 0x85, 0); + + gpio_mode_setup(GPIOD, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO3); +} + +void traceswo_baud(unsigned int baud) +{ + uart_set_baudrate(TRACEUART, baud); + uart_set_databits(TRACEUART, 8); +} + +#define FIFO_SIZE 256 + +/* RX Fifo buffer */ +static volatile uint8_t buf_rx[FIFO_SIZE]; +/* Fifo in pointer, writes assumed to be atomic, should be only incremented within RX ISR */ +static volatile uint32_t buf_rx_in = 0; +/* Fifo out pointer, writes assumed to be atomic, should be only incremented outside RX ISR */ +static volatile uint32_t buf_rx_out = 0; + +void trace_buf_push(void) +{ + size_t len; + + if (buf_rx_in == buf_rx_out) { + return; + } else if (buf_rx_in > buf_rx_out) { + len = buf_rx_in - buf_rx_out; + } else { + len = FIFO_SIZE - buf_rx_out; + } + + if (len > 64) { + len = 64; + } + + if (usbd_ep_write_packet(usbdev, 0x85, (uint8_t *)&buf_rx[buf_rx_out], len) == len) { + buf_rx_out += len; + buf_rx_out %= FIFO_SIZE; + } +} + +void trace_buf_drain(usbd_device *dev, uint8_t ep) +{ + (void) dev; + (void) ep; + trace_buf_push(); +} + +void trace_tick(void) +{ + trace_buf_push(); +} + +void TRACEUART_ISR(void) +{ + uint32_t flush = uart_is_interrupt_source(TRACEUART, UART_INT_RT); + + while (!uart_is_rx_fifo_empty(TRACEUART)) { + uint32_t c = uart_recv(TRACEUART); + + /* If the next increment of rx_in would put it at the same point + * as rx_out, the FIFO is considered full. + */ + if (((buf_rx_in + 1) % FIFO_SIZE) != buf_rx_out) + { + /* insert into FIFO */ + buf_rx[buf_rx_in++] = c; + + /* wrap out pointer */ + if (buf_rx_in >= FIFO_SIZE) + { + buf_rx_in = 0; + } + } else { + flush = 1; + break; + } + } + + if (flush) { + /* advance fifo out pointer by amount written */ + trace_buf_push(); + } +} + diff --git a/src/platforms/tm4c/usbuart.c b/src/platforms/tm4c/usbuart.c new file mode 100644 index 0000000..bb769f0 --- /dev/null +++ b/src/platforms/tm4c/usbuart.c @@ -0,0 +1,182 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2012 Black Sphere Technologies Ltd. + * Written by Gareth McMullin + * + * Copyright (C) 2014 Fredrik Ahlberg + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * 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, see . + */ + +#include +#include +#include +#include +#include +#include + +#include + +#define FIFO_SIZE 128 + +/* RX Fifo buffer */ +static uint8_t buf_rx[FIFO_SIZE]; +/* Fifo in pointer, writes assumed to be atomic, should be only incremented within RX ISR */ +static uint8_t buf_rx_in; +/* Fifo out pointer, writes assumed to be atomic, should be only incremented outside RX ISR */ +static uint8_t buf_rx_out; + +void usbuart_init(void) +{ + UART_PIN_SETUP(); + + periph_clock_enable(USBUART_CLK); + __asm__("nop"); __asm__("nop"); __asm__("nop"); + + uart_disable(USBUART); + + /* Setup UART parameters. */ + uart_clock_from_sysclk(USBUART); + uart_set_baudrate(USBUART, 38400); + uart_set_databits(USBUART, 8); + uart_set_stopbits(USBUART, 1); + uart_set_parity(USBUART, UART_PARITY_NONE); + + // Enable FIFO + uart_enable_fifo(USBUART); + + // Set FIFO interrupt trigger levels to 1/8 full for RX buffer and + // 7/8 empty (1/8 full) for TX buffer + uart_set_fifo_trigger_levels(USBUART, UART_FIFO_RX_TRIG_1_8, UART_FIFO_TX_TRIG_7_8); + + uart_clear_interrupt_flag(USBUART, UART_INT_RX | UART_INT_RT); + + /* Enable interrupts */ + uart_enable_interrupts(UART0, UART_INT_RX| UART_INT_RT); + + /* Finally enable the USART. */ + uart_enable(USBUART); + + //nvic_set_priority(USBUSART_IRQ, IRQ_PRI_USBUSART); + nvic_enable_irq(USBUART_IRQ); +} + +void usbuart_set_line_coding(struct usb_cdc_line_coding *coding) +{ + uart_set_baudrate(USBUART, coding->dwDTERate); + uart_set_databits(USBUART, coding->bDataBits); + switch(coding->bCharFormat) { + case 0: + case 1: + uart_set_stopbits(USBUART, 1); + break; + case 2: + uart_set_stopbits(USBUART, 2); + break; + } + switch(coding->bParityType) { + case 0: + uart_set_parity(USBUART, UART_PARITY_NONE); + break; + case 1: + uart_set_parity(USBUART, UART_PARITY_ODD); + break; + case 2: + uart_set_parity(USBUART, UART_PARITY_EVEN); + break; + } +} + +void usbuart_usb_out_cb(usbd_device *dev, uint8_t ep) +{ + (void)ep; + + char buf[CDCACM_PACKET_SIZE]; + int len = usbd_ep_read_packet(dev, CDCACM_UART_ENDPOINT, + buf, CDCACM_PACKET_SIZE); + + for(int i = 0; i < len; i++) + uart_send_blocking(USBUART, buf[i]); +} + + +void usbuart_usb_in_cb(usbd_device *dev, uint8_t ep) +{ + (void) dev; + (void) ep; +} + +/* + * Read a character from the UART RX and stuff it in a software FIFO. + * Allowed to read from FIFO out pointer, but not write to it. + * Allowed to write to FIFO in pointer. + */ +void USBUART_ISR(void) +{ + int flush = uart_is_interrupt_source(USBUART, UART_INT_RT); + + while (!uart_is_rx_fifo_empty(USBUART)) { + char c = uart_recv(USBUART); + + /* If the next increment of rx_in would put it at the same point + * as rx_out, the FIFO is considered full. + */ + if (((buf_rx_in + 1) % FIFO_SIZE) != buf_rx_out) + { + /* insert into FIFO */ + buf_rx[buf_rx_in++] = c; + + /* wrap out pointer */ + if (buf_rx_in >= FIFO_SIZE) + { + buf_rx_in = 0; + } + } else { + flush = 1; + } + } + + if (flush) { + /* forcibly empty fifo if no USB endpoint */ + if (cdcacm_get_config() != 1) + { + buf_rx_out = buf_rx_in; + return; + } + + uint8_t packet_buf[CDCACM_PACKET_SIZE]; + uint8_t packet_size = 0; + uint8_t buf_out = buf_rx_out; + + /* copy from uart FIFO into local usb packet buffer */ + while (buf_rx_in != buf_out && packet_size < CDCACM_PACKET_SIZE) + { + packet_buf[packet_size++] = buf_rx[buf_out++]; + + /* wrap out pointer */ + if (buf_out >= FIFO_SIZE) + { + buf_out = 0; + } + + } + + /* advance fifo out pointer by amount written */ + buf_rx_out += usbd_ep_write_packet(usbdev, + CDCACM_UART_ENDPOINT, packet_buf, packet_size); + buf_rx_out %= FIFO_SIZE; + } +} + -- cgit v1.2.3 From d162e75ceb92de346951b979cee5941bdd6ef651 Mon Sep 17 00:00:00 2001 From: Uwe Bonnes Date: Thu, 18 Dec 2014 11:12:09 +0100 Subject: stm32f4.c: Add STM32F411 ID. --- src/stm32f1.c | 16 +++++++++++++--- src/stm32f4.c | 5 +++-- src/stm32l1.c | 9 ++++++--- 3 files changed, 22 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/stm32f1.c b/src/stm32f1.c index 237135f..d02a26d 100644 --- a/src/stm32f1.c +++ b/src/stm32f1.c @@ -59,8 +59,10 @@ static const char stm32f1_driver_str[] = "STM32, Medium density."; static const char stm32hd_driver_str[] = "STM32, High density."; static const char stm32f3_driver_str[] = "STM32F3xx"; static const char stm32f03_driver_str[] = "STM32F03x"; +static const char stm32f04_driver_str[] = "STM32F04x"; static const char stm32f05_driver_str[] = "STM32F05x"; static const char stm32f07_driver_str[] = "STM32F07x"; +static const char stm32f09_driver_str[] = "STM32F09x"; static const char stm32f1_xml_memory_map[] = "" /* "idcode = adiv5_ap_mem_read(adiv5_target_ap(target), DBGMCU_IDCODE_F0) & 0xfff; switch(target->idcode) { - case 0x444: /* STM32F03 */ - case 0x440: /* STM32F05 */ - case 0x448: /* STM32F07 */ + case 0x444: /* STM32F03 RM0091 Rev.7 */ + case 0x445: /* STM32F04 RM0091 Rev.7 */ + case 0x440: /* STM32F05 RM0091 Rev.7 */ + case 0x448: /* STM32F07 RM0091 Rev.7 */ + case 0x442: /* STM32F09 RM0091 Rev.7 */ switch(target->idcode) { case 0x444: /* STM32F03 */ target->driver = stm32f03_driver_str; break; + case 0x445: /* STM32F04 */ + target->driver = stm32f04_driver_str; + break; case 0x440: /* STM32F05 */ target->driver = stm32f05_driver_str; break; case 0x448: /* STM32F07 */ target->driver = stm32f07_driver_str; break; + case 0x442: /* STM32F09 */ + target->driver = stm32f09_driver_str; + break; } target->xml_mem_map = stm32f1_xml_memory_map; target->flash_erase = stm32md_flash_erase; diff --git a/src/stm32f4.c b/src/stm32f4.c index 892af41..4f27859 100644 --- a/src/stm32f4.c +++ b/src/stm32f4.c @@ -170,8 +170,9 @@ bool stm32f4_probe(struct target_s *target) case 0x411: /* Documented to be 0x413! This is what I read... */ case 0x413: /* F407VGT6 */ case 0x419: /* 427/437 */ - case 0x423: /* F401 */ - case 0x433: /* F401RET6U */ + case 0x423: /* F401 B/C RM0368 Rev.3 */ + case 0x431: /* F411 RM0383 Rev.4 */ + case 0x433: /* F401 D/E RM0368 Rev.3 */ target->xml_mem_map = stm32f4_xml_memory_map; target->driver = stm32f4_driver_str; target->flash_erase = stm32f4_flash_erase; diff --git a/src/stm32l1.c b/src/stm32l1.c index 873d9b9..0472885 100644 --- a/src/stm32l1.c +++ b/src/stm32l1.c @@ -91,9 +91,12 @@ bool stm32l1_probe(struct target_s *target) idcode = adiv5_ap_mem_read(adiv5_target_ap(target), STM32L1_DBGMCU_IDCODE); switch(idcode & 0xFFF) { - case 0x416: /* Medium density */ - case 0x427: /* Medium+ density*/ - case 0x436: /* Medium+/High density */ + case 0x416: /* CAT. 1 device */ + case 0x429: /* CAT. 2 device */ + case 0x427: /* CAT. 3 device */ + case 0x436: /* CAT. 4 device */ + case 0x437: /* CAT. 5 device */ + target->idcode = idcode & 0xFFF; target->driver = stm32l1_driver_str; target->xml_mem_map = stm32l1_xml_memory_map; target->flash_erase = stm32l1_flash_erase; -- cgit v1.2.3 From 9c5ffd61f7d654418c76015f0073e4accbf9e004 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Tue, 6 Jan 2015 22:26:00 +1300 Subject: First cut at Freescale Kinetis support. --- src/Makefile | 1 + src/adiv5.c | 20 +++++++ src/cortexm.c | 1 + src/include/adiv5.h | 2 + src/include/target.h | 1 + src/kinetis.c | 154 +++++++++++++++++++++++++++++++++++++++++++++++++++ 6 files changed, 179 insertions(+) create mode 100644 src/kinetis.c (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 62cc617..b30922c 100644 --- a/src/Makefile +++ b/src/Makefile @@ -27,6 +27,7 @@ SRC = \ lmi.c \ lpc11xx.c \ lpc43xx.c \ + kinetis.c \ main.c \ nrf51.c \ platform.c \ diff --git a/src/adiv5.c b/src/adiv5.c index e7f45c9..6dcc919 100644 --- a/src/adiv5.c +++ b/src/adiv5.c @@ -414,6 +414,26 @@ void adiv5_ap_mem_write_halfword(ADIv5_AP_t *ap, uint32_t addr, uint16_t value) adiv5_ap_write(ap, ADIV5_AP_DRW, v); } +uint8_t adiv5_ap_mem_read_byte(ADIv5_AP_t *ap, uint32_t addr) +{ + adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw | + ADIV5_AP_CSW_SIZE_BYTE | ADIV5_AP_CSW_ADDRINC_SINGLE); + adiv5_ap_write(ap, ADIV5_AP_TAR, addr); + uint32_t v = adiv5_ap_read(ap, ADIV5_AP_DRW); + + return v >> ((addr & 3) * 8); +} + +void adiv5_ap_mem_write_byte(ADIv5_AP_t *ap, uint32_t addr, uint8_t value) +{ + uint32_t v = value << ((addr & 3) * 8); + + adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw | + ADIV5_AP_CSW_SIZE_BYTE | ADIV5_AP_CSW_ADDRINC_SINGLE); + adiv5_ap_write(ap, ADIV5_AP_TAR, addr); + adiv5_ap_write(ap, ADIV5_AP_DRW, v); +} + void adiv5_ap_write(ADIv5_AP_t *ap, uint8_t addr, uint32_t value) { adiv5_dp_write(ap->dp, ADIV5_DP_SELECT, diff --git a/src/cortexm.c b/src/cortexm.c index 3ac960c..731632e 100644 --- a/src/cortexm.c +++ b/src/cortexm.c @@ -386,6 +386,7 @@ cortexm_probe(struct target_s *target) PROBE(nrf51_probe); PROBE(samd20_probe); PROBE(lmi_probe); + PROBE(kinetis_probe); #undef PROBE return true; diff --git a/src/include/adiv5.h b/src/include/adiv5.h index 64b6a28..0f17119 100644 --- a/src/include/adiv5.h +++ b/src/include/adiv5.h @@ -172,6 +172,8 @@ uint32_t adiv5_ap_mem_read(ADIv5_AP_t *ap, uint32_t addr); void adiv5_ap_mem_write(ADIv5_AP_t *ap, uint32_t addr, uint32_t value); uint16_t adiv5_ap_mem_read_halfword(ADIv5_AP_t *ap, uint32_t addr); void adiv5_ap_mem_write_halfword(ADIv5_AP_t *ap, uint32_t addr, uint16_t value); +uint8_t adiv5_ap_mem_read_byte(ADIv5_AP_t *ap, uint32_t addr); +void adiv5_ap_mem_write_byte(ADIv5_AP_t *ap, uint32_t addr, uint8_t value); void adiv5_ap_write(ADIv5_AP_t *ap, uint8_t addr, uint32_t value); uint32_t adiv5_ap_read(ADIv5_AP_t *ap, uint8_t addr); diff --git a/src/include/target.h b/src/include/target.h index f28f2f8..100c4a0 100644 --- a/src/include/target.h +++ b/src/include/target.h @@ -225,6 +225,7 @@ bool lpc43xx_probe(struct target_s *target); bool sam3x_probe(struct target_s *target); bool nrf51_probe(struct target_s *target); bool samd20_probe(struct target_s *target); +bool kinetis_probe(struct target_s *target); #endif diff --git a/src/kinetis.c b/src/kinetis.c new file mode 100644 index 0000000..393bb18 --- /dev/null +++ b/src/kinetis.c @@ -0,0 +1,154 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2015 Black Sphere Technologies Ltd. + * Written by Gareth McMullin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * 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, see . + */ + +/* This file implements KL25 target specific functions providing + * the XML memory map and Flash memory programming. + */ + +#include +#include + +#include "general.h" +#include "adiv5.h" +#include "target.h" + +#define SIM_SDID 0x40048024 + +#define FTFA_BASE 0x40020000 +#define FTFA_FSTAT (FTFA_BASE + 0x00) +#define FTFA_FCNFG (FTFA_BASE + 0x01) +#define FTFA_FSEC (FTFA_BASE + 0x02) +#define FTFA_FOPT (FTFA_BASE + 0x03) +#define FTFA_FCCOB(x) (FTFA_BASE + 0x04 + ((x) ^ 3)) + +#define FTFA_FSTAT_CCIF (1 << 7) +#define FTFA_FSTAT_RDCOLERR (1 << 6) +#define FTFA_FSTAT_ACCERR (1 << 5) +#define FTFA_FSTAT_FPVIOL (1 << 4) +#define FTFA_FSTAT_MGSTAT0 (1 << 0) + +#define FTFA_CMD_CHECK_ERASE 0x01 +#define FTFA_CMD_PROGRAM_CHECK 0x02 +#define FTFA_CMD_READ_RESOURCE 0x03 +#define FTFA_CMD_PROGRAM_LONGWORD 0x06 +#define FTFA_CMD_ERASE_SECTOR 0x09 +#define FTFA_CMD_CHECK_ERASE_ALL 0x40 +#define FTFA_CMD_READ_ONCE 0x41 +#define FTFA_CMD_PROGRAM_ONCE 0x43 +#define FTFA_CMD_ERASE_ALL 0x44 +#define FTFA_CMD_BACKDOOR_ACCESS 0x45 + +#define KL25_PAGESIZE 0x400 + +static int kl25_flash_erase(struct target_s *target, uint32_t addr, int len); +static int kl25_flash_write(struct target_s *target, uint32_t dest, + const uint8_t *src, int len); + +static const char kl25_xml_memory_map[] = "" +/* ""*/ + "" + " " + " 0x400" + " " + " " + " " + ""; + +bool kinetis_probe(struct target_s *t) +{ + uint32_t sdid = adiv5_ap_mem_read(adiv5_target_ap(t), SIM_SDID); + switch (sdid >> 20) { + case 0x251: + t->driver = "KL25"; + t->xml_mem_map = kl25_xml_memory_map; + t->flash_erase = kl25_flash_erase; + t->flash_write = kl25_flash_write; + return true; + } + return false; +} + +static bool +kl25_command(struct target_s *t, uint8_t cmd, uint32_t addr, const uint8_t data[8]) +{ + ADIv5_AP_t *ap = adiv5_target_ap(t); + uint8_t fstat; + + /* Wait for CCIF to be high */ + do { + fstat = adiv5_ap_mem_read_byte(ap, FTFA_FSTAT); + /* Check ACCERR and FPVIOL are zero in FSTAT */ + if (fstat & (FTFA_FSTAT_ACCERR | FTFA_FSTAT_FPVIOL)) + return false; + } while (!(fstat & FTFA_FSTAT_CCIF)); + + /* Write command to FCCOB */ + addr &= 0xffffff; + addr |= (uint32_t)cmd << 24; + adiv5_ap_mem_write(ap, FTFA_FCCOB(0), addr); + if (data) { + adiv5_ap_mem_write(ap, FTFA_FCCOB(4), *(uint32_t*)&data[0]); + adiv5_ap_mem_write(ap, FTFA_FCCOB(8), *(uint32_t*)&data[4]); + } + + /* Enable execution by clearing CCIF */ + adiv5_ap_mem_write_byte(ap, FTFA_FSTAT, FTFA_FSTAT_CCIF); + + /* Wait for execution to complete */ + do { + fstat = adiv5_ap_mem_read_byte(ap, FTFA_FSTAT); + /* Check ACCERR and FPVIOL are zero in FSTAT */ + if (fstat & (FTFA_FSTAT_ACCERR | FTFA_FSTAT_FPVIOL)) + return false; + } while (!(fstat & FTFA_FSTAT_CCIF)); + + return true; +} + +static int kl25_flash_erase(struct target_s *t, uint32_t addr, int len) +{ + addr &= ~(KL25_PAGESIZE - 1); + len = (len + KL25_PAGESIZE - 1) & ~(KL25_PAGESIZE - 1); + + while (len) { + kl25_command(t, FTFA_CMD_ERASE_SECTOR, addr, NULL); + len -= KL25_PAGESIZE; + addr += KL25_PAGESIZE; + } + return 0; +} + +static int kl25_flash_write(struct target_s *t, uint32_t dest, + const uint8_t *src, int len) +{ + /* FIXME handle misaligned start and end of sections */ + if ((dest & 3) || (len & 3)) + return -1; + + while (len) { + kl25_command(t, FTFA_CMD_PROGRAM_LONGWORD, dest, src); + len -= 4; + dest += 4; + src += 4; + } + return 0; +} -- cgit v1.2.3 From da28970c3e164d4166cb8a3e0fe59c804299ed32 Mon Sep 17 00:00:00 2001 From: Marc Singer Date: Fri, 9 Jan 2015 17:53:18 -0800 Subject: Fix to move stubs into rodata. o Stubs were declared as globals which means they will be initialized data. No need for this. Now, stubs are static const and are only present in the program image. --- src/lmi.c | 2 +- src/nrf51.c | 2 +- src/stm32f1.c | 2 +- src/stm32f4.c | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/lmi.c b/src/lmi.c index a08819e..a251242 100644 --- a/src/lmi.c +++ b/src/lmi.c @@ -63,7 +63,7 @@ static const char tm4c123gh6pm_xml_memory_map[] = "" ""; -uint16_t lmi_flash_write_stub[] = { +static const uint16_t lmi_flash_write_stub[] = { // _start: 0x4809, // ldr r0, [pc, #36] // _flashbase 0x490b, // ldr r1, [pc, #44] // _addr diff --git a/src/nrf51.c b/src/nrf51.c index 52c9749..7305d29 100644 --- a/src/nrf51.c +++ b/src/nrf51.c @@ -98,7 +98,7 @@ static const char nrf51_xml_memory_map[] = "" #define NRF51_PAGE_SIZE 1024 -uint16_t nrf51_flash_write_stub[] = { +static const uint16_t nrf51_flash_write_stub[] = { // _start: 0x4808, // ldr r0, [pc, #32] ; (24 <_ready>) 0x4909, // ldr r1, [pc, #36] ; (28 <_addr>) diff --git a/src/stm32f1.c b/src/stm32f1.c index d02a26d..bce00d3 100644 --- a/src/stm32f1.c +++ b/src/stm32f1.c @@ -122,7 +122,7 @@ static const char stm32hd_xml_memory_map[] = "" #define DBGMCU_IDCODE 0xE0042000 #define DBGMCU_IDCODE_F0 0x40015800 -uint16_t stm32f1_flash_write_stub[] = { +static const uint16_t stm32f1_flash_write_stub[] = { // _start: 0x4809, // ldr r0, [pc, #36] // _flashbase 0x490a, // ldr r1, [pc, #40] // _addr diff --git a/src/stm32f4.c b/src/stm32f4.c index 4f27859..148c31b 100644 --- a/src/stm32f4.c +++ b/src/stm32f4.c @@ -122,7 +122,7 @@ static const char stm32f4_xml_memory_map[] = "" #define DBGMCU_IDCODE 0xE0042000 /* This routine is uses word access. Only usable on target voltage >2.7V */ -uint16_t stm32f4_flash_write_stub[] = { +static const uint16_t stm32f4_flash_write_stub[] = { // _start: 0x480a, // ldr r0, [pc, #40] // _flashbase 0x490b, // ldr r1, [pc, #44] // _addr -- cgit v1.2.3 From 985627af7e45207d3bbeab4e4261ed7241674c73 Mon Sep 17 00:00:00 2001 From: David Lawrence Date: Mon, 12 Jan 2015 14:42:58 -0500 Subject: SAM4S support --- src/sam3x.c | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 88 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/sam3x.c b/src/sam3x.c index 79dca3d..38a3ef7 100644 --- a/src/sam3x.c +++ b/src/sam3x.c @@ -68,9 +68,22 @@ static const char sam3n_xml_memory_map[] = "" " " ""; +static const char sam4s_xml_memory_map[] = "" +/* ""*/ + "" + " " + " 0x200" + " " + " " + " " + ""; + /* Enhanced Embedded Flash Controller (EEFC) Register Map */ #define SAM3N_EEFC_BASE 0x400E0A00 #define SAM3X_EEFC_BASE(x) (0x400E0A00+((x)*0x400)) +#define SAM4S_EEFC_BASE(x) (0x400E0A00+((x)*0x200)) #define EEFC_FMR(base) ((base)+0x00) #define EEFC_FCR(base) ((base)+0x04) #define EEFC_FSR(base) ((base)+0x08) @@ -99,14 +112,18 @@ static const char sam3n_xml_memory_map[] = "" #define SAM3X_CHIPID_CIDR 0x400E0940 #define SAM3N_CHIPID_CIDR 0x400E0740 +#define SAM4S_CHIPID_CIDR 0x400E0740 #define CHIPID_CIDR_VERSION_MASK (0x1F << 0) #define CHIPID_CIDR_EPROC_CM3 (0x03 << 5) +#define CHIPID_CIDR_EPROC_CM4 (0x07 << 5) #define CHIPID_CIDR_EPROC_MASK (0x07 << 5) #define CHIPID_CIDR_NVPSIZ_MASK (0x0F << 8) #define CHIPID_CIDR_NVPSIZ_128K (0x07 << 8) #define CHIPID_CIDR_NVPSIZ_256K (0x09 << 8) #define CHIPID_CIDR_NVPSIZ_512K (0x0A << 8) +#define CHIPID_CIDR_NVPSIZ_1024K (0x0C << 8) +#define CHIPID_CIDR_NVPSIZ_2048K (0x0E << 8) #define CHIPID_CIDR_NVPSIZ2_MASK (0x0F << 12) #define CHIPID_CIDR_SRAMSIZ_MASK (0x0F << 16) #define CHIPID_CIDR_ARCH_MASK (0xFF << 20) @@ -116,12 +133,16 @@ static const char sam3n_xml_memory_map[] = "" #define CHIPID_CIDR_ARCH_SAM3NxA (0x93 << 20) #define CHIPID_CIDR_ARCH_SAM3NxB (0x94 << 20) #define CHIPID_CIDR_ARCH_SAM3NxC (0x95 << 20) +#define CHIPID_CIDR_ARCH_SAM4SxA (0x88 << 20) +#define CHIPID_CIDR_ARCH_SAM4SxB (0x89 << 20) +#define CHIPID_CIDR_ARCH_SAM4SxC (0x8A << 20) #define CHIPID_CIDR_NVPTYP_MASK (0x07 << 28) #define CHIPID_CIDR_NVPTYP_FLASH (0x02 << 28) #define CHIPID_CIDR_NVPTYP_ROM_FLASH (0x03 << 28) #define CHIPID_CIDR_EXT (0x01 << 31) -#define PAGE_SIZE 256 +#define SAM3_PAGE_SIZE 256 +#define SAM4_PAGE_SIZE 512 bool sam3x_probe(struct target_s *target) { @@ -155,6 +176,19 @@ bool sam3x_probe(struct target_s *target) return true; } + target->idcode = adiv5_ap_mem_read(ap, SAM4S_CHIPID_CIDR); + switch (target->idcode & (CHIPID_CIDR_ARCH_MASK | CHIPID_CIDR_EPROC_MASK)) { + case CHIPID_CIDR_ARCH_SAM4SxA | CHIPID_CIDR_EPROC_CM4: + case CHIPID_CIDR_ARCH_SAM4SxB | CHIPID_CIDR_EPROC_CM4: + case CHIPID_CIDR_ARCH_SAM4SxC | CHIPID_CIDR_EPROC_CM4: + target->driver = "Atmel SAM4S"; + target->xml_mem_map = sam4s_xml_memory_map; + target->flash_erase = sam3x_flash_erase; + target->flash_write = sam3x_flash_write; + target_add_commands(target, sam3x_cmd_list, "SAM4S"); + return true; + } + return false; } @@ -203,6 +237,33 @@ sam3x_flash_base(struct target_s *target, uint32_t addr, uint32_t *offset) } } + if (strcmp(target->driver, "Atmel SAM4S") == 0) { + uint32_t half = -1; + switch (target->idcode & CHIPID_CIDR_NVPSIZ_MASK) { + case CHIPID_CIDR_NVPSIZ_128K: + case CHIPID_CIDR_NVPSIZ_256K: + case CHIPID_CIDR_NVPSIZ_512K: + if (offset) + *offset = addr - 0x400000; + return SAM4S_EEFC_BASE(0); + case CHIPID_CIDR_NVPSIZ_1024K: + half = 0x480000; + break; + case CHIPID_CIDR_NVPSIZ_2048K: + half = 0x500000; + break; + } + if (addr >= half) { + if (offset) + *offset = addr - half; + return SAM4S_EEFC_BASE(1); + } else { + if (offset) + *offset = addr - 0x400000; + return SAM4S_EEFC_BASE(0); + } + } + /* SAM3N device */ if (offset) *offset = addr - 0x400000; @@ -211,10 +272,16 @@ sam3x_flash_base(struct target_s *target, uint32_t addr, uint32_t *offset) static int sam3x_flash_erase(struct target_s *target, uint32_t addr, int len) { + unsigned page_size; + if (strcmp(target->driver, "Atmel SAM4S") == 0) { + page_size = SAM4_PAGE_SIZE; + } else { + page_size = SAM3_PAGE_SIZE; + } uint32_t offset; uint32_t base = sam3x_flash_base(target, addr, &offset); - unsigned chunk = offset / PAGE_SIZE; - uint8_t buf[PAGE_SIZE]; + unsigned chunk = offset / page_size; + uint8_t buf[page_size]; /* This device doesn't really have a page erase function. * This Erase/Write page is the best we have, so we write with all @@ -223,14 +290,14 @@ static int sam3x_flash_erase(struct target_s *target, uint32_t addr, int len) memset(buf, 0xff, sizeof(buf)); /* Only do this once, since it doesn't change. */ - target_mem_write_words(target, addr, (void*)buf, PAGE_SIZE); + target_mem_write_words(target, addr, (void*)buf, page_size); while (len) { if(sam3x_flash_cmd(target, base, EEFC_FCR_FCMD_EWP, chunk)) return -1; - len -= PAGE_SIZE; - addr += PAGE_SIZE; + len -= page_size; + addr += page_size; chunk++; } @@ -240,12 +307,18 @@ static int sam3x_flash_erase(struct target_s *target, uint32_t addr, int len) static int sam3x_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, int len) { + unsigned page_size; + if (strcmp(target->driver, "Atmel SAM4S") == 0) { + page_size = SAM4_PAGE_SIZE; + } else { + page_size = SAM3_PAGE_SIZE; + } uint32_t offset; uint32_t base = sam3x_flash_base(target, dest, &offset); - uint8_t buf[PAGE_SIZE]; - unsigned first_chunk = offset / PAGE_SIZE; - unsigned last_chunk = (offset + len - 1) / PAGE_SIZE; - offset %= PAGE_SIZE; + uint8_t buf[page_size]; + unsigned first_chunk = offset / page_size; + unsigned last_chunk = (offset + len - 1) / page_size; + offset %= page_size; dest -= offset; for (unsigned chunk = first_chunk; chunk <= last_chunk; chunk++) { @@ -258,7 +331,7 @@ static int sam3x_flash_write(struct target_s *target, uint32_t dest, memset(buf, 0xff, sizeof(buf)); /* copy as much as fits */ - int copylen = PAGE_SIZE - offset; + int copylen = page_size - offset; if (copylen > len) copylen = len; memcpy(&buf[offset], src, copylen); @@ -270,12 +343,12 @@ static int sam3x_flash_write(struct target_s *target, uint32_t dest, } else { /* interior chunk, must be aligned and full-sized */ - memcpy(buf, src, PAGE_SIZE); - len -= PAGE_SIZE; - src += PAGE_SIZE; + memcpy(buf, src, page_size); + len -= page_size; + src += page_size; } - target_mem_write_words(target, dest, (void*)buf, PAGE_SIZE); + target_mem_write_words(target, dest, (void*)buf, page_size); if(sam3x_flash_cmd(target, base, EEFC_FCR_FCMD_WP, chunk)) return -1; } -- cgit v1.2.3 From c12002b63625021ba345bb2cd9d1f21bed9a2c5d Mon Sep 17 00:00:00 2001 From: Richard Meadows Date: Fri, 16 Jan 2015 21:52:19 +0000 Subject: Check target_attach succeeded in vRun command, and return error if not --- src/gdb_main.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/gdb_main.c b/src/gdb_main.c index dc56a59..83ceeff 100644 --- a/src/gdb_main.c +++ b/src/gdb_main.c @@ -406,8 +406,13 @@ handle_v_packet(char *packet, int plen) } else if(last_target) { cur_target = target_attach(last_target, gdb_target_destroy_callback); - target_reset(cur_target); - gdb_putpacketz("T05"); + + /* If we were able to attach to the target again */ + if (cur_target) { + target_reset(cur_target); + gdb_putpacketz("T05"); + } else gdb_putpacketz("E01"); + } else gdb_putpacketz("E01"); } else if (sscanf(packet, "vFlashErase:%08lx,%08lx", &addr, &len) == 2) { -- cgit v1.2.3 From 9072faf6ca1478f21d6bbf46265893a04ae23598 Mon Sep 17 00:00:00 2001 From: Richard Meadows Date: Sat, 17 Jan 2015 18:35:36 +0000 Subject: Fixed spaces / tabs from last commit --- src/gdb_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/gdb_main.c b/src/gdb_main.c index 83ceeff..41ab84a 100644 --- a/src/gdb_main.c +++ b/src/gdb_main.c @@ -410,8 +410,8 @@ handle_v_packet(char *packet, int plen) /* If we were able to attach to the target again */ if (cur_target) { target_reset(cur_target); - gdb_putpacketz("T05"); - } else gdb_putpacketz("E01"); + gdb_putpacketz("T05"); + } else gdb_putpacketz("E01"); } else gdb_putpacketz("E01"); -- cgit v1.2.3 From cad30cfa39fcf321560914d7a0a068ed5e8a5cb5 Mon Sep 17 00:00:00 2001 From: Richard Meadows Date: Sat, 17 Jan 2015 18:58:00 +0000 Subject: Fixed run command on SAM D20 old revision B silicon. This appears to be related to Atmel Errata Reference 12015 (see § 35.4.1 DSU in the datasheet) but only applies to revision B silicon - not revision C. While this is an old silicion revision (latest is revision E as of 17 Jan 2015) I found one on a development board. --- src/samd20.c | 131 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) (limited to 'src') diff --git a/src/samd20.c b/src/samd20.c index fec0180..8b79049 100644 --- a/src/samd20.c +++ b/src/samd20.c @@ -198,6 +198,51 @@ static const char samd20_xml_memory_map[] = "" #define CORTEXM_DHCSR_C_HALT (1 << 1) #define CORTEXM_DHCSR_C_DEBUGEN (1 << 0) + +/* -------------------------------------------------------------------------- */ +/* Cortex-M definitions for SAM D20 revision B fix */ +/* -------------------------------------------------------------------------- */ + +#define CORTEXM_FPB_BASE (CORTEXM_PPB_BASE + 0x2000) + +/* ARM Literature uses FP_*, we use CORTEXM_FPB_* consistently */ +#define CORTEXM_FPB_CTRL (CORTEXM_FPB_BASE + 0x000) +#define CORTEXM_FPB_REMAP (CORTEXM_FPB_BASE + 0x004) +#define CORTEXM_FPB_COMP(i) (CORTEXM_FPB_BASE + 0x008 + (4*(i))) + +#define CORTEXM_DWT_BASE (CORTEXM_PPB_BASE + 0x1000) + +#define CORTEXM_DWT_CTRL (CORTEXM_DWT_BASE + 0x000) +#define CORTEXM_DWT_COMP(i) (CORTEXM_DWT_BASE + 0x020 + (0x10*(i))) +#define CORTEXM_DWT_MASK(i) (CORTEXM_DWT_BASE + 0x024 + (0x10*(i))) +#define CORTEXM_DWT_FUNC(i) (CORTEXM_DWT_BASE + 0x028 + (0x10*(i))) + +#define CORTEXM_MAX_WATCHPOINTS 4 /* architecture says up to 15, no implementation has > 4 */ +#define CORTEXM_MAX_BREAKPOINTS 6 /* architecture says up to 127, no implementation has > 6 */ + +struct cortexm_priv { + bool stepping; + bool on_bkpt; + /* Watchpoint unit status */ + struct wp_unit_s { + uint32_t addr; + uint8_t type; + uint8_t size; + } hw_watchpoint[CORTEXM_MAX_WATCHPOINTS]; + unsigned hw_watchpoint_max; + /* Breakpoint unit status */ + uint32_t hw_breakpoint[CORTEXM_MAX_BREAKPOINTS]; + unsigned hw_breakpoint_max; + /* Copy of DEMCR for vector-catch */ + uint32_t demcr; + /* Semihosting state */ + uint32_t syscall; + uint32_t errno; + uint32_t byte_count; +}; + + + /* Utility */ #define MINIMUM(a,b) ((a < b) ? a : b) @@ -285,6 +330,81 @@ samd20_reset(struct target_s *target) target_check_error(target); } +/** + * Overloads the default cortexm detached function with a version that + * removes the target from extended reset where required. + * + * Only required for SAM D20 _Revision B_ Silicon + */ +static void +samd20_revB_detach(struct target_s *target) +{ + ADIv5_AP_t *ap = adiv5_target_ap(target); + struct cortexm_priv *priv = ap->priv; + unsigned i; + + /* Clear any stale breakpoints */ + for(i = 0; i < priv->hw_breakpoint_max; i++) + adiv5_ap_mem_write(ap, CORTEXM_FPB_COMP(i), 0); + + /* Clear any stale watchpoints */ + for(i = 0; i < priv->hw_watchpoint_max; i++) + adiv5_ap_mem_write(ap, CORTEXM_DWT_FUNC(i), 0); + + /* Disable debug */ + adiv5_ap_mem_write(ap, CORTEXM_DHCSR, CORTEXM_DHCSR_DBGKEY); + + /* ---- Additional ---- */ + /* Exit extended reset */ + if (adiv5_ap_mem_read(ap, SAMD20_DSU_CTRLSTAT) & + SAMD20_STATUSA_CRSTEXT) { + /* Write bit to clear from extended reset */ + adiv5_ap_mem_write(ap, SAMD20_DSU_CTRLSTAT, + SAMD20_STATUSA_CRSTEXT); + } +} + +/** + * Overloads the default cortexm halt_resume function with a version + * that removes the target from extended reset where required. + * + * Only required for SAM D20 _Revision B_ Silicon + */ +static void +samd20_revB_halt_resume(struct target_s *target, bool step) +{ + ADIv5_AP_t *ap = adiv5_target_ap(target); + struct cortexm_priv *priv = ap->priv; + uint32_t dhcsr = CORTEXM_DHCSR_DBGKEY | CORTEXM_DHCSR_C_DEBUGEN; + + if(step) dhcsr |= CORTEXM_DHCSR_C_STEP | CORTEXM_DHCSR_C_MASKINTS; + + /* Disable interrupts while single stepping... */ + if(step != priv->stepping) { + adiv5_ap_mem_write(ap, CORTEXM_DHCSR, dhcsr | CORTEXM_DHCSR_C_HALT); + priv->stepping = step; + } + + if (priv->on_bkpt) { + uint32_t pc = target->pc_read(target); + if ((adiv5_ap_mem_read_halfword(ap, pc) & 0xFF00) == 0xBE00) + target->pc_write(target, pc + 2); + } + + adiv5_ap_mem_write(ap, CORTEXM_DHCSR, dhcsr); + ap->dp->allow_timeout = true; + + /* ---- Additional ---- */ + /* Exit extended reset */ + if (adiv5_ap_mem_read(ap, SAMD20_DSU_CTRLSTAT) & + SAMD20_STATUSA_CRSTEXT) { + /* Write bit to clear from extended reset */ + adiv5_ap_mem_write(ap, SAMD20_DSU_CTRLSTAT, + SAMD20_STATUSA_CRSTEXT); + } +} + + char variant_string[30]; bool samd20_probe(struct target_s *target) { @@ -329,6 +449,17 @@ bool samd20_probe(struct target_s *target) /* Setup Target */ target->driver = variant_string; target->reset = samd20_reset; + + if (revision_variant == 'B') { + /** + * These functions check for and + * extended reset. Appears to be + * related to Errata 35.4.1 ref 12015 + */ + target->detach = samd20_revB_detach; + target->halt_resume = samd20_revB_halt_resume; + } + target->xml_mem_map = samd20_xml_memory_map; target->flash_erase = samd20_flash_erase; target->flash_write = samd20_flash_write; -- cgit v1.2.3 From a3ab9b24d1c3b4dd6678fc88289f0cf397e52c6c Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sun, 18 Jan 2015 12:16:17 +1300 Subject: Avoid repetition of cortexm code in stmd20 driver. --- src/cortexm.c | 134 ++------------------------------------------------ src/include/cortexm.h | 130 ++++++++++++++++++++++++++++++++++++++++++++++++ src/samd20.c | 133 ++----------------------------------------------- 3 files changed, 138 insertions(+), 259 deletions(-) create mode 100644 src/include/cortexm.h (limited to 'src') diff --git a/src/cortexm.c b/src/cortexm.c index 731632e..b7f71eb 100644 --- a/src/cortexm.c +++ b/src/cortexm.c @@ -40,6 +40,7 @@ #include "target.h" #include "command.h" #include "gdb_packet.h" +#include "cortexm.h" static char cortexm_driver_str[] = "ARM Cortex-M"; @@ -54,142 +55,18 @@ const struct command_s cortexm_cmd_list[] = { #define TOPT_FLAVOUR_V6M (1<<0) /* if not set, target is assumed to be v7m */ #define TOPT_FLAVOUR_V7MF (1<<1) /* if set, floating-point enabled. */ -/* Private peripheral bus base address */ -#define CORTEXM_PPB_BASE 0xE0000000 - -#define CORTEXM_SCS_BASE (CORTEXM_PPB_BASE + 0xE000) - -#define CORTEXM_AIRCR (CORTEXM_SCS_BASE + 0xD0C) -#define CORTEXM_CFSR (CORTEXM_SCS_BASE + 0xD28) -#define CORTEXM_HFSR (CORTEXM_SCS_BASE + 0xD2C) -#define CORTEXM_DFSR (CORTEXM_SCS_BASE + 0xD30) -#define CORTEXM_CPACR (CORTEXM_SCS_BASE + 0xD88) -#define CORTEXM_DHCSR (CORTEXM_SCS_BASE + 0xDF0) -#define CORTEXM_DCRSR (CORTEXM_SCS_BASE + 0xDF4) -#define CORTEXM_DCRDR (CORTEXM_SCS_BASE + 0xDF8) -#define CORTEXM_DEMCR (CORTEXM_SCS_BASE + 0xDFC) - -#define CORTEXM_FPB_BASE (CORTEXM_PPB_BASE + 0x2000) - -/* ARM Literature uses FP_*, we use CORTEXM_FPB_* consistently */ -#define CORTEXM_FPB_CTRL (CORTEXM_FPB_BASE + 0x000) -#define CORTEXM_FPB_REMAP (CORTEXM_FPB_BASE + 0x004) -#define CORTEXM_FPB_COMP(i) (CORTEXM_FPB_BASE + 0x008 + (4*(i))) - -#define CORTEXM_DWT_BASE (CORTEXM_PPB_BASE + 0x1000) - -#define CORTEXM_DWT_CTRL (CORTEXM_DWT_BASE + 0x000) -#define CORTEXM_DWT_COMP(i) (CORTEXM_DWT_BASE + 0x020 + (0x10*(i))) -#define CORTEXM_DWT_MASK(i) (CORTEXM_DWT_BASE + 0x024 + (0x10*(i))) -#define CORTEXM_DWT_FUNC(i) (CORTEXM_DWT_BASE + 0x028 + (0x10*(i))) - -/* Application Interrupt and Reset Control Register (AIRCR) */ -#define CORTEXM_AIRCR_VECTKEY (0x05FA << 16) -/* Bits 31:16 - Read as VECTKETSTAT, 0xFA05 */ -#define CORTEXM_AIRCR_ENDIANESS (1 << 15) -/* Bits 15:11 - Unused, reserved */ -#define CORTEXM_AIRCR_PRIGROUP (7 << 8) -/* Bits 7:3 - Unused, reserved */ -#define CORTEXM_AIRCR_SYSRESETREQ (1 << 2) -#define CORTEXM_AIRCR_VECTCLRACTIVE (1 << 1) -#define CORTEXM_AIRCR_VECTRESET (1 << 0) - -/* HardFault Status Register (HFSR) */ -#define CORTEXM_HFSR_DEBUGEVT (1 << 31) -#define CORTEXM_HFSR_FORCED (1 << 30) -/* Bits 29:2 - Not specified */ -#define CORTEXM_HFSR_VECTTBL (1 << 1) -/* Bits 0 - Reserved */ - -/* Debug Fault Status Register (DFSR) */ -/* Bits 31:5 - Reserved */ -#define CORTEXM_DFSR_RESETALL 0x1F -#define CORTEXM_DFSR_EXTERNAL (1 << 4) -#define CORTEXM_DFSR_VCATCH (1 << 3) -#define CORTEXM_DFSR_DWTTRAP (1 << 2) -#define CORTEXM_DFSR_BKPT (1 << 1) -#define CORTEXM_DFSR_HALTED (1 << 0) - -/* Debug Halting Control and Status Register (DHCSR) */ -/* This key must be written to bits 31:16 for write to take effect */ -#define CORTEXM_DHCSR_DBGKEY 0xA05F0000 -/* Bits 31:26 - Reserved */ -#define CORTEXM_DHCSR_S_RESET_ST (1 << 25) -#define CORTEXM_DHCSR_S_RETIRE_ST (1 << 24) -/* Bits 23:20 - Reserved */ -#define CORTEXM_DHCSR_S_LOCKUP (1 << 19) -#define CORTEXM_DHCSR_S_SLEEP (1 << 18) -#define CORTEXM_DHCSR_S_HALT (1 << 17) -#define CORTEXM_DHCSR_S_REGRDY (1 << 16) -/* Bits 15:6 - Reserved */ -#define CORTEXM_DHCSR_C_SNAPSTALL (1 << 5) /* v7m only */ -/* Bit 4 - Reserved */ -#define CORTEXM_DHCSR_C_MASKINTS (1 << 3) -#define CORTEXM_DHCSR_C_STEP (1 << 2) -#define CORTEXM_DHCSR_C_HALT (1 << 1) -#define CORTEXM_DHCSR_C_DEBUGEN (1 << 0) - -/* Debug Core Register Selector Register (DCRSR) */ -#define CORTEXM_DCRSR_REGWnR 0x00010000 -#define CORTEXM_DCRSR_REGSEL_MASK 0x0000001F -#define CORTEXM_DCRSR_REGSEL_XPSR 0x00000010 -#define CORTEXM_DCRSR_REGSEL_MSP 0x00000011 -#define CORTEXM_DCRSR_REGSEL_PSP 0x00000012 - -/* Debug Exception and Monitor Control Register (DEMCR) */ -/* Bits 31:25 - Reserved */ -#define CORTEXM_DEMCR_TRCENA (1 << 24) -/* Bits 23:20 - Reserved */ -#define CORTEXM_DEMCR_MON_REQ (1 << 19) /* v7m only */ -#define CORTEXM_DEMCR_MON_STEP (1 << 18) /* v7m only */ -#define CORTEXM_DEMCR_VC_MON_PEND (1 << 17) /* v7m only */ -#define CORTEXM_DEMCR_VC_MON_EN (1 << 16) /* v7m only */ -/* Bits 15:11 - Reserved */ -#define CORTEXM_DEMCR_VC_HARDERR (1 << 10) -#define CORTEXM_DEMCR_VC_INTERR (1 << 9) /* v7m only */ -#define CORTEXM_DEMCR_VC_BUSERR (1 << 8) /* v7m only */ -#define CORTEXM_DEMCR_VC_STATERR (1 << 7) /* v7m only */ -#define CORTEXM_DEMCR_VC_CHKERR (1 << 6) /* v7m only */ -#define CORTEXM_DEMCR_VC_NOCPERR (1 << 5) /* v7m only */ -#define CORTEXM_DEMCR_VC_MMERR (1 << 4) /* v7m only */ -/* Bits 3:1 - Reserved */ -#define CORTEXM_DEMCR_VC_CORERESET (1 << 0) - -/* Flash Patch and Breakpoint Control Register (FP_CTRL) */ -/* Bits 32:15 - Reserved */ -/* Bits 14:12 - NUM_CODE2 */ /* v7m only */ -/* Bits 11:8 - NUM_LIT */ /* v7m only */ -/* Bits 7:4 - NUM_CODE1 */ -/* Bits 3:2 - Unspecified */ -#define CORTEXM_FPB_CTRL_KEY (1 << 1) -#define CORTEXM_FPB_CTRL_ENABLE (1 << 0) - -/* Data Watchpoint and Trace Mask Register (DWT_MASKx) */ -#define CORTEXM_DWT_MASK_BYTE (0 << 0) -#define CORTEXM_DWT_MASK_HALFWORD (1 << 0) -#define CORTEXM_DWT_MASK_WORD (3 << 0) - -/* Data Watchpoint and Trace Function Register (DWT_FUNCTIONx) */ -#define CORTEXM_DWT_FUNC_MATCHED (1 << 24) -#define CORTEXM_DWT_FUNC_DATAVSIZE_WORD (2 << 10) /* v7m only */ -#define CORTEXM_DWT_FUNC_FUNC_READ (5 << 0) -#define CORTEXM_DWT_FUNC_FUNC_WRITE (6 << 0) -#define CORTEXM_DWT_FUNC_FUNC_ACCESS (7 << 0) - /* Signals returned by cortexm_halt_wait() */ #define SIGINT 2 #define SIGTRAP 5 #define SIGSEGV 11 static bool cortexm_attach(struct target_s *target); -static void cortexm_detach(struct target_s *target); static int cortexm_regs_read(struct target_s *target, void *data); static int cortexm_regs_write(struct target_s *target, const void *data); static int cortexm_pc_write(struct target_s *target, const uint32_t val); static void cortexm_reset(struct target_s *target); -static void cortexm_halt_resume(struct target_s *target, bool step); static int cortexm_halt_wait(struct target_s *target); static void cortexm_halt_request(struct target_s *target); static int cortexm_fault_unwind(struct target_s *target); @@ -456,8 +333,7 @@ cortexm_attach(struct target_s *target) return true; } -static void -cortexm_detach(struct target_s *target) +void cortexm_detach(struct target_s *target) { ADIv5_AP_t *ap = adiv5_target_ap(target); struct cortexm_priv *priv = ap->priv; @@ -646,14 +522,14 @@ cortexm_halt_wait(struct target_s *target) } -static void -cortexm_halt_resume(struct target_s *target, bool step) +void cortexm_halt_resume(struct target_s *target, bool step) { ADIv5_AP_t *ap = adiv5_target_ap(target); struct cortexm_priv *priv = ap->priv; uint32_t dhcsr = CORTEXM_DHCSR_DBGKEY | CORTEXM_DHCSR_C_DEBUGEN; - if(step) dhcsr |= CORTEXM_DHCSR_C_STEP | CORTEXM_DHCSR_C_MASKINTS; + if (step) + dhcsr |= CORTEXM_DHCSR_C_STEP | CORTEXM_DHCSR_C_MASKINTS; /* Disable interrupts while single stepping... */ if(step != priv->stepping) { diff --git a/src/include/cortexm.h b/src/include/cortexm.h new file mode 100644 index 0000000..f6170b0 --- /dev/null +++ b/src/include/cortexm.h @@ -0,0 +1,130 @@ +#ifndef __CORTEXM_H +#define __CORTEXM_H + +/* Private peripheral bus base address */ +#define CORTEXM_PPB_BASE 0xE0000000 + +#define CORTEXM_SCS_BASE (CORTEXM_PPB_BASE + 0xE000) + +#define CORTEXM_AIRCR (CORTEXM_SCS_BASE + 0xD0C) +#define CORTEXM_CFSR (CORTEXM_SCS_BASE + 0xD28) +#define CORTEXM_HFSR (CORTEXM_SCS_BASE + 0xD2C) +#define CORTEXM_DFSR (CORTEXM_SCS_BASE + 0xD30) +#define CORTEXM_CPACR (CORTEXM_SCS_BASE + 0xD88) +#define CORTEXM_DHCSR (CORTEXM_SCS_BASE + 0xDF0) +#define CORTEXM_DCRSR (CORTEXM_SCS_BASE + 0xDF4) +#define CORTEXM_DCRDR (CORTEXM_SCS_BASE + 0xDF8) +#define CORTEXM_DEMCR (CORTEXM_SCS_BASE + 0xDFC) + +#define CORTEXM_FPB_BASE (CORTEXM_PPB_BASE + 0x2000) + +/* ARM Literature uses FP_*, we use CORTEXM_FPB_* consistently */ +#define CORTEXM_FPB_CTRL (CORTEXM_FPB_BASE + 0x000) +#define CORTEXM_FPB_REMAP (CORTEXM_FPB_BASE + 0x004) +#define CORTEXM_FPB_COMP(i) (CORTEXM_FPB_BASE + 0x008 + (4*(i))) + +#define CORTEXM_DWT_BASE (CORTEXM_PPB_BASE + 0x1000) + +#define CORTEXM_DWT_CTRL (CORTEXM_DWT_BASE + 0x000) +#define CORTEXM_DWT_COMP(i) (CORTEXM_DWT_BASE + 0x020 + (0x10*(i))) +#define CORTEXM_DWT_MASK(i) (CORTEXM_DWT_BASE + 0x024 + (0x10*(i))) +#define CORTEXM_DWT_FUNC(i) (CORTEXM_DWT_BASE + 0x028 + (0x10*(i))) + +/* Application Interrupt and Reset Control Register (AIRCR) */ +#define CORTEXM_AIRCR_VECTKEY (0x05FA << 16) +/* Bits 31:16 - Read as VECTKETSTAT, 0xFA05 */ +#define CORTEXM_AIRCR_ENDIANESS (1 << 15) +/* Bits 15:11 - Unused, reserved */ +#define CORTEXM_AIRCR_PRIGROUP (7 << 8) +/* Bits 7:3 - Unused, reserved */ +#define CORTEXM_AIRCR_SYSRESETREQ (1 << 2) +#define CORTEXM_AIRCR_VECTCLRACTIVE (1 << 1) +#define CORTEXM_AIRCR_VECTRESET (1 << 0) + +/* HardFault Status Register (HFSR) */ +#define CORTEXM_HFSR_DEBUGEVT (1 << 31) +#define CORTEXM_HFSR_FORCED (1 << 30) +/* Bits 29:2 - Not specified */ +#define CORTEXM_HFSR_VECTTBL (1 << 1) +/* Bits 0 - Reserved */ + +/* Debug Fault Status Register (DFSR) */ +/* Bits 31:5 - Reserved */ +#define CORTEXM_DFSR_RESETALL 0x1F +#define CORTEXM_DFSR_EXTERNAL (1 << 4) +#define CORTEXM_DFSR_VCATCH (1 << 3) +#define CORTEXM_DFSR_DWTTRAP (1 << 2) +#define CORTEXM_DFSR_BKPT (1 << 1) +#define CORTEXM_DFSR_HALTED (1 << 0) + +/* Debug Halting Control and Status Register (DHCSR) */ +/* This key must be written to bits 31:16 for write to take effect */ +#define CORTEXM_DHCSR_DBGKEY 0xA05F0000 +/* Bits 31:26 - Reserved */ +#define CORTEXM_DHCSR_S_RESET_ST (1 << 25) +#define CORTEXM_DHCSR_S_RETIRE_ST (1 << 24) +/* Bits 23:20 - Reserved */ +#define CORTEXM_DHCSR_S_LOCKUP (1 << 19) +#define CORTEXM_DHCSR_S_SLEEP (1 << 18) +#define CORTEXM_DHCSR_S_HALT (1 << 17) +#define CORTEXM_DHCSR_S_REGRDY (1 << 16) +/* Bits 15:6 - Reserved */ +#define CORTEXM_DHCSR_C_SNAPSTALL (1 << 5) /* v7m only */ +/* Bit 4 - Reserved */ +#define CORTEXM_DHCSR_C_MASKINTS (1 << 3) +#define CORTEXM_DHCSR_C_STEP (1 << 2) +#define CORTEXM_DHCSR_C_HALT (1 << 1) +#define CORTEXM_DHCSR_C_DEBUGEN (1 << 0) + +/* Debug Core Register Selector Register (DCRSR) */ +#define CORTEXM_DCRSR_REGWnR 0x00010000 +#define CORTEXM_DCRSR_REGSEL_MASK 0x0000001F +#define CORTEXM_DCRSR_REGSEL_XPSR 0x00000010 +#define CORTEXM_DCRSR_REGSEL_MSP 0x00000011 +#define CORTEXM_DCRSR_REGSEL_PSP 0x00000012 + +/* Debug Exception and Monitor Control Register (DEMCR) */ +/* Bits 31:25 - Reserved */ +#define CORTEXM_DEMCR_TRCENA (1 << 24) +/* Bits 23:20 - Reserved */ +#define CORTEXM_DEMCR_MON_REQ (1 << 19) /* v7m only */ +#define CORTEXM_DEMCR_MON_STEP (1 << 18) /* v7m only */ +#define CORTEXM_DEMCR_VC_MON_PEND (1 << 17) /* v7m only */ +#define CORTEXM_DEMCR_VC_MON_EN (1 << 16) /* v7m only */ +/* Bits 15:11 - Reserved */ +#define CORTEXM_DEMCR_VC_HARDERR (1 << 10) +#define CORTEXM_DEMCR_VC_INTERR (1 << 9) /* v7m only */ +#define CORTEXM_DEMCR_VC_BUSERR (1 << 8) /* v7m only */ +#define CORTEXM_DEMCR_VC_STATERR (1 << 7) /* v7m only */ +#define CORTEXM_DEMCR_VC_CHKERR (1 << 6) /* v7m only */ +#define CORTEXM_DEMCR_VC_NOCPERR (1 << 5) /* v7m only */ +#define CORTEXM_DEMCR_VC_MMERR (1 << 4) /* v7m only */ +/* Bits 3:1 - Reserved */ +#define CORTEXM_DEMCR_VC_CORERESET (1 << 0) + +/* Flash Patch and Breakpoint Control Register (FP_CTRL) */ +/* Bits 32:15 - Reserved */ +/* Bits 14:12 - NUM_CODE2 */ /* v7m only */ +/* Bits 11:8 - NUM_LIT */ /* v7m only */ +/* Bits 7:4 - NUM_CODE1 */ +/* Bits 3:2 - Unspecified */ +#define CORTEXM_FPB_CTRL_KEY (1 << 1) +#define CORTEXM_FPB_CTRL_ENABLE (1 << 0) + +/* Data Watchpoint and Trace Mask Register (DWT_MASKx) */ +#define CORTEXM_DWT_MASK_BYTE (0 << 0) +#define CORTEXM_DWT_MASK_HALFWORD (1 << 0) +#define CORTEXM_DWT_MASK_WORD (3 << 0) + +/* Data Watchpoint and Trace Function Register (DWT_FUNCTIONx) */ +#define CORTEXM_DWT_FUNC_MATCHED (1 << 24) +#define CORTEXM_DWT_FUNC_DATAVSIZE_WORD (2 << 10) /* v7m only */ +#define CORTEXM_DWT_FUNC_FUNC_READ (5 << 0) +#define CORTEXM_DWT_FUNC_FUNC_WRITE (6 << 0) +#define CORTEXM_DWT_FUNC_FUNC_ACCESS (7 << 0) + +void cortexm_detach(struct target_s *target); +void cortexm_halt_resume(struct target_s *target, bool step); + +#endif + diff --git a/src/samd20.c b/src/samd20.c index 8b79049..b252524 100644 --- a/src/samd20.c +++ b/src/samd20.c @@ -39,6 +39,7 @@ #include "target.h" #include "command.h" #include "gdb_packet.h" +#include "cortexm.h" static int samd20_flash_erase(struct target_s *target, uint32_t addr, int len); static int samd20_flash_write(struct target_s *target, uint32_t dest, @@ -145,104 +146,6 @@ static const char samd20_xml_memory_map[] = "" /* Component ID */ #define SAMD20_CID_VALUE 0xB105100D -#define CORTEXM_PPB_BASE 0xE0000000 - -#define CORTEXM_SCS_BASE (CORTEXM_PPB_BASE + 0xE000) - -#define CORTEXM_AIRCR (CORTEXM_SCS_BASE + 0xD0C) -#define CORTEXM_CFSR (CORTEXM_SCS_BASE + 0xD28) -#define CORTEXM_HFSR (CORTEXM_SCS_BASE + 0xD2C) -#define CORTEXM_DFSR (CORTEXM_SCS_BASE + 0xD30) -#define CORTEXM_CPACR (CORTEXM_SCS_BASE + 0xD88) -#define CORTEXM_DHCSR (CORTEXM_SCS_BASE + 0xDF0) -#define CORTEXM_DCRSR (CORTEXM_SCS_BASE + 0xDF4) -#define CORTEXM_DCRDR (CORTEXM_SCS_BASE + 0xDF8) -#define CORTEXM_DEMCR (CORTEXM_SCS_BASE + 0xDFC) - -/* Application Interrupt and Reset Control Register (AIRCR) */ -#define CORTEXM_AIRCR_VECTKEY (0x05FA << 16) -/* Bits 31:16 - Read as VECTKETSTAT, 0xFA05 */ -#define CORTEXM_AIRCR_ENDIANESS (1 << 15) -/* Bits 15:11 - Unused, reserved */ -#define CORTEXM_AIRCR_PRIGROUP (7 << 8) -/* Bits 7:3 - Unused, reserved */ -#define CORTEXM_AIRCR_SYSRESETREQ (1 << 2) -#define CORTEXM_AIRCR_VECTCLRACTIVE (1 << 1) -#define CORTEXM_AIRCR_VECTRESET (1 << 0) - -/* Debug Fault Status Register (DFSR) */ -/* Bits 31:5 - Reserved */ -#define CORTEXM_DFSR_RESETALL 0x1F -#define CORTEXM_DFSR_EXTERNAL (1 << 4) -#define CORTEXM_DFSR_VCATCH (1 << 3) -#define CORTEXM_DFSR_DWTTRAP (1 << 2) -#define CORTEXM_DFSR_BKPT (1 << 1) -#define CORTEXM_DFSR_HALTED (1 << 0) - -/* Debug Halting Control and Status Register (DHCSR) */ -/* This key must be written to bits 31:16 for write to take effect */ -#define CORTEXM_DHCSR_DBGKEY 0xA05F0000 -/* Bits 31:26 - Reserved */ -#define CORTEXM_DHCSR_S_RESET_ST (1 << 25) -#define CORTEXM_DHCSR_S_RETIRE_ST (1 << 24) -/* Bits 23:20 - Reserved */ -#define CORTEXM_DHCSR_S_LOCKUP (1 << 19) -#define CORTEXM_DHCSR_S_SLEEP (1 << 18) -#define CORTEXM_DHCSR_S_HALT (1 << 17) -#define CORTEXM_DHCSR_S_REGRDY (1 << 16) -/* Bits 15:6 - Reserved */ -#define CORTEXM_DHCSR_C_SNAPSTALL (1 << 5) /* v7m only */ -/* Bit 4 - Reserved */ -#define CORTEXM_DHCSR_C_MASKINTS (1 << 3) -#define CORTEXM_DHCSR_C_STEP (1 << 2) -#define CORTEXM_DHCSR_C_HALT (1 << 1) -#define CORTEXM_DHCSR_C_DEBUGEN (1 << 0) - - -/* -------------------------------------------------------------------------- */ -/* Cortex-M definitions for SAM D20 revision B fix */ -/* -------------------------------------------------------------------------- */ - -#define CORTEXM_FPB_BASE (CORTEXM_PPB_BASE + 0x2000) - -/* ARM Literature uses FP_*, we use CORTEXM_FPB_* consistently */ -#define CORTEXM_FPB_CTRL (CORTEXM_FPB_BASE + 0x000) -#define CORTEXM_FPB_REMAP (CORTEXM_FPB_BASE + 0x004) -#define CORTEXM_FPB_COMP(i) (CORTEXM_FPB_BASE + 0x008 + (4*(i))) - -#define CORTEXM_DWT_BASE (CORTEXM_PPB_BASE + 0x1000) - -#define CORTEXM_DWT_CTRL (CORTEXM_DWT_BASE + 0x000) -#define CORTEXM_DWT_COMP(i) (CORTEXM_DWT_BASE + 0x020 + (0x10*(i))) -#define CORTEXM_DWT_MASK(i) (CORTEXM_DWT_BASE + 0x024 + (0x10*(i))) -#define CORTEXM_DWT_FUNC(i) (CORTEXM_DWT_BASE + 0x028 + (0x10*(i))) - -#define CORTEXM_MAX_WATCHPOINTS 4 /* architecture says up to 15, no implementation has > 4 */ -#define CORTEXM_MAX_BREAKPOINTS 6 /* architecture says up to 127, no implementation has > 6 */ - -struct cortexm_priv { - bool stepping; - bool on_bkpt; - /* Watchpoint unit status */ - struct wp_unit_s { - uint32_t addr; - uint8_t type; - uint8_t size; - } hw_watchpoint[CORTEXM_MAX_WATCHPOINTS]; - unsigned hw_watchpoint_max; - /* Breakpoint unit status */ - uint32_t hw_breakpoint[CORTEXM_MAX_BREAKPOINTS]; - unsigned hw_breakpoint_max; - /* Copy of DEMCR for vector-catch */ - uint32_t demcr; - /* Semihosting state */ - uint32_t syscall; - uint32_t errno; - uint32_t byte_count; -}; - - - /* Utility */ #define MINIMUM(a,b) ((a < b) ? a : b) @@ -340,19 +243,7 @@ static void samd20_revB_detach(struct target_s *target) { ADIv5_AP_t *ap = adiv5_target_ap(target); - struct cortexm_priv *priv = ap->priv; - unsigned i; - - /* Clear any stale breakpoints */ - for(i = 0; i < priv->hw_breakpoint_max; i++) - adiv5_ap_mem_write(ap, CORTEXM_FPB_COMP(i), 0); - - /* Clear any stale watchpoints */ - for(i = 0; i < priv->hw_watchpoint_max; i++) - adiv5_ap_mem_write(ap, CORTEXM_DWT_FUNC(i), 0); - - /* Disable debug */ - adiv5_ap_mem_write(ap, CORTEXM_DHCSR, CORTEXM_DHCSR_DBGKEY); + cortexm_detach(target); /* ---- Additional ---- */ /* Exit extended reset */ @@ -374,25 +265,7 @@ static void samd20_revB_halt_resume(struct target_s *target, bool step) { ADIv5_AP_t *ap = adiv5_target_ap(target); - struct cortexm_priv *priv = ap->priv; - uint32_t dhcsr = CORTEXM_DHCSR_DBGKEY | CORTEXM_DHCSR_C_DEBUGEN; - - if(step) dhcsr |= CORTEXM_DHCSR_C_STEP | CORTEXM_DHCSR_C_MASKINTS; - - /* Disable interrupts while single stepping... */ - if(step != priv->stepping) { - adiv5_ap_mem_write(ap, CORTEXM_DHCSR, dhcsr | CORTEXM_DHCSR_C_HALT); - priv->stepping = step; - } - - if (priv->on_bkpt) { - uint32_t pc = target->pc_read(target); - if ((adiv5_ap_mem_read_halfword(ap, pc) & 0xFF00) == 0xBE00) - target->pc_write(target, pc + 2); - } - - adiv5_ap_mem_write(ap, CORTEXM_DHCSR, dhcsr); - ap->dp->allow_timeout = true; + cortexm_halt_resume(target, step); /* ---- Additional ---- */ /* Exit extended reset */ -- cgit v1.2.3 From 1c1312b467c60bed7ca6e81905c4436629153ae2 Mon Sep 17 00:00:00 2001 From: Richard Meadows Date: Sun, 18 Jan 2015 13:22:41 +0000 Subject: Added better feedback for samd erase failures --- src/samd20.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/samd20.c b/src/samd20.c index b252524..04ab737 100644 --- a/src/samd20.c +++ b/src/samd20.c @@ -501,14 +501,34 @@ static bool samd20_cmd_erase_all(target *t) { ADIv5_AP_t *ap = adiv5_target_ap(t); + /* Clear the DSU status bits */ + adiv5_ap_mem_write(ap, SAMD20_DSU_CTRLSTAT, + (SAMD20_STATUSA_DONE | SAMD20_STATUSA_PERR | SAMD20_STATUSA_FAIL)); + /* Erase all */ adiv5_ap_mem_write(ap, SAMD20_DSU_CTRLSTAT, SAMD20_CTRL_CHIP_ERASE); /* Poll for DSU Ready */ - while ((adiv5_ap_mem_read(ap, SAMD20_DSU_CTRLSTAT) & SAMD20_STATUSA_DONE) == 0) + uint32_t status; + while (((status = adiv5_ap_mem_read(ap, SAMD20_DSU_CTRLSTAT)) & + (SAMD20_STATUSA_DONE | SAMD20_STATUSA_PERR | SAMD20_STATUSA_FAIL)) == 0) if(target_check_error(t)) return false; + /* Test the protection error bit in Status A */ + if (status & SAMD20_STATUSA_PERR) { + gdb_outf("Erase failed due to a protection error.\n"); + return true; + } + + /* Test the fail bit in Status A */ + if (status & SAMD20_STATUSA_FAIL) { + gdb_outf("Erase failed.\n"); + return true; + } + + gdb_outf("Erase successful!\n"); + return true; } -- cgit v1.2.3 From e75ea64a010412dc407692a6e28c76e8b0359c66 Mon Sep 17 00:00:00 2001 From: Richard Meadows Date: Sun, 18 Jan 2015 14:11:58 +0000 Subject: Renamed nvmc control a register to match datasheet --- src/samd20.c | 43 +++++++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/samd20.c b/src/samd20.c index 04ab737..64233bc 100644 --- a/src/samd20.c +++ b/src/samd20.c @@ -81,23 +81,27 @@ static const char samd20_xml_memory_map[] = "" #define SAMD20_ROW_SIZE 256 #define SAMD20_PAGE_SIZE 64 +/* -------------------------------------------------------------------------- */ /* Non-Volatile Memory Controller (NVMC) Registers */ +/* -------------------------------------------------------------------------- */ + #define SAMD20_NVMC 0x41004000 -#define SAMD20_NVMC_CMD (SAMD20_NVMC + 0x0) +#define SAMD20_NVMC_CTRLA (SAMD20_NVMC + 0x0) +#define SAMD20_NVMC_CTRLB (SAMD20_NVMC + 0x04) #define SAMD20_NVMC_PARAM (SAMD20_NVMC + 0x08) #define SAMD20_NVMC_INTFLAG (SAMD20_NVMC + 0x14) #define SAMD20_NVMC_STATUS (SAMD20_NVMC + 0x18) #define SAMD20_NVMC_ADDRESS (SAMD20_NVMC + 0x1C) -/* Command Register (CMD) */ -#define SAMD20_CMD_KEY 0xA500 -#define SAMD20_CMD_ERASEROW 0x0002 -#define SAMD20_CMD_WRITEPAGE 0x0004 -#define SAMD20_CMD_ERASEAUXROW 0x0005 -#define SAMD20_CMD_WRITEAUXPAGE 0x0006 -#define SAMD20_CMD_LOCK 0x0040 -#define SAMD20_CMD_UNLOCK 0x0041 -#define SAMD20_CMD_PAGEBUFFERCLEAR 0x0044 +/* Control A Register (CTRLA) */ +#define SAMD20_CTRLA_CMD_KEY 0xA500 +#define SAMD20_CTRLA_CMD_ERASEROW 0x0002 +#define SAMD20_CTRLA_CMD_WRITEPAGE 0x0004 +#define SAMD20_CTRLA_CMD_ERASEAUXROW 0x0005 +#define SAMD20_CTRLA_CMD_WRITEAUXPAGE 0x0006 +#define SAMD20_CTRLA_CMD_LOCK 0x0040 +#define SAMD20_CTRLA_CMD_UNLOCK 0x0041 +#define SAMD20_CTRLA_CMD_PAGEBUFFERCLEAR 0x0044 /* Interrupt Flag Register (INTFLAG) */ #define SAMD20_NVMC_READY (1 << 0) @@ -109,7 +113,10 @@ static const char samd20_xml_memory_map[] = "" #define SAMD20_NVM_SERIAL(n) (0x0080A00C + (0x30 * ((n + 3) / 4)) + \ (0x4 * n)) +/* -------------------------------------------------------------------------- */ /* Device Service Unit (DSU) Registers */ +/* -------------------------------------------------------------------------- */ + #define SAMD20_DSU 0x41002000 #define SAMD20_DSU_EXT_ACCESS (SAMD20_DSU + 0x100) #define SAMD20_DSU_CTRLSTAT (SAMD20_DSU_EXT_ACCESS + 0x0) @@ -366,14 +373,14 @@ static void samd20_lock_current_address(struct target_s *target) ADIv5_AP_t *ap = adiv5_target_ap(target); /* Issue the unlock command */ - adiv5_ap_mem_write(ap, SAMD20_NVMC_CMD, SAMD20_CMD_KEY | SAMD20_CMD_LOCK); + adiv5_ap_mem_write(ap, SAMD20_NVMC_CTRLA, SAMD20_CTRLA_CMD_KEY | SAMD20_CTRLA_CMD_LOCK); } static void samd20_unlock_current_address(struct target_s *target) { ADIv5_AP_t *ap = adiv5_target_ap(target); /* Issue the unlock command */ - adiv5_ap_mem_write(ap, SAMD20_NVMC_CMD, SAMD20_CMD_KEY | SAMD20_CMD_UNLOCK); + adiv5_ap_mem_write(ap, SAMD20_NVMC_CTRLA, SAMD20_CTRLA_CMD_KEY | SAMD20_CTRLA_CMD_UNLOCK); } /** @@ -395,7 +402,7 @@ static int samd20_flash_erase(struct target_s *target, uint32_t addr, int len) samd20_unlock_current_address(target); /* Issue the erase command */ - adiv5_ap_mem_write(ap, SAMD20_NVMC_CMD, SAMD20_CMD_KEY | SAMD20_CMD_ERASEROW); + adiv5_ap_mem_write(ap, SAMD20_NVMC_CTRLA, SAMD20_CTRLA_CMD_KEY | SAMD20_CTRLA_CMD_ERASEROW); /* Poll for NVM Ready */ while ((adiv5_ap_mem_read(ap, SAMD20_NVMC_INTFLAG) & SAMD20_NVMC_READY) == 0) if(target_check_error(target)) @@ -460,8 +467,8 @@ static int samd20_flash_write(struct target_s *target, uint32_t dest, samd20_unlock_current_address(target); /* Issue the write page command */ - adiv5_ap_mem_write(ap, SAMD20_NVMC_CMD, - SAMD20_CMD_KEY | SAMD20_CMD_WRITEPAGE); + adiv5_ap_mem_write(ap, SAMD20_NVMC_CTRLA, + SAMD20_CTRLA_CMD_KEY | SAMD20_CTRLA_CMD_WRITEPAGE); } else { /* Write first word to set address */ adiv5_ap_mem_write(ap, addr, data[i]); addr += 4; i++; @@ -551,7 +558,7 @@ static bool samd20_set_flashlock(target *t, uint16_t value) adiv5_ap_mem_write(ap, SAMD20_NVMC_ADDRESS, SAMD20_NVM_USER_ROW_LOW >> 1); /* Issue the erase command */ - adiv5_ap_mem_write(ap, SAMD20_NVMC_CMD, SAMD20_CMD_KEY | SAMD20_CMD_ERASEAUXROW); + adiv5_ap_mem_write(ap, SAMD20_NVMC_CTRLA, SAMD20_CTRLA_CMD_KEY | SAMD20_CTRLA_CMD_ERASEAUXROW); /* Poll for NVM Ready */ while ((adiv5_ap_mem_read(ap, SAMD20_NVMC_INTFLAG) & SAMD20_NVMC_READY) == 0) @@ -566,8 +573,8 @@ static bool samd20_set_flashlock(target *t, uint16_t value) adiv5_ap_mem_write(ap, SAMD20_NVM_USER_ROW_HIGH, high); /* Issue the page write command */ - adiv5_ap_mem_write(ap, SAMD20_NVMC_CMD, - SAMD20_CMD_KEY | SAMD20_CMD_WRITEAUXPAGE); + adiv5_ap_mem_write(ap, SAMD20_NVMC_CTRLA, + SAMD20_CTRLA_CMD_KEY | SAMD20_CTRLA_CMD_WRITEAUXPAGE); return true; } -- cgit v1.2.3 From 372606177357a815dd7c484739649b50118ad42e Mon Sep 17 00:00:00 2001 From: Richard Meadows Date: Sun, 18 Jan 2015 20:46:26 +0000 Subject: Support for the NVMCTRL Security Bit (PROT=1) --- src/cortexm.c | 5 +--- src/include/cortexm.h | 1 + src/samd20.c | 77 +++++++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 73 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/cortexm.c b/src/cortexm.c index b7f71eb..364e276 100644 --- a/src/cortexm.c +++ b/src/cortexm.c @@ -60,8 +60,6 @@ const struct command_s cortexm_cmd_list[] = { #define SIGTRAP 5 #define SIGSEGV 11 -static bool cortexm_attach(struct target_s *target); - static int cortexm_regs_read(struct target_s *target, void *data); static int cortexm_regs_write(struct target_s *target, const void *data); static int cortexm_pc_write(struct target_s *target, const uint32_t val); @@ -269,8 +267,7 @@ cortexm_probe(struct target_s *target) return true; } -static bool -cortexm_attach(struct target_s *target) +bool cortexm_attach(struct target_s *target) { ADIv5_AP_t *ap = adiv5_target_ap(target); struct cortexm_priv *priv = ap->priv; diff --git a/src/include/cortexm.h b/src/include/cortexm.h index f6170b0..f1fc07a 100644 --- a/src/include/cortexm.h +++ b/src/include/cortexm.h @@ -123,6 +123,7 @@ #define CORTEXM_DWT_FUNC_FUNC_WRITE (6 << 0) #define CORTEXM_DWT_FUNC_FUNC_ACCESS (7 << 0) +bool cortexm_attach(struct target_s *target); void cortexm_detach(struct target_s *target); void cortexm_halt_resume(struct target_s *target, bool step); diff --git a/src/samd20.c b/src/samd20.c index 64233bc..08fe6c2 100644 --- a/src/samd20.c +++ b/src/samd20.c @@ -25,9 +25,6 @@ * http://www.atmel.com/Images/Atmel-42129-SAM-D20_Datasheet.pdf * particularly Sections 12. DSU and 20. NVMCTRL */ -/* TODO: Support for the NVMCTRL Security Bit. If this is set then the - * device will probably not even be detected. - */ #include #include @@ -51,6 +48,7 @@ static bool samd20_cmd_unlock_flash(target *t); static bool samd20_cmd_read_userrow(target *t); static bool samd20_cmd_serial(target *t); static bool samd20_cmd_mbist(target *t); +static bool samd20_cmd_ssb(target *t); const struct command_s samd20_cmd_list[] = { {"erase_mass", (cmd_handler)samd20_cmd_erase_all, "Erase entire flash memory"}, @@ -59,6 +57,7 @@ const struct command_s samd20_cmd_list[] = { {"user_row", (cmd_handler)samd20_cmd_read_userrow, "Prints user row from flash"}, {"serial", (cmd_handler)samd20_cmd_serial, "Prints serial number"}, {"mbist", (cmd_handler)samd20_cmd_mbist, "Runs the built-in memory test"}, + {"set_security_bit", (cmd_handler)samd20_cmd_ssb, "Sets the Security Bit"}, {NULL, NULL, NULL} }; @@ -102,6 +101,8 @@ static const char samd20_xml_memory_map[] = "" #define SAMD20_CTRLA_CMD_LOCK 0x0040 #define SAMD20_CTRLA_CMD_UNLOCK 0x0041 #define SAMD20_CTRLA_CMD_PAGEBUFFERCLEAR 0x0044 +#define SAMD20_CTRLA_CMD_SSB 0x0045 +#define SAMD20_CTRLA_CMD_INVALL 0x0046 /* Interrupt Flag Register (INTFLAG) */ #define SAMD20_NVMC_READY (1 << 0) @@ -137,6 +138,7 @@ static const char samd20_xml_memory_map[] = "" #define SAMD20_STATUSA_BERR (1 << 10) #define SAMD20_STATUSA_CRSTEXT (1 << 9) #define SAMD20_STATUSA_DONE (1 << 8) +#define SAMD20_STATUSB_PROT (1 << 16) /* Device Identification Register (DID) */ #define SAMD20_DID_MASK 0xFFBF0000 @@ -284,8 +286,32 @@ samd20_revB_halt_resume(struct target_s *target, bool step) } } +/** + * Overload the default cortexm attach for when the samd20 is protected. + * + * If the samd20 is protected then the default cortexm attach will + * fail as the S_HALT bit in the DHCSR will never go high. This + * function allows users to attach on a temporary basis so they can + * rescue the device. + */ +static bool +samd20_protected_attach(struct target_s *target) +{ + /** + * TODO: Notify the user that we're not really attached and + * they should issue the 'monitor erase_mass' command to + * regain access to the chip. + */ + + /* Patch back in the normal cortexm attach for next time */ + target->attach = cortexm_attach; + + /* Allow attach this time */ + return true; +} + -char variant_string[30]; +char variant_string[40]; bool samd20_probe(struct target_s *target) { ADIv5_AP_t *ap = adiv5_target_ap(target); @@ -306,6 +332,7 @@ bool samd20_probe(struct target_s *target) & SAMD20_DID_DEVSEL_MASK; uint8_t revision = (did >> SAMD20_DID_REVISION_POS) & SAMD20_DID_REVISION_MASK; + uint32_t ctrlstat = adiv5_ap_mem_read(ap, SAMD20_DSU_CTRLSTAT); /* Pin Variant */ char pin_variant; @@ -322,9 +349,17 @@ bool samd20_probe(struct target_s *target) /* Revision */ char revision_variant = 'A' + revision; + /* Protected? */ + int protected = (ctrlstat & SAMD20_STATUSB_PROT); + /* Part String */ - sprintf(variant_string, "Atmel SAMD20%c%dA (rev %c)", - pin_variant, mem_variant, revision_variant); + if (protected) { + sprintf(variant_string, "Atmel SAMD20%c%dA (rev %c) (PROT=1)", + pin_variant, mem_variant, revision_variant); + } else { + sprintf(variant_string, "Atmel SAMD20%c%dA (rev %c)", + pin_variant, mem_variant, revision_variant); + } /* Setup Target */ target->driver = variant_string; @@ -339,6 +374,16 @@ bool samd20_probe(struct target_s *target) target->detach = samd20_revB_detach; target->halt_resume = samd20_revB_halt_resume; } + if (protected) { + /** + * Overload the default cortexm attach + * for when the samd20 is protected. + * This function allows users to + * attach on a temporary basis so they + * can rescue the device. + */ + target->attach = samd20_protected_attach; + } target->xml_mem_map = samd20_xml_memory_map; target->flash_erase = samd20_flash_erase; @@ -669,3 +714,23 @@ static bool samd20_cmd_mbist(target *t) return true; } +/** + * Sets the security bit + */ +static bool samd20_cmd_ssb(target *t) +{ + ADIv5_AP_t *ap = adiv5_target_ap(t); + + /* Issue the ssb command */ + adiv5_ap_mem_write(ap, SAMD20_NVMC_CTRLA, SAMD20_CTRLA_CMD_KEY | SAMD20_CTRLA_CMD_SSB); + + /* Poll for NVM Ready */ + while ((adiv5_ap_mem_read(ap, SAMD20_NVMC_INTFLAG) & SAMD20_NVMC_READY) == 0) + if(target_check_error(t)) + return -1; + + gdb_outf("Set the security bit! " + "You will need to issue 'monitor erase_mass' to clear this.\n"); + + return true; +} -- cgit v1.2.3 From 565795e1680eb2a0f2f5737dddd7df293824ec4a Mon Sep 17 00:00:00 2001 From: Richard Meadows Date: Sun, 18 Jan 2015 22:35:59 +0000 Subject: Added support for SAMD10/11/21, and list of tested SAM D devices This allows blackmagic to be used with the new Arduino Zero board via the unpopulated SWD header on the east end of the board. --- src/cortexm.c | 2 +- src/include/target.h | 2 +- src/samd20.c | 458 ++++++++++++++++++++++++++++----------------------- 3 files changed, 257 insertions(+), 205 deletions(-) (limited to 'src') diff --git a/src/cortexm.c b/src/cortexm.c index 364e276..12914d3 100644 --- a/src/cortexm.c +++ b/src/cortexm.c @@ -259,7 +259,7 @@ cortexm_probe(struct target_s *target) PROBE(lpc43xx_probe); PROBE(sam3x_probe); PROBE(nrf51_probe); - PROBE(samd20_probe); + PROBE(samd_probe); PROBE(lmi_probe); PROBE(kinetis_probe); #undef PROBE diff --git a/src/include/target.h b/src/include/target.h index 100c4a0..50f1ebe 100644 --- a/src/include/target.h +++ b/src/include/target.h @@ -224,7 +224,7 @@ bool lpc11xx_probe(struct target_s *target); bool lpc43xx_probe(struct target_s *target); bool sam3x_probe(struct target_s *target); bool nrf51_probe(struct target_s *target); -bool samd20_probe(struct target_s *target); +bool samd_probe(struct target_s *target); bool kinetis_probe(struct target_s *target); #endif diff --git a/src/samd20.c b/src/samd20.c index 08fe6c2..b043c50 100644 --- a/src/samd20.c +++ b/src/samd20.c @@ -17,9 +17,15 @@ * along with this program. If not, see . */ -/* This file implements Atmel SAM D20 target specific functions for +/* This file implements Atmel SAM D target specific functions for * detecting the device, providing the XML memory map and Flash memory * programming. + * + * Tested with + * * SAMD20E17A (rev C) + * * SAMD20J18A (rev B) + * * SAMD21J18A (rev B) + * * */ /* Refer to the SAM D20 Datasheet: * http://www.atmel.com/Images/Atmel-42129-SAM-D20_Datasheet.pdf @@ -38,26 +44,26 @@ #include "gdb_packet.h" #include "cortexm.h" -static int samd20_flash_erase(struct target_s *target, uint32_t addr, int len); -static int samd20_flash_write(struct target_s *target, uint32_t dest, +static int samd_flash_erase(struct target_s *target, uint32_t addr, int len); +static int samd_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, int len); -static bool samd20_cmd_erase_all(target *t); -static bool samd20_cmd_lock_flash(target *t); -static bool samd20_cmd_unlock_flash(target *t); -static bool samd20_cmd_read_userrow(target *t); -static bool samd20_cmd_serial(target *t); -static bool samd20_cmd_mbist(target *t); -static bool samd20_cmd_ssb(target *t); - -const struct command_s samd20_cmd_list[] = { - {"erase_mass", (cmd_handler)samd20_cmd_erase_all, "Erase entire flash memory"}, - {"lock_flash", (cmd_handler)samd20_cmd_lock_flash, "Locks flash against spurious commands"}, - {"unlock_flash", (cmd_handler)samd20_cmd_unlock_flash, "Unlocks flash"}, - {"user_row", (cmd_handler)samd20_cmd_read_userrow, "Prints user row from flash"}, - {"serial", (cmd_handler)samd20_cmd_serial, "Prints serial number"}, - {"mbist", (cmd_handler)samd20_cmd_mbist, "Runs the built-in memory test"}, - {"set_security_bit", (cmd_handler)samd20_cmd_ssb, "Sets the Security Bit"}, +static bool samd_cmd_erase_all(target *t); +static bool samd_cmd_lock_flash(target *t); +static bool samd_cmd_unlock_flash(target *t); +static bool samd_cmd_read_userrow(target *t); +static bool samd_cmd_serial(target *t); +static bool samd_cmd_mbist(target *t); +static bool samd_cmd_ssb(target *t); + +const struct command_s samd_cmd_list[] = { + {"erase_mass", (cmd_handler)samd_cmd_erase_all, "Erase entire flash memory"}, + {"lock_flash", (cmd_handler)samd_cmd_lock_flash, "Locks flash against spurious commands"}, + {"unlock_flash", (cmd_handler)samd_cmd_unlock_flash, "Unlocks flash"}, + {"user_row", (cmd_handler)samd_cmd_read_userrow, "Prints user row from flash"}, + {"serial", (cmd_handler)samd_cmd_serial, "Prints serial number"}, + {"mbist", (cmd_handler)samd_cmd_mbist, "Runs the built-in memory test"}, + {"set_security_bit", (cmd_handler)samd_cmd_ssb, "Sets the Security Bit"}, {NULL, NULL, NULL} }; @@ -65,7 +71,7 @@ const struct command_s samd20_cmd_list[] = { * 256KB Flash Max., 32KB RAM Max. The smallest unit of erase is the * one row = 256 bytes. */ -static const char samd20_xml_memory_map[] = "" +static const char samd_xml_memory_map[] = "" /* ""*/ @@ -77,83 +83,85 @@ static const char samd20_xml_memory_map[] = "" ""; /* Non-Volatile Memory Controller (NVMC) Parameters */ -#define SAMD20_ROW_SIZE 256 -#define SAMD20_PAGE_SIZE 64 +#define SAMD_ROW_SIZE 256 +#define SAMD_PAGE_SIZE 64 /* -------------------------------------------------------------------------- */ /* Non-Volatile Memory Controller (NVMC) Registers */ /* -------------------------------------------------------------------------- */ -#define SAMD20_NVMC 0x41004000 -#define SAMD20_NVMC_CTRLA (SAMD20_NVMC + 0x0) -#define SAMD20_NVMC_CTRLB (SAMD20_NVMC + 0x04) -#define SAMD20_NVMC_PARAM (SAMD20_NVMC + 0x08) -#define SAMD20_NVMC_INTFLAG (SAMD20_NVMC + 0x14) -#define SAMD20_NVMC_STATUS (SAMD20_NVMC + 0x18) -#define SAMD20_NVMC_ADDRESS (SAMD20_NVMC + 0x1C) +#define SAMD_NVMC 0x41004000 +#define SAMD_NVMC_CTRLA (SAMD_NVMC + 0x0) +#define SAMD_NVMC_CTRLB (SAMD_NVMC + 0x04) +#define SAMD_NVMC_PARAM (SAMD_NVMC + 0x08) +#define SAMD_NVMC_INTFLAG (SAMD_NVMC + 0x14) +#define SAMD_NVMC_STATUS (SAMD_NVMC + 0x18) +#define SAMD_NVMC_ADDRESS (SAMD_NVMC + 0x1C) /* Control A Register (CTRLA) */ -#define SAMD20_CTRLA_CMD_KEY 0xA500 -#define SAMD20_CTRLA_CMD_ERASEROW 0x0002 -#define SAMD20_CTRLA_CMD_WRITEPAGE 0x0004 -#define SAMD20_CTRLA_CMD_ERASEAUXROW 0x0005 -#define SAMD20_CTRLA_CMD_WRITEAUXPAGE 0x0006 -#define SAMD20_CTRLA_CMD_LOCK 0x0040 -#define SAMD20_CTRLA_CMD_UNLOCK 0x0041 -#define SAMD20_CTRLA_CMD_PAGEBUFFERCLEAR 0x0044 -#define SAMD20_CTRLA_CMD_SSB 0x0045 -#define SAMD20_CTRLA_CMD_INVALL 0x0046 +#define SAMD_CTRLA_CMD_KEY 0xA500 +#define SAMD_CTRLA_CMD_ERASEROW 0x0002 +#define SAMD_CTRLA_CMD_WRITEPAGE 0x0004 +#define SAMD_CTRLA_CMD_ERASEAUXROW 0x0005 +#define SAMD_CTRLA_CMD_WRITEAUXPAGE 0x0006 +#define SAMD_CTRLA_CMD_LOCK 0x0040 +#define SAMD_CTRLA_CMD_UNLOCK 0x0041 +#define SAMD_CTRLA_CMD_PAGEBUFFERCLEAR 0x0044 +#define SAMD_CTRLA_CMD_SSB 0x0045 +#define SAMD_CTRLA_CMD_INVALL 0x0046 /* Interrupt Flag Register (INTFLAG) */ -#define SAMD20_NVMC_READY (1 << 0) +#define SAMD_NVMC_READY (1 << 0) /* Non-Volatile Memory Calibration and Auxiliary Registers */ -#define SAMD20_NVM_USER_ROW_LOW 0x00804000 -#define SAMD20_NVM_USER_ROW_HIGH 0x00804004 -#define SAMD20_NVM_CALIBRATION 0x00806020 -#define SAMD20_NVM_SERIAL(n) (0x0080A00C + (0x30 * ((n + 3) / 4)) + \ +#define SAMD_NVM_USER_ROW_LOW 0x00804000 +#define SAMD_NVM_USER_ROW_HIGH 0x00804004 +#define SAMD_NVM_CALIBRATION 0x00806020 +#define SAMD_NVM_SERIAL(n) (0x0080A00C + (0x30 * ((n + 3) / 4)) + \ (0x4 * n)) /* -------------------------------------------------------------------------- */ /* Device Service Unit (DSU) Registers */ /* -------------------------------------------------------------------------- */ -#define SAMD20_DSU 0x41002000 -#define SAMD20_DSU_EXT_ACCESS (SAMD20_DSU + 0x100) -#define SAMD20_DSU_CTRLSTAT (SAMD20_DSU_EXT_ACCESS + 0x0) -#define SAMD20_DSU_ADDRESS (SAMD20_DSU_EXT_ACCESS + 0x4) -#define SAMD20_DSU_LENGTH (SAMD20_DSU_EXT_ACCESS + 0x8) -#define SAMD20_DSU_DID (SAMD20_DSU_EXT_ACCESS + 0x018) -#define SAMD20_DSU_PID(n) (SAMD20_DSU + 0x1FE0 + \ +#define SAMD_DSU 0x41002000 +#define SAMD_DSU_EXT_ACCESS (SAMD_DSU + 0x100) +#define SAMD_DSU_CTRLSTAT (SAMD_DSU_EXT_ACCESS + 0x0) +#define SAMD_DSU_ADDRESS (SAMD_DSU_EXT_ACCESS + 0x4) +#define SAMD_DSU_LENGTH (SAMD_DSU_EXT_ACCESS + 0x8) +#define SAMD_DSU_DID (SAMD_DSU_EXT_ACCESS + 0x018) +#define SAMD_DSU_PID(n) (SAMD_DSU + 0x1FE0 + \ (0x4 * (n % 4)) - (0x10 * (n / 4))) -#define SAMD20_DSU_CID(n) (SAMD20_DSU + 0x1FF0 + \ +#define SAMD_DSU_CID(n) (SAMD_DSU + 0x1FF0 + \ (0x4 * (n % 4))) /* Control and Status Register (CTRLSTAT) */ -#define SAMD20_CTRL_CHIP_ERASE (1 << 4) -#define SAMD20_CTRL_MBIST (1 << 3) -#define SAMD20_CTRL_CRC (1 << 2) -#define SAMD20_STATUSA_PERR (1 << 12) -#define SAMD20_STATUSA_FAIL (1 << 11) -#define SAMD20_STATUSA_BERR (1 << 10) -#define SAMD20_STATUSA_CRSTEXT (1 << 9) -#define SAMD20_STATUSA_DONE (1 << 8) -#define SAMD20_STATUSB_PROT (1 << 16) +#define SAMD_CTRL_CHIP_ERASE (1 << 4) +#define SAMD_CTRL_MBIST (1 << 3) +#define SAMD_CTRL_CRC (1 << 2) +#define SAMD_STATUSA_PERR (1 << 12) +#define SAMD_STATUSA_FAIL (1 << 11) +#define SAMD_STATUSA_BERR (1 << 10) +#define SAMD_STATUSA_CRSTEXT (1 << 9) +#define SAMD_STATUSA_DONE (1 << 8) +#define SAMD_STATUSB_PROT (1 << 16) /* Device Identification Register (DID) */ -#define SAMD20_DID_MASK 0xFFBF0000 -#define SAMD20_DID_CONST_VALUE 0x10000000 -#define SAMD20_DID_DEVSEL_MASK 0x0F -#define SAMD20_DID_DEVSEL_POS 0 -#define SAMD20_DID_REVISION_MASK 0x0F -#define SAMD20_DID_REVISION_POS 8 +#define SAMD_DID_MASK 0xFFBC0000 +#define SAMD_DID_CONST_VALUE 0x10000000 +#define SAMD_DID_DEVSEL_MASK 0x0F +#define SAMD_DID_DEVSEL_POS 0 +#define SAMD_DID_REVISION_MASK 0x0F +#define SAMD_DID_REVISION_POS 8 +#define SAMD_DID_SERIES_MASK 0x03 +#define SAMD_DID_SERIES_POS 16 /* Peripheral ID */ -#define SAMD20_PID_MASK 0x00F7FFFF -#define SAMD20_PID_CONST_VALUE 0x0001FCD0 +#define SAMD_PID_MASK 0x00F7FFFF +#define SAMD_PID_CONST_VALUE 0x0001FCD0 /* Component ID */ -#define SAMD20_CID_VALUE 0xB105100D +#define SAMD_CID_VALUE 0xB105100D /* Utility */ #define MINIMUM(a,b) ((a < b) ? a : b) @@ -161,7 +169,7 @@ static const char samd20_xml_memory_map[] = "" /** * Reads the SAM D20 Peripheral ID */ -uint64_t samd20_read_pid(struct target_s *target) +uint64_t samd_read_pid(struct target_s *target) { ADIv5_AP_t *ap = adiv5_target_ap(target); uint64_t pid = 0; @@ -169,14 +177,14 @@ uint64_t samd20_read_pid(struct target_s *target) /* Five PID registers to read LSB first */ for (i = 0, j = 0; i < 5; i++, j += 8) - pid |= (adiv5_ap_mem_read(ap, SAMD20_DSU_PID(i)) & 0xFF) << j; + pid |= (adiv5_ap_mem_read(ap, SAMD_DSU_PID(i)) & 0xFF) << j; return pid; } /** * Reads the SAM D20 Component ID */ -uint32_t samd20_read_cid(struct target_s *target) +uint32_t samd_read_cid(struct target_s *target) { ADIv5_AP_t *ap = adiv5_target_ap(target); uint64_t cid = 0; @@ -184,7 +192,7 @@ uint32_t samd20_read_cid(struct target_s *target) /* Four CID registers to read LSB first */ for (i = 0, j = 0; i < 4; i++, j += 8) - cid |= (adiv5_ap_mem_read(ap, SAMD20_DSU_CID(i)) & 0xFF) << j; + cid |= (adiv5_ap_mem_read(ap, SAMD_DSU_CID(i)) & 0xFF) << j; return cid; } @@ -194,7 +202,7 @@ uint32_t samd20_read_cid(struct target_s *target) * removes the target from extended reset where required. */ static void -samd20_reset(struct target_s *target) +samd_reset(struct target_s *target) { ADIv5_AP_t *ap = adiv5_target_ap(target); @@ -225,11 +233,11 @@ samd20_reset(struct target_s *target) CORTEXM_AIRCR_VECTKEY | CORTEXM_AIRCR_SYSRESETREQ); /* Exit extended reset */ - if (adiv5_ap_mem_read(ap, SAMD20_DSU_CTRLSTAT) & - SAMD20_STATUSA_CRSTEXT) { + if (adiv5_ap_mem_read(ap, SAMD_DSU_CTRLSTAT) & + SAMD_STATUSA_CRSTEXT) { /* Write bit to clear from extended reset */ - adiv5_ap_mem_write(ap, SAMD20_DSU_CTRLSTAT, - SAMD20_STATUSA_CRSTEXT); + adiv5_ap_mem_write(ap, SAMD_DSU_CTRLSTAT, + SAMD_STATUSA_CRSTEXT); } /* Poll for release from reset */ @@ -256,11 +264,11 @@ samd20_revB_detach(struct target_s *target) /* ---- Additional ---- */ /* Exit extended reset */ - if (adiv5_ap_mem_read(ap, SAMD20_DSU_CTRLSTAT) & - SAMD20_STATUSA_CRSTEXT) { + if (adiv5_ap_mem_read(ap, SAMD_DSU_CTRLSTAT) & + SAMD_STATUSA_CRSTEXT) { /* Write bit to clear from extended reset */ - adiv5_ap_mem_write(ap, SAMD20_DSU_CTRLSTAT, - SAMD20_STATUSA_CRSTEXT); + adiv5_ap_mem_write(ap, SAMD_DSU_CTRLSTAT, + SAMD_STATUSA_CRSTEXT); } } @@ -278,24 +286,24 @@ samd20_revB_halt_resume(struct target_s *target, bool step) /* ---- Additional ---- */ /* Exit extended reset */ - if (adiv5_ap_mem_read(ap, SAMD20_DSU_CTRLSTAT) & - SAMD20_STATUSA_CRSTEXT) { + if (adiv5_ap_mem_read(ap, SAMD_DSU_CTRLSTAT) & + SAMD_STATUSA_CRSTEXT) { /* Write bit to clear from extended reset */ - adiv5_ap_mem_write(ap, SAMD20_DSU_CTRLSTAT, - SAMD20_STATUSA_CRSTEXT); + adiv5_ap_mem_write(ap, SAMD_DSU_CTRLSTAT, + SAMD_STATUSA_CRSTEXT); } } /** - * Overload the default cortexm attach for when the samd20 is protected. + * Overload the default cortexm attach for when the samd is protected. * - * If the samd20 is protected then the default cortexm attach will + * If the samd is protected then the default cortexm attach will * fail as the S_HALT bit in the DHCSR will never go high. This * function allows users to attach on a temporary basis so they can * rescue the device. */ static bool -samd20_protected_attach(struct target_s *target) +samd_protected_attach(struct target_s *target) { /** * TODO: Notify the user that we're not really attached and @@ -310,62 +318,106 @@ samd20_protected_attach(struct target_s *target) return true; } +/** + * Use the DSU Device Indentification Register to populate a struct + * describing the SAM D device. + */ +struct samd_descr { + uint8_t series; + char revision; + char pin; + uint8_t mem; + char package[3]; +}; +struct samd_descr samd_parse_device_id(uint32_t did) +{ + struct samd_descr samd; + memset(samd.package, 0, 3); + + uint8_t series = (did >> SAMD_DID_SERIES_POS) + & SAMD_DID_SERIES_MASK; + uint8_t revision = (did >> SAMD_DID_REVISION_POS) + & SAMD_DID_REVISION_MASK; + uint8_t devsel = (did >> SAMD_DID_DEVSEL_POS) + & SAMD_DID_DEVSEL_MASK; + + /* Series */ + switch (series) { + case 0: samd.series = 20; break; + case 1: samd.series = 21; break; + case 2: samd.series = 10; break; + case 3: samd.series = 11; break; + } + /* Revision */ + samd.revision = 'A' + revision; + + switch (samd.series) { + case 20: /* SAM D20 */ + case 21: /* SAM D21 */ + switch (devsel / 5) { + case 0: samd.pin = 'J'; break; + case 1: samd.pin = 'G'; break; + case 2: samd.pin = 'E'; break; + default: samd.pin = 'u'; break; + } + samd.mem = 18 - (devsel % 5); + break; + case 10: /* SAM D10 */ + case 11: /* SAM D11 */ + switch (devsel / 3) { + case 0: samd.package[0] = 'M'; break; + case 1: samd.package[0] = 'S'; samd.package[1] = 'S'; break; + } + samd.pin = 'D'; + samd.mem = 14 - (devsel % 3); + break; + } + + return samd; +} + char variant_string[40]; -bool samd20_probe(struct target_s *target) +bool samd_probe(struct target_s *target) { ADIv5_AP_t *ap = adiv5_target_ap(target); - uint32_t cid = samd20_read_cid(target); - uint32_t pid = samd20_read_pid(target); + uint32_t cid = samd_read_cid(target); + uint32_t pid = samd_read_pid(target); /* Check the ARM Coresight Component and Perhiperal IDs */ - if (cid == SAMD20_CID_VALUE && - (pid & SAMD20_PID_MASK) == SAMD20_PID_CONST_VALUE) { + if (cid == SAMD_CID_VALUE && + (pid & SAMD_PID_MASK) == SAMD_PID_CONST_VALUE) { /* Read the Device ID */ - uint32_t did = adiv5_ap_mem_read(ap, SAMD20_DSU_DID); + uint32_t did = adiv5_ap_mem_read(ap, SAMD_DSU_DID); /* If the Device ID matches */ - if ((did & SAMD20_DID_MASK) == SAMD20_DID_CONST_VALUE) { - - uint8_t devsel = (did >> SAMD20_DID_DEVSEL_POS) - & SAMD20_DID_DEVSEL_MASK; - uint8_t revision = (did >> SAMD20_DID_REVISION_POS) - & SAMD20_DID_REVISION_MASK; - uint32_t ctrlstat = adiv5_ap_mem_read(ap, SAMD20_DSU_CTRLSTAT); - - /* Pin Variant */ - char pin_variant; - switch (devsel / 5) { - case 0: pin_variant = 'J'; break; - case 1: pin_variant = 'G'; break; - case 2: pin_variant = 'E'; break; - default: pin_variant = 'u'; break; - } - - /* Mem Variant */ - uint8_t mem_variant = 18 - (devsel % 5); + if ((did & SAMD_DID_MASK) == SAMD_DID_CONST_VALUE) { - /* Revision */ - char revision_variant = 'A' + revision; + uint32_t ctrlstat = adiv5_ap_mem_read(ap, SAMD_DSU_CTRLSTAT); + struct samd_descr samd = samd_parse_device_id(did); /* Protected? */ - int protected = (ctrlstat & SAMD20_STATUSB_PROT); + int protected = (ctrlstat & SAMD_STATUSB_PROT); /* Part String */ if (protected) { - sprintf(variant_string, "Atmel SAMD20%c%dA (rev %c) (PROT=1)", - pin_variant, mem_variant, revision_variant); + sprintf(variant_string, + "Atmel SAMD%d%c%dA%s (rev %c) (PROT=1)", + samd.series, samd.pin, samd.mem, + samd.package, samd.revision); } else { - sprintf(variant_string, "Atmel SAMD20%c%dA (rev %c)", - pin_variant, mem_variant, revision_variant); + sprintf(variant_string, + "Atmel SAMD%d%c%dA%s (rev %c)", + samd.series, samd.pin, samd.mem, + samd.package, samd.revision); } /* Setup Target */ target->driver = variant_string; - target->reset = samd20_reset; + target->reset = samd_reset; - if (revision_variant == 'B') { + if (samd.series == 20 && samd.revision == 'B') { /** * These functions check for and * extended reset. Appears to be @@ -377,29 +429,29 @@ bool samd20_probe(struct target_s *target) if (protected) { /** * Overload the default cortexm attach - * for when the samd20 is protected. + * for when the samd is protected. * This function allows users to * attach on a temporary basis so they * can rescue the device. */ - target->attach = samd20_protected_attach; + target->attach = samd_protected_attach; } - target->xml_mem_map = samd20_xml_memory_map; - target->flash_erase = samd20_flash_erase; - target->flash_write = samd20_flash_write; - target_add_commands(target, samd20_cmd_list, "SAMD20"); + target->xml_mem_map = samd_xml_memory_map; + target->flash_erase = samd_flash_erase; + target->flash_write = samd_flash_write; + target_add_commands(target, samd_cmd_list, "SAMD"); /* If we're not in reset here */ if (!connect_assert_srst) { /* We'll have to release the target from * extended reset to make attach possible */ - if (adiv5_ap_mem_read(ap, SAMD20_DSU_CTRLSTAT) & - SAMD20_STATUSA_CRSTEXT) { + if (adiv5_ap_mem_read(ap, SAMD_DSU_CTRLSTAT) & + SAMD_STATUSA_CRSTEXT) { /* Write bit to clear from extended reset */ - adiv5_ap_mem_write(ap, SAMD20_DSU_CTRLSTAT, - SAMD20_STATUSA_CRSTEXT); + adiv5_ap_mem_write(ap, SAMD_DSU_CTRLSTAT, + SAMD_STATUSA_CRSTEXT); } } @@ -413,51 +465,51 @@ bool samd20_probe(struct target_s *target) /** * Temporary (until next reset) flash memory locking / unlocking */ -static void samd20_lock_current_address(struct target_s *target) +static void samd_lock_current_address(struct target_s *target) { ADIv5_AP_t *ap = adiv5_target_ap(target); /* Issue the unlock command */ - adiv5_ap_mem_write(ap, SAMD20_NVMC_CTRLA, SAMD20_CTRLA_CMD_KEY | SAMD20_CTRLA_CMD_LOCK); + adiv5_ap_mem_write(ap, SAMD_NVMC_CTRLA, SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_LOCK); } -static void samd20_unlock_current_address(struct target_s *target) +static void samd_unlock_current_address(struct target_s *target) { ADIv5_AP_t *ap = adiv5_target_ap(target); /* Issue the unlock command */ - adiv5_ap_mem_write(ap, SAMD20_NVMC_CTRLA, SAMD20_CTRLA_CMD_KEY | SAMD20_CTRLA_CMD_UNLOCK); + adiv5_ap_mem_write(ap, SAMD_NVMC_CTRLA, SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_UNLOCK); } /** * Erase flash row by row */ -static int samd20_flash_erase(struct target_s *target, uint32_t addr, int len) +static int samd_flash_erase(struct target_s *target, uint32_t addr, int len) { ADIv5_AP_t *ap = adiv5_target_ap(target); - addr &= ~(SAMD20_ROW_SIZE - 1); - len &= ~(SAMD20_ROW_SIZE - 1); + addr &= ~(SAMD_ROW_SIZE - 1); + len &= ~(SAMD_ROW_SIZE - 1); while (len) { /* Write address of first word in row to erase it */ /* Must be shifted right for 16-bit address, see Datasheet §20.8.8 Address */ - adiv5_ap_mem_write(ap, SAMD20_NVMC_ADDRESS, addr >> 1); + adiv5_ap_mem_write(ap, SAMD_NVMC_ADDRESS, addr >> 1); /* Unlock */ - samd20_unlock_current_address(target); + samd_unlock_current_address(target); /* Issue the erase command */ - adiv5_ap_mem_write(ap, SAMD20_NVMC_CTRLA, SAMD20_CTRLA_CMD_KEY | SAMD20_CTRLA_CMD_ERASEROW); + adiv5_ap_mem_write(ap, SAMD_NVMC_CTRLA, SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_ERASEROW); /* Poll for NVM Ready */ - while ((adiv5_ap_mem_read(ap, SAMD20_NVMC_INTFLAG) & SAMD20_NVMC_READY) == 0) + while ((adiv5_ap_mem_read(ap, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0) if(target_check_error(target)) return -1; /* Lock */ - samd20_lock_current_address(target); + samd_lock_current_address(target); - addr += SAMD20_ROW_SIZE; - len -= SAMD20_ROW_SIZE; + addr += SAMD_ROW_SIZE; + len -= SAMD_ROW_SIZE; } return 0; @@ -466,7 +518,7 @@ static int samd20_flash_erase(struct target_s *target, uint32_t addr, int len) /** * Write flash page by page */ -static int samd20_flash_write(struct target_s *target, uint32_t dest, +static int samd_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, int len) { ADIv5_AP_t *ap = adiv5_target_ap(target); @@ -486,14 +538,14 @@ static int samd20_flash_write(struct target_s *target, uint32_t dest, uint32_t end = (dest + len - 1) & ~0x3; /* The start address of the first page involved in the write */ - uint32_t first_page = dest & ~(SAMD20_PAGE_SIZE - 1); + uint32_t first_page = dest & ~(SAMD_PAGE_SIZE - 1); /* The start address of the last page involved in the write */ - uint32_t last_page = (dest + len - 1) & ~(SAMD20_PAGE_SIZE - 1); + uint32_t last_page = (dest + len - 1) & ~(SAMD_PAGE_SIZE - 1); uint32_t end_of_this_page; - for (uint32_t page = first_page; page <= last_page; page += SAMD20_PAGE_SIZE) { - end_of_this_page = page + (SAMD20_PAGE_SIZE - 4); + for (uint32_t page = first_page; page <= last_page; page += SAMD_PAGE_SIZE) { + end_of_this_page = page + (SAMD_PAGE_SIZE - 4); if (addr > page || (page == last_page && end < end_of_this_page)) { /* Setup write */ @@ -509,17 +561,17 @@ static int samd20_flash_write(struct target_s *target, uint32_t dest, } /* Unlock */ - samd20_unlock_current_address(target); + samd_unlock_current_address(target); /* Issue the write page command */ - adiv5_ap_mem_write(ap, SAMD20_NVMC_CTRLA, - SAMD20_CTRLA_CMD_KEY | SAMD20_CTRLA_CMD_WRITEPAGE); + adiv5_ap_mem_write(ap, SAMD_NVMC_CTRLA, + SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_WRITEPAGE); } else { /* Write first word to set address */ adiv5_ap_mem_write(ap, addr, data[i]); addr += 4; i++; /* Unlock */ - samd20_unlock_current_address(target); + samd_unlock_current_address(target); /* Set up write */ adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw | @@ -529,18 +581,18 @@ static int samd20_flash_write(struct target_s *target, uint32_t dest, ((uint32_t)ap->apsel << 24)|(ADIV5_AP_DRW & 0xF0)); /* Full, automatic page write */ - for (; addr < page + SAMD20_PAGE_SIZE; addr += 4, i++) { + for (; addr < page + SAMD_PAGE_SIZE; addr += 4, i++) { adiv5_dp_write_ap(ap->dp, ADIV5_AP_DRW, data[i]); } } /* Poll for NVM Ready */ - while ((adiv5_ap_mem_read(ap, SAMD20_NVMC_INTFLAG) & SAMD20_NVMC_READY) == 0) + while ((adiv5_ap_mem_read(ap, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0) if(target_check_error(target)) return -1; /* Lock */ - samd20_lock_current_address(target); + samd_lock_current_address(target); } return 0; @@ -549,32 +601,32 @@ static int samd20_flash_write(struct target_s *target, uint32_t dest, /** * Uses the Device Service Unit to erase the entire flash */ -static bool samd20_cmd_erase_all(target *t) +static bool samd_cmd_erase_all(target *t) { ADIv5_AP_t *ap = adiv5_target_ap(t); /* Clear the DSU status bits */ - adiv5_ap_mem_write(ap, SAMD20_DSU_CTRLSTAT, - (SAMD20_STATUSA_DONE | SAMD20_STATUSA_PERR | SAMD20_STATUSA_FAIL)); + adiv5_ap_mem_write(ap, SAMD_DSU_CTRLSTAT, + (SAMD_STATUSA_DONE | SAMD_STATUSA_PERR | SAMD_STATUSA_FAIL)); /* Erase all */ - adiv5_ap_mem_write(ap, SAMD20_DSU_CTRLSTAT, SAMD20_CTRL_CHIP_ERASE); + adiv5_ap_mem_write(ap, SAMD_DSU_CTRLSTAT, SAMD_CTRL_CHIP_ERASE); /* Poll for DSU Ready */ uint32_t status; - while (((status = adiv5_ap_mem_read(ap, SAMD20_DSU_CTRLSTAT)) & - (SAMD20_STATUSA_DONE | SAMD20_STATUSA_PERR | SAMD20_STATUSA_FAIL)) == 0) + while (((status = adiv5_ap_mem_read(ap, SAMD_DSU_CTRLSTAT)) & + (SAMD_STATUSA_DONE | SAMD_STATUSA_PERR | SAMD_STATUSA_FAIL)) == 0) if(target_check_error(t)) return false; /* Test the protection error bit in Status A */ - if (status & SAMD20_STATUSA_PERR) { + if (status & SAMD_STATUSA_PERR) { gdb_outf("Erase failed due to a protection error.\n"); return true; } /* Test the fail bit in Status A */ - if (status & SAMD20_STATUSA_FAIL) { + if (status & SAMD_STATUSA_FAIL) { gdb_outf("Erase failed.\n"); return true; } @@ -591,22 +643,22 @@ static bool samd20_cmd_erase_all(target *t) * * 0x0000 = Lock, 0xFFFF = Unlock (default) */ -static bool samd20_set_flashlock(target *t, uint16_t value) +static bool samd_set_flashlock(target *t, uint16_t value) { ADIv5_AP_t *ap = adiv5_target_ap(t); - uint32_t high = adiv5_ap_mem_read(ap, SAMD20_NVM_USER_ROW_HIGH); - uint32_t low = adiv5_ap_mem_read(ap, SAMD20_NVM_USER_ROW_LOW); + uint32_t high = adiv5_ap_mem_read(ap, SAMD_NVM_USER_ROW_HIGH); + uint32_t low = adiv5_ap_mem_read(ap, SAMD_NVM_USER_ROW_LOW); /* Write address of a word in the row to erase it */ /* Must be shifted right for 16-bit address, see Datasheet §20.8.8 Address */ - adiv5_ap_mem_write(ap, SAMD20_NVMC_ADDRESS, SAMD20_NVM_USER_ROW_LOW >> 1); + adiv5_ap_mem_write(ap, SAMD_NVMC_ADDRESS, SAMD_NVM_USER_ROW_LOW >> 1); /* Issue the erase command */ - adiv5_ap_mem_write(ap, SAMD20_NVMC_CTRLA, SAMD20_CTRLA_CMD_KEY | SAMD20_CTRLA_CMD_ERASEAUXROW); + adiv5_ap_mem_write(ap, SAMD_NVMC_CTRLA, SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_ERASEAUXROW); /* Poll for NVM Ready */ - while ((adiv5_ap_mem_read(ap, SAMD20_NVMC_INTFLAG) & SAMD20_NVMC_READY) == 0) + while ((adiv5_ap_mem_read(ap, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0) if(target_check_error(t)) return -1; @@ -614,44 +666,44 @@ static bool samd20_set_flashlock(target *t, uint16_t value) high = (high & 0x0000FFFF) | ((value << 16) & 0xFFFF0000); /* Write back */ - adiv5_ap_mem_write(ap, SAMD20_NVM_USER_ROW_LOW, low); - adiv5_ap_mem_write(ap, SAMD20_NVM_USER_ROW_HIGH, high); + adiv5_ap_mem_write(ap, SAMD_NVM_USER_ROW_LOW, low); + adiv5_ap_mem_write(ap, SAMD_NVM_USER_ROW_HIGH, high); /* Issue the page write command */ - adiv5_ap_mem_write(ap, SAMD20_NVMC_CTRLA, - SAMD20_CTRLA_CMD_KEY | SAMD20_CTRLA_CMD_WRITEAUXPAGE); + adiv5_ap_mem_write(ap, SAMD_NVMC_CTRLA, + SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_WRITEAUXPAGE); return true; } -static bool samd20_cmd_lock_flash(target *t) +static bool samd_cmd_lock_flash(target *t) { - return samd20_set_flashlock(t, 0x0000); + return samd_set_flashlock(t, 0x0000); } -static bool samd20_cmd_unlock_flash(target *t) +static bool samd_cmd_unlock_flash(target *t) { - return samd20_set_flashlock(t, 0xFFFF); + return samd_set_flashlock(t, 0xFFFF); } -static bool samd20_cmd_read_userrow(target *t) +static bool samd_cmd_read_userrow(target *t) { ADIv5_AP_t *ap = adiv5_target_ap(t); gdb_outf("User Row: 0x%08x%08x\n", - adiv5_ap_mem_read(ap, SAMD20_NVM_USER_ROW_HIGH), - adiv5_ap_mem_read(ap, SAMD20_NVM_USER_ROW_LOW)); + adiv5_ap_mem_read(ap, SAMD_NVM_USER_ROW_HIGH), + adiv5_ap_mem_read(ap, SAMD_NVM_USER_ROW_LOW)); return true; } /** * Reads the 128-bit serial number from the NVM */ -static bool samd20_cmd_serial(target *t) +static bool samd_cmd_serial(target *t) { ADIv5_AP_t *ap = adiv5_target_ap(t); gdb_outf("Serial Number: 0x"); for (uint32_t i = 0; i < 4; i++) { - gdb_outf("%08x", adiv5_ap_mem_read(ap, SAMD20_NVM_SERIAL(i))); + gdb_outf("%08x", adiv5_ap_mem_read(ap, SAMD_NVM_SERIAL(i))); } gdb_outf("\n"); @@ -661,15 +713,15 @@ static bool samd20_cmd_serial(target *t) /** * Returns the size (in bytes) of the current SAM D20's flash memory. */ -static uint32_t samd20_flash_size(target *t) +static uint32_t samd_flash_size(target *t) { ADIv5_AP_t *ap = adiv5_target_ap(t); /* Read the Device ID */ - uint32_t did = adiv5_ap_mem_read(ap, SAMD20_DSU_DID); + uint32_t did = adiv5_ap_mem_read(ap, SAMD_DSU_DID); /* Mask off the device select bits */ - uint8_t devsel = did & SAMD20_DID_DEVSEL_MASK; + uint8_t devsel = did & SAMD_DID_DEVSEL_MASK; /* Shift the maximum flash size (256KB) down as appropriate */ return (0x40000 >> (devsel % 5)); @@ -677,37 +729,37 @@ static uint32_t samd20_flash_size(target *t) /** * Runs the Memory Built In Self Test (MBIST) */ -static bool samd20_cmd_mbist(target *t) +static bool samd_cmd_mbist(target *t) { ADIv5_AP_t *ap = adiv5_target_ap(t); /* Write the memory parameters to the DSU */ - adiv5_ap_mem_write(ap, SAMD20_DSU_ADDRESS, 0); - adiv5_ap_mem_write(ap, SAMD20_DSU_LENGTH, samd20_flash_size(t)); + adiv5_ap_mem_write(ap, SAMD_DSU_ADDRESS, 0); + adiv5_ap_mem_write(ap, SAMD_DSU_LENGTH, samd_flash_size(t)); /* Clear the fail bit */ - adiv5_ap_mem_write(ap, SAMD20_DSU_CTRLSTAT, SAMD20_STATUSA_FAIL); + adiv5_ap_mem_write(ap, SAMD_DSU_CTRLSTAT, SAMD_STATUSA_FAIL); /* Write the MBIST command */ - adiv5_ap_mem_write(ap, SAMD20_DSU_CTRLSTAT, SAMD20_CTRL_MBIST); + adiv5_ap_mem_write(ap, SAMD_DSU_CTRLSTAT, SAMD_CTRL_MBIST); /* Poll for DSU Ready */ uint32_t status; - while (((status = adiv5_ap_mem_read(ap, SAMD20_DSU_CTRLSTAT)) & - (SAMD20_STATUSA_DONE | SAMD20_STATUSA_PERR | SAMD20_STATUSA_FAIL)) == 0) + while (((status = adiv5_ap_mem_read(ap, SAMD_DSU_CTRLSTAT)) & + (SAMD_STATUSA_DONE | SAMD_STATUSA_PERR | SAMD_STATUSA_FAIL)) == 0) if(target_check_error(t)) return false; /* Test the protection error bit in Status A */ - if (status & SAMD20_STATUSA_PERR) { + if (status & SAMD_STATUSA_PERR) { gdb_outf("MBIST not run due to protection error.\n"); return true; } /* Test the fail bit in Status A */ - if (status & SAMD20_STATUSA_FAIL) { + if (status & SAMD_STATUSA_FAIL) { gdb_outf("MBIST Fail @ 0x%08x\n", - adiv5_ap_mem_read(ap, SAMD20_DSU_ADDRESS)); + adiv5_ap_mem_read(ap, SAMD_DSU_ADDRESS)); } else { gdb_outf("MBIST Passed!\n"); } @@ -717,15 +769,15 @@ static bool samd20_cmd_mbist(target *t) /** * Sets the security bit */ -static bool samd20_cmd_ssb(target *t) +static bool samd_cmd_ssb(target *t) { ADIv5_AP_t *ap = adiv5_target_ap(t); /* Issue the ssb command */ - adiv5_ap_mem_write(ap, SAMD20_NVMC_CTRLA, SAMD20_CTRLA_CMD_KEY | SAMD20_CTRLA_CMD_SSB); + adiv5_ap_mem_write(ap, SAMD_NVMC_CTRLA, SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_SSB); /* Poll for NVM Ready */ - while ((adiv5_ap_mem_read(ap, SAMD20_NVMC_INTFLAG) & SAMD20_NVMC_READY) == 0) + while ((adiv5_ap_mem_read(ap, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0) if(target_check_error(t)) return -1; -- cgit v1.2.3 From ea78e2d737cbe4a61156fdddc140fba4eab0bc3d Mon Sep 17 00:00:00 2001 From: Richard Meadows Date: Sun, 18 Jan 2015 22:40:02 +0000 Subject: Complete refactor of samd20 -> samd --- src/Makefile | 3 +- src/samd.c | 788 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ src/samd20.c | 788 ----------------------------------------------------------- 3 files changed, 789 insertions(+), 790 deletions(-) create mode 100644 src/samd.c delete mode 100644 src/samd20.c (limited to 'src') diff --git a/src/Makefile b/src/Makefile index b30922c..fcf5d1f 100644 --- a/src/Makefile +++ b/src/Makefile @@ -32,7 +32,7 @@ SRC = \ nrf51.c \ platform.c \ sam3x.c \ - samd20.c \ + samd.c \ stm32f1.c \ stm32f4.c \ stm32l1.c \ @@ -53,4 +53,3 @@ clean: host_clean -$(RM) platforms/*/*.o platforms/*/*.d mapfile -include *.d - diff --git a/src/samd.c b/src/samd.c new file mode 100644 index 0000000..b043c50 --- /dev/null +++ b/src/samd.c @@ -0,0 +1,788 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2014 Richard Meadows + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * 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, see . + */ + +/* This file implements Atmel SAM D target specific functions for + * detecting the device, providing the XML memory map and Flash memory + * programming. + * + * Tested with + * * SAMD20E17A (rev C) + * * SAMD20J18A (rev B) + * * SAMD21J18A (rev B) + * * + */ +/* Refer to the SAM D20 Datasheet: + * http://www.atmel.com/Images/Atmel-42129-SAM-D20_Datasheet.pdf + * particularly Sections 12. DSU and 20. NVMCTRL + */ + +#include +#include +#include + +#include "general.h" +#include "jtagtap.h" +#include "adiv5.h" +#include "target.h" +#include "command.h" +#include "gdb_packet.h" +#include "cortexm.h" + +static int samd_flash_erase(struct target_s *target, uint32_t addr, int len); +static int samd_flash_write(struct target_s *target, uint32_t dest, + const uint8_t *src, int len); + +static bool samd_cmd_erase_all(target *t); +static bool samd_cmd_lock_flash(target *t); +static bool samd_cmd_unlock_flash(target *t); +static bool samd_cmd_read_userrow(target *t); +static bool samd_cmd_serial(target *t); +static bool samd_cmd_mbist(target *t); +static bool samd_cmd_ssb(target *t); + +const struct command_s samd_cmd_list[] = { + {"erase_mass", (cmd_handler)samd_cmd_erase_all, "Erase entire flash memory"}, + {"lock_flash", (cmd_handler)samd_cmd_lock_flash, "Locks flash against spurious commands"}, + {"unlock_flash", (cmd_handler)samd_cmd_unlock_flash, "Unlocks flash"}, + {"user_row", (cmd_handler)samd_cmd_read_userrow, "Prints user row from flash"}, + {"serial", (cmd_handler)samd_cmd_serial, "Prints serial number"}, + {"mbist", (cmd_handler)samd_cmd_mbist, "Runs the built-in memory test"}, + {"set_security_bit", (cmd_handler)samd_cmd_ssb, "Sets the Security Bit"}, + {NULL, NULL, NULL} +}; + +/** + * 256KB Flash Max., 32KB RAM Max. The smallest unit of erase is the + * one row = 256 bytes. + */ +static const char samd_xml_memory_map[] = "" +/* ""*/ + "" + " " + " 0x100" + " " + " " + ""; + +/* Non-Volatile Memory Controller (NVMC) Parameters */ +#define SAMD_ROW_SIZE 256 +#define SAMD_PAGE_SIZE 64 + +/* -------------------------------------------------------------------------- */ +/* Non-Volatile Memory Controller (NVMC) Registers */ +/* -------------------------------------------------------------------------- */ + +#define SAMD_NVMC 0x41004000 +#define SAMD_NVMC_CTRLA (SAMD_NVMC + 0x0) +#define SAMD_NVMC_CTRLB (SAMD_NVMC + 0x04) +#define SAMD_NVMC_PARAM (SAMD_NVMC + 0x08) +#define SAMD_NVMC_INTFLAG (SAMD_NVMC + 0x14) +#define SAMD_NVMC_STATUS (SAMD_NVMC + 0x18) +#define SAMD_NVMC_ADDRESS (SAMD_NVMC + 0x1C) + +/* Control A Register (CTRLA) */ +#define SAMD_CTRLA_CMD_KEY 0xA500 +#define SAMD_CTRLA_CMD_ERASEROW 0x0002 +#define SAMD_CTRLA_CMD_WRITEPAGE 0x0004 +#define SAMD_CTRLA_CMD_ERASEAUXROW 0x0005 +#define SAMD_CTRLA_CMD_WRITEAUXPAGE 0x0006 +#define SAMD_CTRLA_CMD_LOCK 0x0040 +#define SAMD_CTRLA_CMD_UNLOCK 0x0041 +#define SAMD_CTRLA_CMD_PAGEBUFFERCLEAR 0x0044 +#define SAMD_CTRLA_CMD_SSB 0x0045 +#define SAMD_CTRLA_CMD_INVALL 0x0046 + +/* Interrupt Flag Register (INTFLAG) */ +#define SAMD_NVMC_READY (1 << 0) + +/* Non-Volatile Memory Calibration and Auxiliary Registers */ +#define SAMD_NVM_USER_ROW_LOW 0x00804000 +#define SAMD_NVM_USER_ROW_HIGH 0x00804004 +#define SAMD_NVM_CALIBRATION 0x00806020 +#define SAMD_NVM_SERIAL(n) (0x0080A00C + (0x30 * ((n + 3) / 4)) + \ + (0x4 * n)) + +/* -------------------------------------------------------------------------- */ +/* Device Service Unit (DSU) Registers */ +/* -------------------------------------------------------------------------- */ + +#define SAMD_DSU 0x41002000 +#define SAMD_DSU_EXT_ACCESS (SAMD_DSU + 0x100) +#define SAMD_DSU_CTRLSTAT (SAMD_DSU_EXT_ACCESS + 0x0) +#define SAMD_DSU_ADDRESS (SAMD_DSU_EXT_ACCESS + 0x4) +#define SAMD_DSU_LENGTH (SAMD_DSU_EXT_ACCESS + 0x8) +#define SAMD_DSU_DID (SAMD_DSU_EXT_ACCESS + 0x018) +#define SAMD_DSU_PID(n) (SAMD_DSU + 0x1FE0 + \ + (0x4 * (n % 4)) - (0x10 * (n / 4))) +#define SAMD_DSU_CID(n) (SAMD_DSU + 0x1FF0 + \ + (0x4 * (n % 4))) + +/* Control and Status Register (CTRLSTAT) */ +#define SAMD_CTRL_CHIP_ERASE (1 << 4) +#define SAMD_CTRL_MBIST (1 << 3) +#define SAMD_CTRL_CRC (1 << 2) +#define SAMD_STATUSA_PERR (1 << 12) +#define SAMD_STATUSA_FAIL (1 << 11) +#define SAMD_STATUSA_BERR (1 << 10) +#define SAMD_STATUSA_CRSTEXT (1 << 9) +#define SAMD_STATUSA_DONE (1 << 8) +#define SAMD_STATUSB_PROT (1 << 16) + +/* Device Identification Register (DID) */ +#define SAMD_DID_MASK 0xFFBC0000 +#define SAMD_DID_CONST_VALUE 0x10000000 +#define SAMD_DID_DEVSEL_MASK 0x0F +#define SAMD_DID_DEVSEL_POS 0 +#define SAMD_DID_REVISION_MASK 0x0F +#define SAMD_DID_REVISION_POS 8 +#define SAMD_DID_SERIES_MASK 0x03 +#define SAMD_DID_SERIES_POS 16 + +/* Peripheral ID */ +#define SAMD_PID_MASK 0x00F7FFFF +#define SAMD_PID_CONST_VALUE 0x0001FCD0 + +/* Component ID */ +#define SAMD_CID_VALUE 0xB105100D + +/* Utility */ +#define MINIMUM(a,b) ((a < b) ? a : b) + +/** + * Reads the SAM D20 Peripheral ID + */ +uint64_t samd_read_pid(struct target_s *target) +{ + ADIv5_AP_t *ap = adiv5_target_ap(target); + uint64_t pid = 0; + uint8_t i, j; + + /* Five PID registers to read LSB first */ + for (i = 0, j = 0; i < 5; i++, j += 8) + pid |= (adiv5_ap_mem_read(ap, SAMD_DSU_PID(i)) & 0xFF) << j; + + return pid; +} +/** + * Reads the SAM D20 Component ID + */ +uint32_t samd_read_cid(struct target_s *target) +{ + ADIv5_AP_t *ap = adiv5_target_ap(target); + uint64_t cid = 0; + uint8_t i, j; + + /* Four CID registers to read LSB first */ + for (i = 0, j = 0; i < 4; i++, j += 8) + cid |= (adiv5_ap_mem_read(ap, SAMD_DSU_CID(i)) & 0xFF) << j; + + return cid; +} + +/** + * Overloads the default cortexm reset function with a version that + * removes the target from extended reset where required. + */ +static void +samd_reset(struct target_s *target) +{ + ADIv5_AP_t *ap = adiv5_target_ap(target); + + /** + * SRST is not asserted here as it appears to reset the adiv5 + * logic, meaning that subsequent adiv5_* calls PLATFORM_FATAL_ERROR. + * + * This is ok as normally you can just connect the debugger and go, + * but if that's not possible (protection or SWCLK being used for + * something else) then having SWCLK low on reset should get you + * debug access (cold-plugging). TODO: Confirm this + * + * See the SAM D20 datasheet §12.6 Debug Operation for more + * details. + * + * jtagtap_srst(true); + * jtagtap_srst(false); + */ + + /* Read DHCSR here to clear S_RESET_ST bit before reset */ + adiv5_ap_mem_read(ap, CORTEXM_DHCSR); + + /* Request system reset from NVIC: SRST doesn't work correctly */ + /* This could be VECTRESET: 0x05FA0001 (reset only core) + * or SYSRESETREQ: 0x05FA0004 (system reset) + */ + adiv5_ap_mem_write(ap, CORTEXM_AIRCR, + CORTEXM_AIRCR_VECTKEY | CORTEXM_AIRCR_SYSRESETREQ); + + /* Exit extended reset */ + if (adiv5_ap_mem_read(ap, SAMD_DSU_CTRLSTAT) & + SAMD_STATUSA_CRSTEXT) { + /* Write bit to clear from extended reset */ + adiv5_ap_mem_write(ap, SAMD_DSU_CTRLSTAT, + SAMD_STATUSA_CRSTEXT); + } + + /* Poll for release from reset */ + while(adiv5_ap_mem_read(ap, CORTEXM_DHCSR) & CORTEXM_DHCSR_S_RESET_ST); + + /* Reset DFSR flags */ + adiv5_ap_mem_write(ap, CORTEXM_DFSR, CORTEXM_DFSR_RESETALL); + + /* Clear any target errors */ + target_check_error(target); +} + +/** + * Overloads the default cortexm detached function with a version that + * removes the target from extended reset where required. + * + * Only required for SAM D20 _Revision B_ Silicon + */ +static void +samd20_revB_detach(struct target_s *target) +{ + ADIv5_AP_t *ap = adiv5_target_ap(target); + cortexm_detach(target); + + /* ---- Additional ---- */ + /* Exit extended reset */ + if (adiv5_ap_mem_read(ap, SAMD_DSU_CTRLSTAT) & + SAMD_STATUSA_CRSTEXT) { + /* Write bit to clear from extended reset */ + adiv5_ap_mem_write(ap, SAMD_DSU_CTRLSTAT, + SAMD_STATUSA_CRSTEXT); + } +} + +/** + * Overloads the default cortexm halt_resume function with a version + * that removes the target from extended reset where required. + * + * Only required for SAM D20 _Revision B_ Silicon + */ +static void +samd20_revB_halt_resume(struct target_s *target, bool step) +{ + ADIv5_AP_t *ap = adiv5_target_ap(target); + cortexm_halt_resume(target, step); + + /* ---- Additional ---- */ + /* Exit extended reset */ + if (adiv5_ap_mem_read(ap, SAMD_DSU_CTRLSTAT) & + SAMD_STATUSA_CRSTEXT) { + /* Write bit to clear from extended reset */ + adiv5_ap_mem_write(ap, SAMD_DSU_CTRLSTAT, + SAMD_STATUSA_CRSTEXT); + } +} + +/** + * Overload the default cortexm attach for when the samd is protected. + * + * If the samd is protected then the default cortexm attach will + * fail as the S_HALT bit in the DHCSR will never go high. This + * function allows users to attach on a temporary basis so they can + * rescue the device. + */ +static bool +samd_protected_attach(struct target_s *target) +{ + /** + * TODO: Notify the user that we're not really attached and + * they should issue the 'monitor erase_mass' command to + * regain access to the chip. + */ + + /* Patch back in the normal cortexm attach for next time */ + target->attach = cortexm_attach; + + /* Allow attach this time */ + return true; +} + +/** + * Use the DSU Device Indentification Register to populate a struct + * describing the SAM D device. + */ +struct samd_descr { + uint8_t series; + char revision; + char pin; + uint8_t mem; + char package[3]; +}; +struct samd_descr samd_parse_device_id(uint32_t did) +{ + struct samd_descr samd; + memset(samd.package, 0, 3); + + uint8_t series = (did >> SAMD_DID_SERIES_POS) + & SAMD_DID_SERIES_MASK; + uint8_t revision = (did >> SAMD_DID_REVISION_POS) + & SAMD_DID_REVISION_MASK; + uint8_t devsel = (did >> SAMD_DID_DEVSEL_POS) + & SAMD_DID_DEVSEL_MASK; + + /* Series */ + switch (series) { + case 0: samd.series = 20; break; + case 1: samd.series = 21; break; + case 2: samd.series = 10; break; + case 3: samd.series = 11; break; + } + /* Revision */ + samd.revision = 'A' + revision; + + switch (samd.series) { + case 20: /* SAM D20 */ + case 21: /* SAM D21 */ + switch (devsel / 5) { + case 0: samd.pin = 'J'; break; + case 1: samd.pin = 'G'; break; + case 2: samd.pin = 'E'; break; + default: samd.pin = 'u'; break; + } + samd.mem = 18 - (devsel % 5); + break; + case 10: /* SAM D10 */ + case 11: /* SAM D11 */ + switch (devsel / 3) { + case 0: samd.package[0] = 'M'; break; + case 1: samd.package[0] = 'S'; samd.package[1] = 'S'; break; + } + samd.pin = 'D'; + samd.mem = 14 - (devsel % 3); + break; + } + + return samd; +} + + +char variant_string[40]; +bool samd_probe(struct target_s *target) +{ + ADIv5_AP_t *ap = adiv5_target_ap(target); + uint32_t cid = samd_read_cid(target); + uint32_t pid = samd_read_pid(target); + + /* Check the ARM Coresight Component and Perhiperal IDs */ + if (cid == SAMD_CID_VALUE && + (pid & SAMD_PID_MASK) == SAMD_PID_CONST_VALUE) { + + /* Read the Device ID */ + uint32_t did = adiv5_ap_mem_read(ap, SAMD_DSU_DID); + + /* If the Device ID matches */ + if ((did & SAMD_DID_MASK) == SAMD_DID_CONST_VALUE) { + + uint32_t ctrlstat = adiv5_ap_mem_read(ap, SAMD_DSU_CTRLSTAT); + struct samd_descr samd = samd_parse_device_id(did); + + /* Protected? */ + int protected = (ctrlstat & SAMD_STATUSB_PROT); + + /* Part String */ + if (protected) { + sprintf(variant_string, + "Atmel SAMD%d%c%dA%s (rev %c) (PROT=1)", + samd.series, samd.pin, samd.mem, + samd.package, samd.revision); + } else { + sprintf(variant_string, + "Atmel SAMD%d%c%dA%s (rev %c)", + samd.series, samd.pin, samd.mem, + samd.package, samd.revision); + } + + /* Setup Target */ + target->driver = variant_string; + target->reset = samd_reset; + + if (samd.series == 20 && samd.revision == 'B') { + /** + * These functions check for and + * extended reset. Appears to be + * related to Errata 35.4.1 ref 12015 + */ + target->detach = samd20_revB_detach; + target->halt_resume = samd20_revB_halt_resume; + } + if (protected) { + /** + * Overload the default cortexm attach + * for when the samd is protected. + * This function allows users to + * attach on a temporary basis so they + * can rescue the device. + */ + target->attach = samd_protected_attach; + } + + target->xml_mem_map = samd_xml_memory_map; + target->flash_erase = samd_flash_erase; + target->flash_write = samd_flash_write; + target_add_commands(target, samd_cmd_list, "SAMD"); + + /* If we're not in reset here */ + if (!connect_assert_srst) { + /* We'll have to release the target from + * extended reset to make attach possible */ + if (adiv5_ap_mem_read(ap, SAMD_DSU_CTRLSTAT) & + SAMD_STATUSA_CRSTEXT) { + + /* Write bit to clear from extended reset */ + adiv5_ap_mem_write(ap, SAMD_DSU_CTRLSTAT, + SAMD_STATUSA_CRSTEXT); + } + } + + return true; + } + } + + return false; +} + +/** + * Temporary (until next reset) flash memory locking / unlocking + */ +static void samd_lock_current_address(struct target_s *target) +{ + ADIv5_AP_t *ap = adiv5_target_ap(target); + + /* Issue the unlock command */ + adiv5_ap_mem_write(ap, SAMD_NVMC_CTRLA, SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_LOCK); +} +static void samd_unlock_current_address(struct target_s *target) +{ + ADIv5_AP_t *ap = adiv5_target_ap(target); + + /* Issue the unlock command */ + adiv5_ap_mem_write(ap, SAMD_NVMC_CTRLA, SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_UNLOCK); +} + +/** + * Erase flash row by row + */ +static int samd_flash_erase(struct target_s *target, uint32_t addr, int len) +{ + ADIv5_AP_t *ap = adiv5_target_ap(target); + + addr &= ~(SAMD_ROW_SIZE - 1); + len &= ~(SAMD_ROW_SIZE - 1); + + while (len) { + /* Write address of first word in row to erase it */ + /* Must be shifted right for 16-bit address, see Datasheet §20.8.8 Address */ + adiv5_ap_mem_write(ap, SAMD_NVMC_ADDRESS, addr >> 1); + + /* Unlock */ + samd_unlock_current_address(target); + + /* Issue the erase command */ + adiv5_ap_mem_write(ap, SAMD_NVMC_CTRLA, SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_ERASEROW); + /* Poll for NVM Ready */ + while ((adiv5_ap_mem_read(ap, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0) + if(target_check_error(target)) + return -1; + + /* Lock */ + samd_lock_current_address(target); + + addr += SAMD_ROW_SIZE; + len -= SAMD_ROW_SIZE; + } + + return 0; +} + +/** + * Write flash page by page + */ +static int samd_flash_write(struct target_s *target, uint32_t dest, + const uint8_t *src, int len) +{ + ADIv5_AP_t *ap = adiv5_target_ap(target); + + /* Find the size of our 32-bit data buffer */ + uint32_t offset = dest % 4; + uint32_t words = (offset + len + 3) / 4; + uint32_t data[words], i = 0; + + /* Populate the data buffer */ + memset((uint8_t *)data, 0xFF, words * 4); + memcpy((uint8_t *)data + offset, src, len); + + /* The address of the first word involved in the write */ + uint32_t addr = dest & ~0x3; + /* The address of the last word involved in the write */ + uint32_t end = (dest + len - 1) & ~0x3; + + /* The start address of the first page involved in the write */ + uint32_t first_page = dest & ~(SAMD_PAGE_SIZE - 1); + /* The start address of the last page involved in the write */ + uint32_t last_page = (dest + len - 1) & ~(SAMD_PAGE_SIZE - 1); + uint32_t end_of_this_page; + + + for (uint32_t page = first_page; page <= last_page; page += SAMD_PAGE_SIZE) { + end_of_this_page = page + (SAMD_PAGE_SIZE - 4); + + if (addr > page || (page == last_page && end < end_of_this_page)) { + /* Setup write */ + adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw | + ADIV5_AP_CSW_SIZE_WORD | ADIV5_AP_CSW_ADDRINC_SINGLE); + adiv5_ap_write(ap, ADIV5_AP_TAR, addr); + adiv5_dp_write(ap->dp, ADIV5_DP_SELECT, + ((uint32_t)ap->apsel << 24)|(ADIV5_AP_DRW & 0xF0)); + + /* Partial, manual page write */ + for (; addr <= MINIMUM(end, end_of_this_page); addr += 4, i++) { + adiv5_dp_write_ap(ap->dp, ADIV5_AP_DRW, data[i]); + } + + /* Unlock */ + samd_unlock_current_address(target); + + /* Issue the write page command */ + adiv5_ap_mem_write(ap, SAMD_NVMC_CTRLA, + SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_WRITEPAGE); + } else { + /* Write first word to set address */ + adiv5_ap_mem_write(ap, addr, data[i]); addr += 4; i++; + + /* Unlock */ + samd_unlock_current_address(target); + + /* Set up write */ + adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw | + ADIV5_AP_CSW_SIZE_WORD | ADIV5_AP_CSW_ADDRINC_SINGLE); + adiv5_ap_write(ap, ADIV5_AP_TAR, addr); + adiv5_dp_write(ap->dp, ADIV5_DP_SELECT, + ((uint32_t)ap->apsel << 24)|(ADIV5_AP_DRW & 0xF0)); + + /* Full, automatic page write */ + for (; addr < page + SAMD_PAGE_SIZE; addr += 4, i++) { + adiv5_dp_write_ap(ap->dp, ADIV5_AP_DRW, data[i]); + } + } + + /* Poll for NVM Ready */ + while ((adiv5_ap_mem_read(ap, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0) + if(target_check_error(target)) + return -1; + + /* Lock */ + samd_lock_current_address(target); + } + + return 0; +} + +/** + * Uses the Device Service Unit to erase the entire flash + */ +static bool samd_cmd_erase_all(target *t) +{ + ADIv5_AP_t *ap = adiv5_target_ap(t); + + /* Clear the DSU status bits */ + adiv5_ap_mem_write(ap, SAMD_DSU_CTRLSTAT, + (SAMD_STATUSA_DONE | SAMD_STATUSA_PERR | SAMD_STATUSA_FAIL)); + + /* Erase all */ + adiv5_ap_mem_write(ap, SAMD_DSU_CTRLSTAT, SAMD_CTRL_CHIP_ERASE); + + /* Poll for DSU Ready */ + uint32_t status; + while (((status = adiv5_ap_mem_read(ap, SAMD_DSU_CTRLSTAT)) & + (SAMD_STATUSA_DONE | SAMD_STATUSA_PERR | SAMD_STATUSA_FAIL)) == 0) + if(target_check_error(t)) + return false; + + /* Test the protection error bit in Status A */ + if (status & SAMD_STATUSA_PERR) { + gdb_outf("Erase failed due to a protection error.\n"); + return true; + } + + /* Test the fail bit in Status A */ + if (status & SAMD_STATUSA_FAIL) { + gdb_outf("Erase failed.\n"); + return true; + } + + gdb_outf("Erase successful!\n"); + + return true; +} + +/** + * Sets the NVM region lock bits in the User Row. This value is read + * at startup as the default value for the lock bits, and hence does + * not take effect until a reset. + * + * 0x0000 = Lock, 0xFFFF = Unlock (default) + */ +static bool samd_set_flashlock(target *t, uint16_t value) +{ + ADIv5_AP_t *ap = adiv5_target_ap(t); + + uint32_t high = adiv5_ap_mem_read(ap, SAMD_NVM_USER_ROW_HIGH); + uint32_t low = adiv5_ap_mem_read(ap, SAMD_NVM_USER_ROW_LOW); + + /* Write address of a word in the row to erase it */ + /* Must be shifted right for 16-bit address, see Datasheet §20.8.8 Address */ + adiv5_ap_mem_write(ap, SAMD_NVMC_ADDRESS, SAMD_NVM_USER_ROW_LOW >> 1); + + /* Issue the erase command */ + adiv5_ap_mem_write(ap, SAMD_NVMC_CTRLA, SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_ERASEAUXROW); + + /* Poll for NVM Ready */ + while ((adiv5_ap_mem_read(ap, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0) + if(target_check_error(t)) + return -1; + + /* Modify the high byte of the user row */ + high = (high & 0x0000FFFF) | ((value << 16) & 0xFFFF0000); + + /* Write back */ + adiv5_ap_mem_write(ap, SAMD_NVM_USER_ROW_LOW, low); + adiv5_ap_mem_write(ap, SAMD_NVM_USER_ROW_HIGH, high); + + /* Issue the page write command */ + adiv5_ap_mem_write(ap, SAMD_NVMC_CTRLA, + SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_WRITEAUXPAGE); + + return true; +} +static bool samd_cmd_lock_flash(target *t) +{ + return samd_set_flashlock(t, 0x0000); +} +static bool samd_cmd_unlock_flash(target *t) +{ + return samd_set_flashlock(t, 0xFFFF); +} +static bool samd_cmd_read_userrow(target *t) +{ + ADIv5_AP_t *ap = adiv5_target_ap(t); + + gdb_outf("User Row: 0x%08x%08x\n", + adiv5_ap_mem_read(ap, SAMD_NVM_USER_ROW_HIGH), + adiv5_ap_mem_read(ap, SAMD_NVM_USER_ROW_LOW)); + + return true; +} +/** + * Reads the 128-bit serial number from the NVM + */ +static bool samd_cmd_serial(target *t) +{ + ADIv5_AP_t *ap = adiv5_target_ap(t); + + gdb_outf("Serial Number: 0x"); + + for (uint32_t i = 0; i < 4; i++) { + gdb_outf("%08x", adiv5_ap_mem_read(ap, SAMD_NVM_SERIAL(i))); + } + + gdb_outf("\n"); + + return true; +} +/** + * Returns the size (in bytes) of the current SAM D20's flash memory. + */ +static uint32_t samd_flash_size(target *t) +{ + ADIv5_AP_t *ap = adiv5_target_ap(t); + + /* Read the Device ID */ + uint32_t did = adiv5_ap_mem_read(ap, SAMD_DSU_DID); + + /* Mask off the device select bits */ + uint8_t devsel = did & SAMD_DID_DEVSEL_MASK; + + /* Shift the maximum flash size (256KB) down as appropriate */ + return (0x40000 >> (devsel % 5)); +} +/** + * Runs the Memory Built In Self Test (MBIST) + */ +static bool samd_cmd_mbist(target *t) +{ + ADIv5_AP_t *ap = adiv5_target_ap(t); + + /* Write the memory parameters to the DSU */ + adiv5_ap_mem_write(ap, SAMD_DSU_ADDRESS, 0); + adiv5_ap_mem_write(ap, SAMD_DSU_LENGTH, samd_flash_size(t)); + + /* Clear the fail bit */ + adiv5_ap_mem_write(ap, SAMD_DSU_CTRLSTAT, SAMD_STATUSA_FAIL); + + /* Write the MBIST command */ + adiv5_ap_mem_write(ap, SAMD_DSU_CTRLSTAT, SAMD_CTRL_MBIST); + + /* Poll for DSU Ready */ + uint32_t status; + while (((status = adiv5_ap_mem_read(ap, SAMD_DSU_CTRLSTAT)) & + (SAMD_STATUSA_DONE | SAMD_STATUSA_PERR | SAMD_STATUSA_FAIL)) == 0) + if(target_check_error(t)) + return false; + + /* Test the protection error bit in Status A */ + if (status & SAMD_STATUSA_PERR) { + gdb_outf("MBIST not run due to protection error.\n"); + return true; + } + + /* Test the fail bit in Status A */ + if (status & SAMD_STATUSA_FAIL) { + gdb_outf("MBIST Fail @ 0x%08x\n", + adiv5_ap_mem_read(ap, SAMD_DSU_ADDRESS)); + } else { + gdb_outf("MBIST Passed!\n"); + } + + return true; +} +/** + * Sets the security bit + */ +static bool samd_cmd_ssb(target *t) +{ + ADIv5_AP_t *ap = adiv5_target_ap(t); + + /* Issue the ssb command */ + adiv5_ap_mem_write(ap, SAMD_NVMC_CTRLA, SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_SSB); + + /* Poll for NVM Ready */ + while ((adiv5_ap_mem_read(ap, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0) + if(target_check_error(t)) + return -1; + + gdb_outf("Set the security bit! " + "You will need to issue 'monitor erase_mass' to clear this.\n"); + + return true; +} diff --git a/src/samd20.c b/src/samd20.c deleted file mode 100644 index b043c50..0000000 --- a/src/samd20.c +++ /dev/null @@ -1,788 +0,0 @@ -/* - * This file is part of the Black Magic Debug project. - * - * Copyright (C) 2014 Richard Meadows - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * 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, see . - */ - -/* This file implements Atmel SAM D target specific functions for - * detecting the device, providing the XML memory map and Flash memory - * programming. - * - * Tested with - * * SAMD20E17A (rev C) - * * SAMD20J18A (rev B) - * * SAMD21J18A (rev B) - * * - */ -/* Refer to the SAM D20 Datasheet: - * http://www.atmel.com/Images/Atmel-42129-SAM-D20_Datasheet.pdf - * particularly Sections 12. DSU and 20. NVMCTRL - */ - -#include -#include -#include - -#include "general.h" -#include "jtagtap.h" -#include "adiv5.h" -#include "target.h" -#include "command.h" -#include "gdb_packet.h" -#include "cortexm.h" - -static int samd_flash_erase(struct target_s *target, uint32_t addr, int len); -static int samd_flash_write(struct target_s *target, uint32_t dest, - const uint8_t *src, int len); - -static bool samd_cmd_erase_all(target *t); -static bool samd_cmd_lock_flash(target *t); -static bool samd_cmd_unlock_flash(target *t); -static bool samd_cmd_read_userrow(target *t); -static bool samd_cmd_serial(target *t); -static bool samd_cmd_mbist(target *t); -static bool samd_cmd_ssb(target *t); - -const struct command_s samd_cmd_list[] = { - {"erase_mass", (cmd_handler)samd_cmd_erase_all, "Erase entire flash memory"}, - {"lock_flash", (cmd_handler)samd_cmd_lock_flash, "Locks flash against spurious commands"}, - {"unlock_flash", (cmd_handler)samd_cmd_unlock_flash, "Unlocks flash"}, - {"user_row", (cmd_handler)samd_cmd_read_userrow, "Prints user row from flash"}, - {"serial", (cmd_handler)samd_cmd_serial, "Prints serial number"}, - {"mbist", (cmd_handler)samd_cmd_mbist, "Runs the built-in memory test"}, - {"set_security_bit", (cmd_handler)samd_cmd_ssb, "Sets the Security Bit"}, - {NULL, NULL, NULL} -}; - -/** - * 256KB Flash Max., 32KB RAM Max. The smallest unit of erase is the - * one row = 256 bytes. - */ -static const char samd_xml_memory_map[] = "" -/* ""*/ - "" - " " - " 0x100" - " " - " " - ""; - -/* Non-Volatile Memory Controller (NVMC) Parameters */ -#define SAMD_ROW_SIZE 256 -#define SAMD_PAGE_SIZE 64 - -/* -------------------------------------------------------------------------- */ -/* Non-Volatile Memory Controller (NVMC) Registers */ -/* -------------------------------------------------------------------------- */ - -#define SAMD_NVMC 0x41004000 -#define SAMD_NVMC_CTRLA (SAMD_NVMC + 0x0) -#define SAMD_NVMC_CTRLB (SAMD_NVMC + 0x04) -#define SAMD_NVMC_PARAM (SAMD_NVMC + 0x08) -#define SAMD_NVMC_INTFLAG (SAMD_NVMC + 0x14) -#define SAMD_NVMC_STATUS (SAMD_NVMC + 0x18) -#define SAMD_NVMC_ADDRESS (SAMD_NVMC + 0x1C) - -/* Control A Register (CTRLA) */ -#define SAMD_CTRLA_CMD_KEY 0xA500 -#define SAMD_CTRLA_CMD_ERASEROW 0x0002 -#define SAMD_CTRLA_CMD_WRITEPAGE 0x0004 -#define SAMD_CTRLA_CMD_ERASEAUXROW 0x0005 -#define SAMD_CTRLA_CMD_WRITEAUXPAGE 0x0006 -#define SAMD_CTRLA_CMD_LOCK 0x0040 -#define SAMD_CTRLA_CMD_UNLOCK 0x0041 -#define SAMD_CTRLA_CMD_PAGEBUFFERCLEAR 0x0044 -#define SAMD_CTRLA_CMD_SSB 0x0045 -#define SAMD_CTRLA_CMD_INVALL 0x0046 - -/* Interrupt Flag Register (INTFLAG) */ -#define SAMD_NVMC_READY (1 << 0) - -/* Non-Volatile Memory Calibration and Auxiliary Registers */ -#define SAMD_NVM_USER_ROW_LOW 0x00804000 -#define SAMD_NVM_USER_ROW_HIGH 0x00804004 -#define SAMD_NVM_CALIBRATION 0x00806020 -#define SAMD_NVM_SERIAL(n) (0x0080A00C + (0x30 * ((n + 3) / 4)) + \ - (0x4 * n)) - -/* -------------------------------------------------------------------------- */ -/* Device Service Unit (DSU) Registers */ -/* -------------------------------------------------------------------------- */ - -#define SAMD_DSU 0x41002000 -#define SAMD_DSU_EXT_ACCESS (SAMD_DSU + 0x100) -#define SAMD_DSU_CTRLSTAT (SAMD_DSU_EXT_ACCESS + 0x0) -#define SAMD_DSU_ADDRESS (SAMD_DSU_EXT_ACCESS + 0x4) -#define SAMD_DSU_LENGTH (SAMD_DSU_EXT_ACCESS + 0x8) -#define SAMD_DSU_DID (SAMD_DSU_EXT_ACCESS + 0x018) -#define SAMD_DSU_PID(n) (SAMD_DSU + 0x1FE0 + \ - (0x4 * (n % 4)) - (0x10 * (n / 4))) -#define SAMD_DSU_CID(n) (SAMD_DSU + 0x1FF0 + \ - (0x4 * (n % 4))) - -/* Control and Status Register (CTRLSTAT) */ -#define SAMD_CTRL_CHIP_ERASE (1 << 4) -#define SAMD_CTRL_MBIST (1 << 3) -#define SAMD_CTRL_CRC (1 << 2) -#define SAMD_STATUSA_PERR (1 << 12) -#define SAMD_STATUSA_FAIL (1 << 11) -#define SAMD_STATUSA_BERR (1 << 10) -#define SAMD_STATUSA_CRSTEXT (1 << 9) -#define SAMD_STATUSA_DONE (1 << 8) -#define SAMD_STATUSB_PROT (1 << 16) - -/* Device Identification Register (DID) */ -#define SAMD_DID_MASK 0xFFBC0000 -#define SAMD_DID_CONST_VALUE 0x10000000 -#define SAMD_DID_DEVSEL_MASK 0x0F -#define SAMD_DID_DEVSEL_POS 0 -#define SAMD_DID_REVISION_MASK 0x0F -#define SAMD_DID_REVISION_POS 8 -#define SAMD_DID_SERIES_MASK 0x03 -#define SAMD_DID_SERIES_POS 16 - -/* Peripheral ID */ -#define SAMD_PID_MASK 0x00F7FFFF -#define SAMD_PID_CONST_VALUE 0x0001FCD0 - -/* Component ID */ -#define SAMD_CID_VALUE 0xB105100D - -/* Utility */ -#define MINIMUM(a,b) ((a < b) ? a : b) - -/** - * Reads the SAM D20 Peripheral ID - */ -uint64_t samd_read_pid(struct target_s *target) -{ - ADIv5_AP_t *ap = adiv5_target_ap(target); - uint64_t pid = 0; - uint8_t i, j; - - /* Five PID registers to read LSB first */ - for (i = 0, j = 0; i < 5; i++, j += 8) - pid |= (adiv5_ap_mem_read(ap, SAMD_DSU_PID(i)) & 0xFF) << j; - - return pid; -} -/** - * Reads the SAM D20 Component ID - */ -uint32_t samd_read_cid(struct target_s *target) -{ - ADIv5_AP_t *ap = adiv5_target_ap(target); - uint64_t cid = 0; - uint8_t i, j; - - /* Four CID registers to read LSB first */ - for (i = 0, j = 0; i < 4; i++, j += 8) - cid |= (adiv5_ap_mem_read(ap, SAMD_DSU_CID(i)) & 0xFF) << j; - - return cid; -} - -/** - * Overloads the default cortexm reset function with a version that - * removes the target from extended reset where required. - */ -static void -samd_reset(struct target_s *target) -{ - ADIv5_AP_t *ap = adiv5_target_ap(target); - - /** - * SRST is not asserted here as it appears to reset the adiv5 - * logic, meaning that subsequent adiv5_* calls PLATFORM_FATAL_ERROR. - * - * This is ok as normally you can just connect the debugger and go, - * but if that's not possible (protection or SWCLK being used for - * something else) then having SWCLK low on reset should get you - * debug access (cold-plugging). TODO: Confirm this - * - * See the SAM D20 datasheet §12.6 Debug Operation for more - * details. - * - * jtagtap_srst(true); - * jtagtap_srst(false); - */ - - /* Read DHCSR here to clear S_RESET_ST bit before reset */ - adiv5_ap_mem_read(ap, CORTEXM_DHCSR); - - /* Request system reset from NVIC: SRST doesn't work correctly */ - /* This could be VECTRESET: 0x05FA0001 (reset only core) - * or SYSRESETREQ: 0x05FA0004 (system reset) - */ - adiv5_ap_mem_write(ap, CORTEXM_AIRCR, - CORTEXM_AIRCR_VECTKEY | CORTEXM_AIRCR_SYSRESETREQ); - - /* Exit extended reset */ - if (adiv5_ap_mem_read(ap, SAMD_DSU_CTRLSTAT) & - SAMD_STATUSA_CRSTEXT) { - /* Write bit to clear from extended reset */ - adiv5_ap_mem_write(ap, SAMD_DSU_CTRLSTAT, - SAMD_STATUSA_CRSTEXT); - } - - /* Poll for release from reset */ - while(adiv5_ap_mem_read(ap, CORTEXM_DHCSR) & CORTEXM_DHCSR_S_RESET_ST); - - /* Reset DFSR flags */ - adiv5_ap_mem_write(ap, CORTEXM_DFSR, CORTEXM_DFSR_RESETALL); - - /* Clear any target errors */ - target_check_error(target); -} - -/** - * Overloads the default cortexm detached function with a version that - * removes the target from extended reset where required. - * - * Only required for SAM D20 _Revision B_ Silicon - */ -static void -samd20_revB_detach(struct target_s *target) -{ - ADIv5_AP_t *ap = adiv5_target_ap(target); - cortexm_detach(target); - - /* ---- Additional ---- */ - /* Exit extended reset */ - if (adiv5_ap_mem_read(ap, SAMD_DSU_CTRLSTAT) & - SAMD_STATUSA_CRSTEXT) { - /* Write bit to clear from extended reset */ - adiv5_ap_mem_write(ap, SAMD_DSU_CTRLSTAT, - SAMD_STATUSA_CRSTEXT); - } -} - -/** - * Overloads the default cortexm halt_resume function with a version - * that removes the target from extended reset where required. - * - * Only required for SAM D20 _Revision B_ Silicon - */ -static void -samd20_revB_halt_resume(struct target_s *target, bool step) -{ - ADIv5_AP_t *ap = adiv5_target_ap(target); - cortexm_halt_resume(target, step); - - /* ---- Additional ---- */ - /* Exit extended reset */ - if (adiv5_ap_mem_read(ap, SAMD_DSU_CTRLSTAT) & - SAMD_STATUSA_CRSTEXT) { - /* Write bit to clear from extended reset */ - adiv5_ap_mem_write(ap, SAMD_DSU_CTRLSTAT, - SAMD_STATUSA_CRSTEXT); - } -} - -/** - * Overload the default cortexm attach for when the samd is protected. - * - * If the samd is protected then the default cortexm attach will - * fail as the S_HALT bit in the DHCSR will never go high. This - * function allows users to attach on a temporary basis so they can - * rescue the device. - */ -static bool -samd_protected_attach(struct target_s *target) -{ - /** - * TODO: Notify the user that we're not really attached and - * they should issue the 'monitor erase_mass' command to - * regain access to the chip. - */ - - /* Patch back in the normal cortexm attach for next time */ - target->attach = cortexm_attach; - - /* Allow attach this time */ - return true; -} - -/** - * Use the DSU Device Indentification Register to populate a struct - * describing the SAM D device. - */ -struct samd_descr { - uint8_t series; - char revision; - char pin; - uint8_t mem; - char package[3]; -}; -struct samd_descr samd_parse_device_id(uint32_t did) -{ - struct samd_descr samd; - memset(samd.package, 0, 3); - - uint8_t series = (did >> SAMD_DID_SERIES_POS) - & SAMD_DID_SERIES_MASK; - uint8_t revision = (did >> SAMD_DID_REVISION_POS) - & SAMD_DID_REVISION_MASK; - uint8_t devsel = (did >> SAMD_DID_DEVSEL_POS) - & SAMD_DID_DEVSEL_MASK; - - /* Series */ - switch (series) { - case 0: samd.series = 20; break; - case 1: samd.series = 21; break; - case 2: samd.series = 10; break; - case 3: samd.series = 11; break; - } - /* Revision */ - samd.revision = 'A' + revision; - - switch (samd.series) { - case 20: /* SAM D20 */ - case 21: /* SAM D21 */ - switch (devsel / 5) { - case 0: samd.pin = 'J'; break; - case 1: samd.pin = 'G'; break; - case 2: samd.pin = 'E'; break; - default: samd.pin = 'u'; break; - } - samd.mem = 18 - (devsel % 5); - break; - case 10: /* SAM D10 */ - case 11: /* SAM D11 */ - switch (devsel / 3) { - case 0: samd.package[0] = 'M'; break; - case 1: samd.package[0] = 'S'; samd.package[1] = 'S'; break; - } - samd.pin = 'D'; - samd.mem = 14 - (devsel % 3); - break; - } - - return samd; -} - - -char variant_string[40]; -bool samd_probe(struct target_s *target) -{ - ADIv5_AP_t *ap = adiv5_target_ap(target); - uint32_t cid = samd_read_cid(target); - uint32_t pid = samd_read_pid(target); - - /* Check the ARM Coresight Component and Perhiperal IDs */ - if (cid == SAMD_CID_VALUE && - (pid & SAMD_PID_MASK) == SAMD_PID_CONST_VALUE) { - - /* Read the Device ID */ - uint32_t did = adiv5_ap_mem_read(ap, SAMD_DSU_DID); - - /* If the Device ID matches */ - if ((did & SAMD_DID_MASK) == SAMD_DID_CONST_VALUE) { - - uint32_t ctrlstat = adiv5_ap_mem_read(ap, SAMD_DSU_CTRLSTAT); - struct samd_descr samd = samd_parse_device_id(did); - - /* Protected? */ - int protected = (ctrlstat & SAMD_STATUSB_PROT); - - /* Part String */ - if (protected) { - sprintf(variant_string, - "Atmel SAMD%d%c%dA%s (rev %c) (PROT=1)", - samd.series, samd.pin, samd.mem, - samd.package, samd.revision); - } else { - sprintf(variant_string, - "Atmel SAMD%d%c%dA%s (rev %c)", - samd.series, samd.pin, samd.mem, - samd.package, samd.revision); - } - - /* Setup Target */ - target->driver = variant_string; - target->reset = samd_reset; - - if (samd.series == 20 && samd.revision == 'B') { - /** - * These functions check for and - * extended reset. Appears to be - * related to Errata 35.4.1 ref 12015 - */ - target->detach = samd20_revB_detach; - target->halt_resume = samd20_revB_halt_resume; - } - if (protected) { - /** - * Overload the default cortexm attach - * for when the samd is protected. - * This function allows users to - * attach on a temporary basis so they - * can rescue the device. - */ - target->attach = samd_protected_attach; - } - - target->xml_mem_map = samd_xml_memory_map; - target->flash_erase = samd_flash_erase; - target->flash_write = samd_flash_write; - target_add_commands(target, samd_cmd_list, "SAMD"); - - /* If we're not in reset here */ - if (!connect_assert_srst) { - /* We'll have to release the target from - * extended reset to make attach possible */ - if (adiv5_ap_mem_read(ap, SAMD_DSU_CTRLSTAT) & - SAMD_STATUSA_CRSTEXT) { - - /* Write bit to clear from extended reset */ - adiv5_ap_mem_write(ap, SAMD_DSU_CTRLSTAT, - SAMD_STATUSA_CRSTEXT); - } - } - - return true; - } - } - - return false; -} - -/** - * Temporary (until next reset) flash memory locking / unlocking - */ -static void samd_lock_current_address(struct target_s *target) -{ - ADIv5_AP_t *ap = adiv5_target_ap(target); - - /* Issue the unlock command */ - adiv5_ap_mem_write(ap, SAMD_NVMC_CTRLA, SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_LOCK); -} -static void samd_unlock_current_address(struct target_s *target) -{ - ADIv5_AP_t *ap = adiv5_target_ap(target); - - /* Issue the unlock command */ - adiv5_ap_mem_write(ap, SAMD_NVMC_CTRLA, SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_UNLOCK); -} - -/** - * Erase flash row by row - */ -static int samd_flash_erase(struct target_s *target, uint32_t addr, int len) -{ - ADIv5_AP_t *ap = adiv5_target_ap(target); - - addr &= ~(SAMD_ROW_SIZE - 1); - len &= ~(SAMD_ROW_SIZE - 1); - - while (len) { - /* Write address of first word in row to erase it */ - /* Must be shifted right for 16-bit address, see Datasheet §20.8.8 Address */ - adiv5_ap_mem_write(ap, SAMD_NVMC_ADDRESS, addr >> 1); - - /* Unlock */ - samd_unlock_current_address(target); - - /* Issue the erase command */ - adiv5_ap_mem_write(ap, SAMD_NVMC_CTRLA, SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_ERASEROW); - /* Poll for NVM Ready */ - while ((adiv5_ap_mem_read(ap, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0) - if(target_check_error(target)) - return -1; - - /* Lock */ - samd_lock_current_address(target); - - addr += SAMD_ROW_SIZE; - len -= SAMD_ROW_SIZE; - } - - return 0; -} - -/** - * Write flash page by page - */ -static int samd_flash_write(struct target_s *target, uint32_t dest, - const uint8_t *src, int len) -{ - ADIv5_AP_t *ap = adiv5_target_ap(target); - - /* Find the size of our 32-bit data buffer */ - uint32_t offset = dest % 4; - uint32_t words = (offset + len + 3) / 4; - uint32_t data[words], i = 0; - - /* Populate the data buffer */ - memset((uint8_t *)data, 0xFF, words * 4); - memcpy((uint8_t *)data + offset, src, len); - - /* The address of the first word involved in the write */ - uint32_t addr = dest & ~0x3; - /* The address of the last word involved in the write */ - uint32_t end = (dest + len - 1) & ~0x3; - - /* The start address of the first page involved in the write */ - uint32_t first_page = dest & ~(SAMD_PAGE_SIZE - 1); - /* The start address of the last page involved in the write */ - uint32_t last_page = (dest + len - 1) & ~(SAMD_PAGE_SIZE - 1); - uint32_t end_of_this_page; - - - for (uint32_t page = first_page; page <= last_page; page += SAMD_PAGE_SIZE) { - end_of_this_page = page + (SAMD_PAGE_SIZE - 4); - - if (addr > page || (page == last_page && end < end_of_this_page)) { - /* Setup write */ - adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw | - ADIV5_AP_CSW_SIZE_WORD | ADIV5_AP_CSW_ADDRINC_SINGLE); - adiv5_ap_write(ap, ADIV5_AP_TAR, addr); - adiv5_dp_write(ap->dp, ADIV5_DP_SELECT, - ((uint32_t)ap->apsel << 24)|(ADIV5_AP_DRW & 0xF0)); - - /* Partial, manual page write */ - for (; addr <= MINIMUM(end, end_of_this_page); addr += 4, i++) { - adiv5_dp_write_ap(ap->dp, ADIV5_AP_DRW, data[i]); - } - - /* Unlock */ - samd_unlock_current_address(target); - - /* Issue the write page command */ - adiv5_ap_mem_write(ap, SAMD_NVMC_CTRLA, - SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_WRITEPAGE); - } else { - /* Write first word to set address */ - adiv5_ap_mem_write(ap, addr, data[i]); addr += 4; i++; - - /* Unlock */ - samd_unlock_current_address(target); - - /* Set up write */ - adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw | - ADIV5_AP_CSW_SIZE_WORD | ADIV5_AP_CSW_ADDRINC_SINGLE); - adiv5_ap_write(ap, ADIV5_AP_TAR, addr); - adiv5_dp_write(ap->dp, ADIV5_DP_SELECT, - ((uint32_t)ap->apsel << 24)|(ADIV5_AP_DRW & 0xF0)); - - /* Full, automatic page write */ - for (; addr < page + SAMD_PAGE_SIZE; addr += 4, i++) { - adiv5_dp_write_ap(ap->dp, ADIV5_AP_DRW, data[i]); - } - } - - /* Poll for NVM Ready */ - while ((adiv5_ap_mem_read(ap, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0) - if(target_check_error(target)) - return -1; - - /* Lock */ - samd_lock_current_address(target); - } - - return 0; -} - -/** - * Uses the Device Service Unit to erase the entire flash - */ -static bool samd_cmd_erase_all(target *t) -{ - ADIv5_AP_t *ap = adiv5_target_ap(t); - - /* Clear the DSU status bits */ - adiv5_ap_mem_write(ap, SAMD_DSU_CTRLSTAT, - (SAMD_STATUSA_DONE | SAMD_STATUSA_PERR | SAMD_STATUSA_FAIL)); - - /* Erase all */ - adiv5_ap_mem_write(ap, SAMD_DSU_CTRLSTAT, SAMD_CTRL_CHIP_ERASE); - - /* Poll for DSU Ready */ - uint32_t status; - while (((status = adiv5_ap_mem_read(ap, SAMD_DSU_CTRLSTAT)) & - (SAMD_STATUSA_DONE | SAMD_STATUSA_PERR | SAMD_STATUSA_FAIL)) == 0) - if(target_check_error(t)) - return false; - - /* Test the protection error bit in Status A */ - if (status & SAMD_STATUSA_PERR) { - gdb_outf("Erase failed due to a protection error.\n"); - return true; - } - - /* Test the fail bit in Status A */ - if (status & SAMD_STATUSA_FAIL) { - gdb_outf("Erase failed.\n"); - return true; - } - - gdb_outf("Erase successful!\n"); - - return true; -} - -/** - * Sets the NVM region lock bits in the User Row. This value is read - * at startup as the default value for the lock bits, and hence does - * not take effect until a reset. - * - * 0x0000 = Lock, 0xFFFF = Unlock (default) - */ -static bool samd_set_flashlock(target *t, uint16_t value) -{ - ADIv5_AP_t *ap = adiv5_target_ap(t); - - uint32_t high = adiv5_ap_mem_read(ap, SAMD_NVM_USER_ROW_HIGH); - uint32_t low = adiv5_ap_mem_read(ap, SAMD_NVM_USER_ROW_LOW); - - /* Write address of a word in the row to erase it */ - /* Must be shifted right for 16-bit address, see Datasheet §20.8.8 Address */ - adiv5_ap_mem_write(ap, SAMD_NVMC_ADDRESS, SAMD_NVM_USER_ROW_LOW >> 1); - - /* Issue the erase command */ - adiv5_ap_mem_write(ap, SAMD_NVMC_CTRLA, SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_ERASEAUXROW); - - /* Poll for NVM Ready */ - while ((adiv5_ap_mem_read(ap, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0) - if(target_check_error(t)) - return -1; - - /* Modify the high byte of the user row */ - high = (high & 0x0000FFFF) | ((value << 16) & 0xFFFF0000); - - /* Write back */ - adiv5_ap_mem_write(ap, SAMD_NVM_USER_ROW_LOW, low); - adiv5_ap_mem_write(ap, SAMD_NVM_USER_ROW_HIGH, high); - - /* Issue the page write command */ - adiv5_ap_mem_write(ap, SAMD_NVMC_CTRLA, - SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_WRITEAUXPAGE); - - return true; -} -static bool samd_cmd_lock_flash(target *t) -{ - return samd_set_flashlock(t, 0x0000); -} -static bool samd_cmd_unlock_flash(target *t) -{ - return samd_set_flashlock(t, 0xFFFF); -} -static bool samd_cmd_read_userrow(target *t) -{ - ADIv5_AP_t *ap = adiv5_target_ap(t); - - gdb_outf("User Row: 0x%08x%08x\n", - adiv5_ap_mem_read(ap, SAMD_NVM_USER_ROW_HIGH), - adiv5_ap_mem_read(ap, SAMD_NVM_USER_ROW_LOW)); - - return true; -} -/** - * Reads the 128-bit serial number from the NVM - */ -static bool samd_cmd_serial(target *t) -{ - ADIv5_AP_t *ap = adiv5_target_ap(t); - - gdb_outf("Serial Number: 0x"); - - for (uint32_t i = 0; i < 4; i++) { - gdb_outf("%08x", adiv5_ap_mem_read(ap, SAMD_NVM_SERIAL(i))); - } - - gdb_outf("\n"); - - return true; -} -/** - * Returns the size (in bytes) of the current SAM D20's flash memory. - */ -static uint32_t samd_flash_size(target *t) -{ - ADIv5_AP_t *ap = adiv5_target_ap(t); - - /* Read the Device ID */ - uint32_t did = adiv5_ap_mem_read(ap, SAMD_DSU_DID); - - /* Mask off the device select bits */ - uint8_t devsel = did & SAMD_DID_DEVSEL_MASK; - - /* Shift the maximum flash size (256KB) down as appropriate */ - return (0x40000 >> (devsel % 5)); -} -/** - * Runs the Memory Built In Self Test (MBIST) - */ -static bool samd_cmd_mbist(target *t) -{ - ADIv5_AP_t *ap = adiv5_target_ap(t); - - /* Write the memory parameters to the DSU */ - adiv5_ap_mem_write(ap, SAMD_DSU_ADDRESS, 0); - adiv5_ap_mem_write(ap, SAMD_DSU_LENGTH, samd_flash_size(t)); - - /* Clear the fail bit */ - adiv5_ap_mem_write(ap, SAMD_DSU_CTRLSTAT, SAMD_STATUSA_FAIL); - - /* Write the MBIST command */ - adiv5_ap_mem_write(ap, SAMD_DSU_CTRLSTAT, SAMD_CTRL_MBIST); - - /* Poll for DSU Ready */ - uint32_t status; - while (((status = adiv5_ap_mem_read(ap, SAMD_DSU_CTRLSTAT)) & - (SAMD_STATUSA_DONE | SAMD_STATUSA_PERR | SAMD_STATUSA_FAIL)) == 0) - if(target_check_error(t)) - return false; - - /* Test the protection error bit in Status A */ - if (status & SAMD_STATUSA_PERR) { - gdb_outf("MBIST not run due to protection error.\n"); - return true; - } - - /* Test the fail bit in Status A */ - if (status & SAMD_STATUSA_FAIL) { - gdb_outf("MBIST Fail @ 0x%08x\n", - adiv5_ap_mem_read(ap, SAMD_DSU_ADDRESS)); - } else { - gdb_outf("MBIST Passed!\n"); - } - - return true; -} -/** - * Sets the security bit - */ -static bool samd_cmd_ssb(target *t) -{ - ADIv5_AP_t *ap = adiv5_target_ap(t); - - /* Issue the ssb command */ - adiv5_ap_mem_write(ap, SAMD_NVMC_CTRLA, SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_SSB); - - /* Poll for NVM Ready */ - while ((adiv5_ap_mem_read(ap, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0) - if(target_check_error(t)) - return -1; - - gdb_outf("Set the security bit! " - "You will need to issue 'monitor erase_mass' to clear this.\n"); - - return true; -} -- cgit v1.2.3 From a7283196d1f91515089c7cd7aee06acffeaee94d Mon Sep 17 00:00:00 2001 From: Martin Knoll Date: Thu, 22 Jan 2015 16:09:01 +0100 Subject: SAM3S support --- src/sam3x.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'src') diff --git a/src/sam3x.c b/src/sam3x.c index 38a3ef7..864d8f8 100644 --- a/src/sam3x.c +++ b/src/sam3x.c @@ -112,6 +112,7 @@ static const char sam4s_xml_memory_map[] = "" #define SAM3X_CHIPID_CIDR 0x400E0940 #define SAM3N_CHIPID_CIDR 0x400E0740 +#define SAM3S_CHIPID_CIDR 0x400E0740 #define SAM4S_CHIPID_CIDR 0x400E0740 #define CHIPID_CIDR_VERSION_MASK (0x1F << 0) @@ -133,6 +134,9 @@ static const char sam4s_xml_memory_map[] = "" #define CHIPID_CIDR_ARCH_SAM3NxA (0x93 << 20) #define CHIPID_CIDR_ARCH_SAM3NxB (0x94 << 20) #define CHIPID_CIDR_ARCH_SAM3NxC (0x95 << 20) +#define CHIPID_CIDR_ARCH_SAM3SxA (0x88 << 20) +#define CHIPID_CIDR_ARCH_SAM3SxB (0x89 << 20) +#define CHIPID_CIDR_ARCH_SAM3SxC (0x8A << 20) #define CHIPID_CIDR_ARCH_SAM4SxA (0x88 << 20) #define CHIPID_CIDR_ARCH_SAM4SxB (0x89 << 20) #define CHIPID_CIDR_ARCH_SAM4SxC (0x8A << 20) @@ -175,6 +179,19 @@ bool sam3x_probe(struct target_s *target) target_add_commands(target, sam3x_cmd_list, "SAM3N"); return true; } + + target->idcode = adiv5_ap_mem_read(ap, SAM3S_CHIPID_CIDR); + switch (target->idcode & (CHIPID_CIDR_ARCH_MASK | CHIPID_CIDR_EPROC_MASK)) { + case CHIPID_CIDR_ARCH_SAM3SxA | CHIPID_CIDR_EPROC_CM3: + case CHIPID_CIDR_ARCH_SAM3SxB | CHIPID_CIDR_EPROC_CM3: + case CHIPID_CIDR_ARCH_SAM3SxC | CHIPID_CIDR_EPROC_CM3: + target->driver = "Atmel SAM3S"; + target->xml_mem_map = sam3n_xml_memory_map; + target->flash_erase = sam3x_flash_erase; + target->flash_write = sam3x_flash_write; + target_add_commands(target, sam3x_cmd_list, "SAM3S"); + return true; + } target->idcode = adiv5_ap_mem_read(ap, SAM4S_CHIPID_CIDR); switch (target->idcode & (CHIPID_CIDR_ARCH_MASK | CHIPID_CIDR_EPROC_MASK)) { -- cgit v1.2.3 From b771d0dcd6424a209b50a66d8ae3a950d070fe27 Mon Sep 17 00:00:00 2001 From: David Lawrence Date: Fri, 23 Jan 2015 16:36:12 -0500 Subject: Add support for SAM4 erase command --- src/sam3x.c | 45 +++++++++++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/sam3x.c b/src/sam3x.c index 38a3ef7..e583a6d 100644 --- a/src/sam3x.c +++ b/src/sam3x.c @@ -96,6 +96,7 @@ static const char sam4s_xml_memory_map[] = "" #define EEFC_FCR_FCMD_EWP 0x03 #define EEFC_FCR_FCMD_EWPL 0x04 #define EEFC_FCR_FCMD_EA 0x05 +#define EEFC_FCR_FCMD_EPA 0x07 #define EEFC_FCR_FCMD_SLB 0x08 #define EEFC_FCR_FCMD_CLB 0x09 #define EEFC_FCR_FCMD_GLB 0x0A @@ -272,32 +273,52 @@ sam3x_flash_base(struct target_s *target, uint32_t addr, uint32_t *offset) static int sam3x_flash_erase(struct target_s *target, uint32_t addr, int len) { - unsigned page_size; - if (strcmp(target->driver, "Atmel SAM4S") == 0) { - page_size = SAM4_PAGE_SIZE; - } else { - page_size = SAM3_PAGE_SIZE; - } uint32_t offset; uint32_t base = sam3x_flash_base(target, addr, &offset); - unsigned chunk = offset / page_size; - uint8_t buf[page_size]; - /* This device doesn't really have a page erase function. + /* The SAM4S is the only supported device with a page erase command. + * Erasing is done in 16-page chunks. arg[15:2] contains the page + * number and arg[1:0] contains 0x2, indicating 16-page chunks. + */ + if (strcmp(target->driver, "Atmel SAM4S") == 0) { + unsigned chunk = offset / SAM4_PAGE_SIZE; + /* Fail if the start address is not 16-page-aligned. */ + if (chunk % 16 != 0) + return -1; + + /* Note that the length might not be a multiple of 16 pages. + * In this case, we will erase a few extra pages at the end. + */ + while (len > 0) { + int16_t arg = (chunk << 2) | 0x2; + if(sam3x_flash_cmd(target, base, EEFC_FCR_FCMD_EPA, arg)) + return -1; + + len -= SAM4_PAGE_SIZE * 16; + addr += SAM4_PAGE_SIZE * 16; + chunk += 16; + } + + return 0; + } + + /* The SAM3X/SAM3N don't really have a page erase function. * This Erase/Write page is the best we have, so we write with all * ones. This does waste time, but what can we do? */ + unsigned chunk = offset / SAM3_PAGE_SIZE; + uint8_t buf[SAM3_PAGE_SIZE]; memset(buf, 0xff, sizeof(buf)); /* Only do this once, since it doesn't change. */ - target_mem_write_words(target, addr, (void*)buf, page_size); + target_mem_write_words(target, addr, (void*)buf, SAM3_PAGE_SIZE); while (len) { if(sam3x_flash_cmd(target, base, EEFC_FCR_FCMD_EWP, chunk)) return -1; - len -= page_size; - addr += page_size; + len -= SAM3_PAGE_SIZE; + addr += SAM3_PAGE_SIZE; chunk++; } -- cgit v1.2.3 From 5d136398e121168c41e1c3488454e02f11afd67b Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sat, 28 Feb 2015 21:23:24 -0800 Subject: Use sensible return convention for platform_target_get_power() --- src/command.c | 2 +- src/platforms/native/platform.c | 9 ++++++--- 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/command.c b/src/command.c index e817197..c13fa9f 100644 --- a/src/command.c +++ b/src/command.c @@ -234,7 +234,7 @@ static bool cmd_target_power(target *t, int argc, const char **argv) (void)t; if (argc == 1) gdb_outf("Target Power: %s\n", - !platform_target_get_power() ? "enabled" : "disabled"); + platform_target_get_power() ? "enabled" : "disabled"); else platform_target_set_power(!strncmp(argv[1], "enable", strlen(argv[1]))); return true; diff --git a/src/platforms/native/platform.c b/src/platforms/native/platform.c index 2789d8c..5e5c78c 100644 --- a/src/platforms/native/platform.c +++ b/src/platforms/native/platform.c @@ -158,12 +158,15 @@ void platform_srst_set_val(bool assert) gpio_set_val(SRST_PORT, SRST_PIN, !assert); } } -bool platform_target_get_power(void) { + +bool platform_target_get_power(void) +{ if (platform_hwversion() > 0) { - return gpio_get(PWR_BR_PORT, PWR_BR_PIN); + return !gpio_get(PWR_BR_PORT, PWR_BR_PIN); } - return 1; /* 1 = Unpowered */ + return 0; } + void platform_target_set_power(bool power) { if (platform_hwversion() > 0) { -- cgit v1.2.3 From 75001a442126e3b42f6f95f1917a7cb33b92d063 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sat, 28 Feb 2015 22:05:10 -0800 Subject: Factor Morse code functions out of platform code. --- src/Makefile | 1 + src/adiv5_jtagdp.c | 1 + src/adiv5_swdp.c | 1 + src/command.c | 1 + src/include/morse.h | 32 ++++++++++ src/jtag_scan.c | 1 + src/morse.c | 100 ++++++++++++++++++++++++++++++++ src/platforms/f4discovery/platform.c | 85 +-------------------------- src/platforms/f4discovery/platform.h | 4 +- src/platforms/launchpad-icdi/platform.c | 8 --- src/platforms/launchpad-icdi/platform.h | 2 - src/platforms/libftdi/platform.c | 8 --- src/platforms/libftdi/platform.h | 3 - src/platforms/native/platform.c | 86 ++------------------------- src/platforms/native/platform.h | 3 +- src/platforms/stlink/platform.c | 8 --- src/platforms/stlink/platform.h | 3 - src/platforms/swlink/platform.c | 8 --- src/platforms/swlink/platform.h | 2 - 19 files changed, 146 insertions(+), 211 deletions(-) create mode 100644 src/include/morse.h create mode 100644 src/morse.c (limited to 'src') diff --git a/src/Makefile b/src/Makefile index fcf5d1f..25cf715 100644 --- a/src/Makefile +++ b/src/Makefile @@ -29,6 +29,7 @@ SRC = \ lpc43xx.c \ kinetis.c \ main.c \ + morse.c \ nrf51.c \ platform.c \ sam3x.c \ diff --git a/src/adiv5_jtagdp.c b/src/adiv5_jtagdp.c index 4306101..fd77a04 100644 --- a/src/adiv5_jtagdp.c +++ b/src/adiv5_jtagdp.c @@ -27,6 +27,7 @@ #include "adiv5.h" #include "jtag_scan.h" #include "jtagtap.h" +#include "morse.h" #include diff --git a/src/adiv5_swdp.c b/src/adiv5_swdp.c index 7896d8b..6bafc91 100644 --- a/src/adiv5_swdp.c +++ b/src/adiv5_swdp.c @@ -30,6 +30,7 @@ #include "jtagtap.h" #include "command.h" +#include "morse.h" #include diff --git a/src/command.c b/src/command.c index c13fa9f..7c17864 100644 --- a/src/command.c +++ b/src/command.c @@ -32,6 +32,7 @@ #include "jtag_scan.h" #include "target.h" +#include "morse.h" #include "adiv5.h" diff --git a/src/include/morse.h b/src/include/morse.h new file mode 100644 index 0000000..ac53893 --- /dev/null +++ b/src/include/morse.h @@ -0,0 +1,32 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2015 Black Sphere Technologies Ltd. + * Written by Gareth McMullin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * 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, see . + */ + +#ifndef __MORSE_H +#define __MORSE_H + +#include + +extern const char *morse_msg; + +void morse(const char *msg, char repeat); +bool morse_update(void); + +#endif + diff --git a/src/jtag_scan.c b/src/jtag_scan.c index 6ca4603..257e6c4 100644 --- a/src/jtag_scan.c +++ b/src/jtag_scan.c @@ -30,6 +30,7 @@ #include "general.h" #include "jtagtap.h" +#include "morse.h" #include "jtag_scan.h" #include "gdb_packet.h" diff --git a/src/morse.c b/src/morse.c new file mode 100644 index 0000000..6b17c16 --- /dev/null +++ b/src/morse.c @@ -0,0 +1,100 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2015 Black Sphere Technologies Ltd. + * Written by Gareth McMullin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * 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, see . + */ +#include "general.h" +#include "morse.h" + +/* Morse code patterns and lengths */ +static const struct { + uint16_t code; + uint8_t bits; +} morse_letter[] = { + { 0b00011101, 8}, // 'A' .- + { 0b000101010111, 12}, // 'B' -... + { 0b00010111010111, 14}, // 'C' -.-. + { 0b0001010111, 10}, // 'D' -.. + { 0b0001, 4}, // 'E' . + { 0b000101110101, 12}, // 'F' ..-. + { 0b000101110111, 12}, // 'G' --. + { 0b0001010101, 10}, // 'H' .... + { 0b000101, 6}, // 'I' .. + {0b0001110111011101, 16}, // 'J' .--- + { 0b000111010111, 12}, // 'K' -.- + { 0b000101011101, 12}, // 'L' .-.. + { 0b0001110111, 10}, // 'M' -- + { 0b00010111, 8}, // 'N' -. + { 0b00011101110111, 14}, // 'O' --- + { 0b00010111011101, 14}, // 'P' .--. + {0b0001110101110111, 16}, // 'Q' --.- + { 0b0001011101, 10}, // 'R' .-. + { 0b00010101, 8}, // 'S' ... + { 0b000111, 6}, // 'T' - + { 0b0001110101, 10}, // 'U' ..- + { 0b000111010101, 12}, // 'V' ...- + { 0b000111011101, 12}, // 'W' .-- + { 0b00011101010111, 14}, // 'X' -..- + {0b0001110111010111, 16}, // 'Y' -.-- + { 0b00010101110111, 14}, // 'Z' --.. +}; + +const char *morse_msg; +static const char * volatile morse_ptr; +static char morse_repeat; + +void morse(const char *msg, char repeat) +{ + morse_msg = morse_ptr = msg; + morse_repeat = repeat; +} + +bool morse_update(void) +{ + static uint16_t code; + static uint8_t bits; + + if (!morse_ptr) + return false; + + if (!bits) { + char c = *morse_ptr++; + if (!c) { + if(morse_repeat) { + morse_ptr = morse_msg; + c = *morse_ptr++; + } else { + morse_ptr = 0; + return false; + } + } + if ((c >= 'A') && (c <= 'Z')) { + c -= 'A'; + code = morse_letter[c].code; + bits = morse_letter[c].bits; + } else { + code = 0; bits = 4; + } + } + + bool ret = code & 1; + code >>= 1; + bits--; + + return ret; +} + diff --git a/src/platforms/f4discovery/platform.c b/src/platforms/f4discovery/platform.c index efe8050..e051564 100644 --- a/src/platforms/f4discovery/platform.c +++ b/src/platforms/f4discovery/platform.c @@ -33,17 +33,14 @@ #include #include "jtag_scan.h" -#include - -#include +#include "usbuart.h" +#include "morse.h" uint8_t running_status; volatile uint32_t timeout_counter; jmp_buf fatal_error_jmpbuf; -static void morse_update(void); - int platform_init(void) { /* Check the USER button*/ @@ -116,83 +113,7 @@ void sys_tick_handler(void) if(timeout_counter) timeout_counter--; - morse_update(); -} - - -/* Morse code patterns and lengths */ -static const struct { - uint16_t code; - uint8_t bits; -} morse_letter[] = { - { 0b00011101, 8}, // 'A' .- - { 0b000101010111, 12}, // 'B' -... - { 0b00010111010111, 14}, // 'C' -.-. - { 0b0001010111, 10}, // 'D' -.. - { 0b0001, 4}, // 'E' . - { 0b000101110101, 12}, // 'F' ..-. - { 0b000101110111, 12}, // 'G' --. - { 0b0001010101, 10}, // 'H' .... - { 0b000101, 6}, // 'I' .. - {0b0001110111011101, 16}, // 'J' .--- - { 0b000111010111, 12}, // 'K' -.- - { 0b000101011101, 12}, // 'L' .-.. - { 0b0001110111, 10}, // 'M' -- - { 0b00010111, 8}, // 'N' -. - { 0b00011101110111, 14}, // 'O' --- - { 0b00010111011101, 14}, // 'P' .--. - {0b0001110101110111, 16}, // 'Q' --.- - { 0b0001011101, 10}, // 'R' .-. - { 0b00010101, 8}, // 'S' ... - { 0b000111, 6}, // 'T' - - { 0b0001110101, 10}, // 'U' ..- - { 0b000111010101, 12}, // 'V' ...- - { 0b000111011101, 12}, // 'W' .-- - { 0b00011101010111, 14}, // 'X' -..- - {0b0001110111010111, 16}, // 'Y' -.-- - { 0b00010101110111, 14}, // 'Z' --.. -}; - - -const char *morse_msg; -static const char * volatile morse_ptr; -static char morse_repeat; - -void morse(const char *msg, char repeat) -{ - morse_msg = morse_ptr = msg; - morse_repeat = repeat; - SET_ERROR_STATE(0); -} - -static void morse_update(void) -{ - static uint16_t code; - static uint8_t bits; - - if(!morse_ptr) return; - - if(!bits) { - char c = *morse_ptr++; - if(!c) { - if(morse_repeat) { - morse_ptr = morse_msg; - c = *morse_ptr++; - } else { - morse_ptr = 0; - return; - } - } - if((c >= 'A') && (c <= 'Z')) { - c -= 'A'; - code = morse_letter[c].code; - bits = morse_letter[c].bits; - } else { - code = 0; bits = 4; - } - } - SET_ERROR_STATE(code & 1); - code >>= 1; bits--; + SET_ERROR_STATE(morse_update()); } const char *platform_target_voltage(void) diff --git a/src/platforms/f4discovery/platform.h b/src/platforms/f4discovery/platform.h index 7d6e92e..90b2a11 100644 --- a/src/platforms/f4discovery/platform.h +++ b/src/platforms/f4discovery/platform.h @@ -34,6 +34,7 @@ #include #include "gdb_packet.h" +#include "morse.h" #define INLINE_GPIO #define CDCACM_PACKET_SIZE 64 @@ -156,8 +157,6 @@ extern volatile uint32_t timeout_counter; extern jmp_buf fatal_error_jmpbuf; -extern const char *morse_msg; - #define gpio_set_val(port, pin, val) do { \ if(val) \ gpio_set((port), (pin)); \ @@ -180,7 +179,6 @@ extern const char *morse_msg; } int platform_init(void); -void morse(const char *msg, char repeat); const char *platform_target_voltage(void); void platform_delay(uint32_t delay); static inline int platform_hwversion(void) diff --git a/src/platforms/launchpad-icdi/platform.c b/src/platforms/launchpad-icdi/platform.c index 848271e..1e66e12 100644 --- a/src/platforms/launchpad-icdi/platform.c +++ b/src/platforms/launchpad-icdi/platform.c @@ -19,14 +19,6 @@ jmp_buf fatal_error_jmpbuf; uint8_t running_status; volatile uint32_t timeout_counter; -const char *morse_msg; - -void morse(const char *msg, char repeat) -{ - (void) msg; - (void) repeat; -} - void sys_tick_handler(void) { if(timeout_counter) diff --git a/src/platforms/launchpad-icdi/platform.h b/src/platforms/launchpad-icdi/platform.h index 7f5d55f..8c343a8 100644 --- a/src/platforms/launchpad-icdi/platform.h +++ b/src/platforms/launchpad-icdi/platform.h @@ -23,7 +23,6 @@ extern usbd_device *usbdev; extern jmp_buf fatal_error_jmpbuf; extern uint8_t running_status; -extern const char *morse_msg; extern volatile uint32_t timeout_counter; #define TMS_PORT GPIOA_BASE @@ -112,7 +111,6 @@ extern usbd_driver lm4f_usb_driver; #define PLATFORM_HAS_TRACESWO int platform_init(void); -void morse(const char *msg, char repeat); inline static void gpio_set_val(uint32_t port, uint8_t pin, uint8_t val) { gpio_write(port, pin, val == 0 ? 0 : 0xff); diff --git a/src/platforms/libftdi/platform.c b/src/platforms/libftdi/platform.c index dc57a45..723efa3 100644 --- a/src/platforms/libftdi/platform.c +++ b/src/platforms/libftdi/platform.c @@ -267,11 +267,3 @@ void platform_delay(uint32_t delay) usleep(delay * 100000); } -void morse(const char *msg, char repeat) -{ - (void)repeat; - - if (msg != NULL) - fprintf(stderr,"%s\n", msg); -} - diff --git a/src/platforms/libftdi/platform.h b/src/platforms/libftdi/platform.h index 5ce45fd..a95a3f4 100644 --- a/src/platforms/libftdi/platform.h +++ b/src/platforms/libftdi/platform.h @@ -40,12 +40,9 @@ #define PLATFORM_FATAL_ERROR(error) abort() #define PLATFORM_SET_FATAL_ERROR_RECOVERY() -#define morse_msg 0 - extern struct ftdi_context *ftdic; int platform_init(int argc, char **argv); -void morse(const char *msg, char repeat); const char *platform_target_voltage(void); void platform_delay(uint32_t delay); diff --git a/src/platforms/native/platform.c b/src/platforms/native/platform.c index 5e5c78c..3e269d9 100644 --- a/src/platforms/native/platform.c +++ b/src/platforms/native/platform.c @@ -34,17 +34,14 @@ #include #include "jtag_scan.h" -#include - -#include +#include "usbuart.h" +#include "morse.h" uint8_t running_status; volatile uint32_t timeout_counter; jmp_buf fatal_error_jmpbuf; -static void morse_update(void); - static void adc_init(void); /* Pins PB[7:5] are used to detect hardware revision. @@ -187,83 +184,7 @@ void sys_tick_handler(void) if(timeout_counter) timeout_counter--; - morse_update(); -} - - -/* Morse code patterns and lengths */ -static const struct { - uint16_t code; - uint8_t bits; -} morse_letter[] = { - { 0b00011101, 8}, // 'A' .- - { 0b000101010111, 12}, // 'B' -... - { 0b00010111010111, 14}, // 'C' -.-. - { 0b0001010111, 10}, // 'D' -.. - { 0b0001, 4}, // 'E' . - { 0b000101110101, 12}, // 'F' ..-. - { 0b000101110111, 12}, // 'G' --. - { 0b0001010101, 10}, // 'H' .... - { 0b000101, 6}, // 'I' .. - {0b0001110111011101, 16}, // 'J' .--- - { 0b000111010111, 12}, // 'K' -.- - { 0b000101011101, 12}, // 'L' .-.. - { 0b0001110111, 10}, // 'M' -- - { 0b00010111, 8}, // 'N' -. - { 0b00011101110111, 14}, // 'O' --- - { 0b00010111011101, 14}, // 'P' .--. - {0b0001110101110111, 16}, // 'Q' --.- - { 0b0001011101, 10}, // 'R' .-. - { 0b00010101, 8}, // 'S' ... - { 0b000111, 6}, // 'T' - - { 0b0001110101, 10}, // 'U' ..- - { 0b000111010101, 12}, // 'V' ...- - { 0b000111011101, 12}, // 'W' .-- - { 0b00011101010111, 14}, // 'X' -..- - {0b0001110111010111, 16}, // 'Y' -.-- - { 0b00010101110111, 14}, // 'Z' --.. -}; - - -const char *morse_msg; -static const char * volatile morse_ptr; -static char morse_repeat; - -void morse(const char *msg, char repeat) -{ - morse_msg = morse_ptr = msg; - morse_repeat = repeat; - SET_ERROR_STATE(0); -} - -static void morse_update(void) -{ - static uint16_t code; - static uint8_t bits; - - if(!morse_ptr) return; - - if(!bits) { - char c = *morse_ptr++; - if(!c) { - if(morse_repeat) { - morse_ptr = morse_msg; - c = *morse_ptr++; - } else { - morse_ptr = 0; - return; - } - } - if((c >= 'A') && (c <= 'Z')) { - c -= 'A'; - code = morse_letter[c].code; - bits = morse_letter[c].bits; - } else { - code = 0; bits = 4; - } - } - SET_ERROR_STATE(code & 1); - code >>= 1; bits--; + SET_ERROR_STATE(morse_update()); } static void adc_init(void) @@ -351,3 +272,4 @@ void setup_vbus_irq(void) exti15_10_isr(); } + diff --git a/src/platforms/native/platform.h b/src/platforms/native/platform.h index 81a2a4b..73b6c59 100644 --- a/src/platforms/native/platform.h +++ b/src/platforms/native/platform.h @@ -35,6 +35,7 @@ #include #include "gdb_packet.h" +#include "morse.h" #define INLINE_GPIO #define CDCACM_PACKET_SIZE 64 @@ -163,7 +164,6 @@ extern volatile uint32_t timeout_counter; extern jmp_buf fatal_error_jmpbuf; -extern const char *morse_msg; #define gpio_set_val(port, pin, val) do { \ if(val) \ @@ -187,7 +187,6 @@ extern const char *morse_msg; } while (0) int platform_init(void); -void morse(const char *msg, char repeat); const char *platform_target_voltage(void); int platform_hwversion(void); void platform_delay(uint32_t delay); diff --git a/src/platforms/stlink/platform.c b/src/platforms/stlink/platform.c index 494499c..6ef8c77 100644 --- a/src/platforms/stlink/platform.c +++ b/src/platforms/stlink/platform.c @@ -156,14 +156,6 @@ void sys_tick_handler(void) timeout_counter--; } -const char *morse_msg; - -void morse(const char *msg, char repeat) -{ - (void)repeat; - morse_msg = msg; -} - const char *platform_target_voltage(void) { return "unknown"; diff --git a/src/platforms/stlink/platform.h b/src/platforms/stlink/platform.h index e56abd9..ee08875 100644 --- a/src/platforms/stlink/platform.h +++ b/src/platforms/stlink/platform.h @@ -143,8 +143,6 @@ extern volatile uint32_t timeout_counter; extern jmp_buf fatal_error_jmpbuf; -extern const char *morse_msg; - #define gpio_set_val(port, pin, val) do { \ if(val) \ gpio_set((port), (pin)); \ @@ -166,7 +164,6 @@ extern uint16_t led_idle_run; } while (0) int platform_init(void); -void morse(const char *msg, char repeat); const char *platform_target_voltage(void); void platform_delay(uint32_t delay); void platform_srst_set_val(bool assert); diff --git a/src/platforms/swlink/platform.c b/src/platforms/swlink/platform.c index 7b7446a..853cbc9 100644 --- a/src/platforms/swlink/platform.c +++ b/src/platforms/swlink/platform.c @@ -124,14 +124,6 @@ void sys_tick_handler(void) timeout_counter--; } -const char *morse_msg; - -void morse(const char *msg, char repeat) -{ - (void)repeat; - morse_msg = msg; -} - const char *platform_target_voltage(void) { return "unknown"; diff --git a/src/platforms/swlink/platform.h b/src/platforms/swlink/platform.h index 6683421..99c8fa3 100644 --- a/src/platforms/swlink/platform.h +++ b/src/platforms/swlink/platform.h @@ -141,7 +141,6 @@ extern volatile uint32_t timeout_counter; extern jmp_buf fatal_error_jmpbuf; -extern const char *morse_msg; #define gpio_set_val(port, pin, val) do { \ if(val) \ @@ -164,7 +163,6 @@ extern const char *morse_msg; } int platform_init(void); -void morse(const char *msg, char repeat); const char *platform_target_voltage(void); void platform_delay(uint32_t delay); -- cgit v1.2.3 From 48fb7ec6625000c2d93456de0649dc0b67b7d6c0 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sat, 28 Feb 2015 22:06:10 -0800 Subject: Add missing includes to fix warnings. --- src/lpc43xx.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src') diff --git a/src/lpc43xx.c b/src/lpc43xx.c index a739878..bfb96f7 100644 --- a/src/lpc43xx.c +++ b/src/lpc43xx.c @@ -19,10 +19,12 @@ #include #include +#include #include "command.h" #include "general.h" #include "adiv5.h" #include "target.h" +#include "gdb_packet.h" #define LPC43XX_CHIPID 0x40043200 #define ARM_CPUID 0xE000ED00 -- cgit v1.2.3 From 5eff0ab5d648408cf4df528d2be3d29b04034083 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sat, 28 Feb 2015 22:09:50 -0800 Subject: Factor out common GPIO code in STM32 platforms. --- src/platforms/f4discovery/platform.h | 28 ++--------------- src/platforms/native/platform.h | 33 ++----------------- src/platforms/stlink/platform.h | 33 ++----------------- src/platforms/stm32/gpio.h | 61 ++++++++++++++++++++++++++++++++++++ src/platforms/swlink/platform.h | 33 ++----------------- 5 files changed, 73 insertions(+), 115 deletions(-) create mode 100644 src/platforms/stm32/gpio.h (limited to 'src') diff --git a/src/platforms/f4discovery/platform.h b/src/platforms/f4discovery/platform.h index 90b2a11..dcad8a0 100644 --- a/src/platforms/f4discovery/platform.h +++ b/src/platforms/f4discovery/platform.h @@ -34,9 +34,9 @@ #include #include "gdb_packet.h" +#include "gpio.h" #include "morse.h" -#define INLINE_GPIO #define CDCACM_PACKET_SIZE 64 #define PLATFORM_HAS_TRACESWO #define BOARD_IDENT "Black Magic Probe (F4Discovery), (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" @@ -200,31 +200,9 @@ void uart_usb_buf_drain(uint8_t ep); #define sprintf siprintf #define vasprintf vasiprintf -#ifdef INLINE_GPIO -static inline void _gpio_set(uint32_t gpioport, uint16_t gpios) -{ - GPIO_BSRR(gpioport) = gpios; - GPIO_BSRR(gpioport) = gpios; -} -#define gpio_set _gpio_set - -static inline void _gpio_clear(uint32_t gpioport, uint16_t gpios) -{ - GPIO_BSRR(gpioport) = gpios<<16; - GPIO_BSRR(gpioport) = gpios<<16; -} -#define gpio_clear _gpio_clear - -static inline uint16_t _gpio_get(uint32_t gpioport, uint16_t gpios) -{ - return (uint16_t)GPIO_IDR(gpioport) & gpios; -} -#define gpio_get _gpio_get -#endif - -#endif - #define disconnect_usb() do {usbd_disconnect(usbdev,1); nvic_disable_irq(USB_IRQ);} while(0) void assert_boot_pin(void); #define setup_vbus_irq() +#endif + diff --git a/src/platforms/native/platform.h b/src/platforms/native/platform.h index 73b6c59..2fa1e84 100644 --- a/src/platforms/native/platform.h +++ b/src/platforms/native/platform.h @@ -35,9 +35,9 @@ #include #include "gdb_packet.h" +#include "gpio.h" #include "morse.h" -#define INLINE_GPIO #define CDCACM_PACKET_SIZE 64 #define PLATFORM_HAS_TRACESWO #define PLATFORM_HAS_POWER_SWITCH @@ -164,14 +164,6 @@ extern volatile uint32_t timeout_counter; extern jmp_buf fatal_error_jmpbuf; - -#define gpio_set_val(port, pin, val) do { \ - if(val) \ - gpio_set((port), (pin)); \ - else \ - gpio_clear((port), (pin)); \ -} while(0) - #define SET_RUN_STATE(state) {running_status = (state);} #define SET_IDLE_STATE(state) {gpio_set_val(LED_PORT, LED_IDLE_RUN, state);} #define SET_ERROR_STATE(state) {gpio_set_val(LED_PORT, LED_ERROR, state);} @@ -189,6 +181,8 @@ extern jmp_buf fatal_error_jmpbuf; int platform_init(void); const char *platform_target_voltage(void); int platform_hwversion(void); +void platform_set_timeout(uint32_t ms); +bool platform_timeout_expired(void); void platform_delay(uint32_t delay); /* */ @@ -205,27 +199,6 @@ void uart_usb_buf_drain(uint8_t ep); #define sprintf siprintf #define vasprintf vasiprintf -#ifdef INLINE_GPIO -static inline void _gpio_set(uint32_t gpioport, uint16_t gpios) -{ - GPIO_BSRR(gpioport) = gpios; -} -#define gpio_set _gpio_set - -static inline void _gpio_clear(uint32_t gpioport, uint16_t gpios) -{ - GPIO_BRR(gpioport) = gpios; -} -#define gpio_clear _gpio_clear - -static inline uint16_t _gpio_get(uint32_t gpioport, uint16_t gpios) -{ - return (uint16_t)GPIO_IDR(gpioport) & gpios; -} -#define gpio_get _gpio_get -#endif - - #define disconnect_usb() gpio_set_mode(USB_PU_PORT, GPIO_MODE_INPUT, 0, USB_PU_PIN); void assert_boot_pin(void); void setup_vbus_irq(void); diff --git a/src/platforms/stlink/platform.h b/src/platforms/stlink/platform.h index ee08875..a49e73a 100644 --- a/src/platforms/stlink/platform.h +++ b/src/platforms/stlink/platform.h @@ -35,8 +35,8 @@ #include #include "gdb_packet.h" +#include "gpio.h" -#define INLINE_GPIO #define CDCACM_PACKET_SIZE 64 #define BOARD_IDENT "Black Magic Probe (STLINK), (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" #define BOARD_IDENT_DFU "Black Magic (Upgrade) for STLink/Discovery, (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" @@ -143,13 +143,6 @@ extern volatile uint32_t timeout_counter; extern jmp_buf fatal_error_jmpbuf; -#define gpio_set_val(port, pin, val) do { \ - if(val) \ - gpio_set((port), (pin)); \ - else \ - gpio_clear((port), (pin)); \ -} while(0) - extern uint16_t led_idle_run; #define SET_RUN_STATE(state) {running_status = (state);} #define SET_IDLE_STATE(state) {gpio_set_val(LED_PORT, led_idle_run, state);} @@ -182,28 +175,8 @@ void uart_usb_buf_drain(uint8_t ep); #define sprintf siprintf #define vasprintf vasiprintf -#ifdef INLINE_GPIO -static inline void _gpio_set(uint32_t gpioport, uint16_t gpios) -{ - GPIO_BSRR(gpioport) = gpios; -} -#define gpio_set _gpio_set - -static inline void _gpio_clear(uint32_t gpioport, uint16_t gpios) -{ - GPIO_BRR(gpioport) = gpios; -} -#define gpio_clear _gpio_clear - -static inline uint16_t _gpio_get(uint32_t gpioport, uint16_t gpios) -{ - return (uint16_t)GPIO_IDR(gpioport) & gpios; -} -#define gpio_get _gpio_get -#endif - -#endif - void disconnect_usb(void); void assert_boot_pin(void); +#endif + diff --git a/src/platforms/stm32/gpio.h b/src/platforms/stm32/gpio.h new file mode 100644 index 0000000..035f3c9 --- /dev/null +++ b/src/platforms/stm32/gpio.h @@ -0,0 +1,61 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2015 Black Sphere Technologies Ltd. + * Written by Gareth McMullin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * 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, see . + */ +#ifndef __GPIO_H +#define __GPIO_H + +#define INLINE_GPIO + +#define gpio_set_val(port, pin, val) do { \ + if(val) \ + gpio_set((port), (pin)); \ + else \ + gpio_clear((port), (pin)); \ +} while(0) + +#ifdef INLINE_GPIO +static inline void _gpio_set(uint32_t gpioport, uint16_t gpios) +{ + GPIO_BSRR(gpioport) = gpios; +#ifdef F4DISCOVERY + GPIO_BSRR(gpioport) = gpios; +#endif +} +#define gpio_set _gpio_set + +static inline void _gpio_clear(uint32_t gpioport, uint16_t gpios) +{ +#ifndef F4DISCOVERY + GPIO_BRR(gpioport) = gpios; +#else + GPIO_BSRR(gpioport) = gpios<<16; + GPIO_BSRR(gpioport) = gpios<<16; +#endif +} +#define gpio_clear _gpio_clear + +static inline uint16_t _gpio_get(uint32_t gpioport, uint16_t gpios) +{ + return (uint16_t)GPIO_IDR(gpioport) & gpios; +} +#define gpio_get _gpio_get +#endif + +#endif + diff --git a/src/platforms/swlink/platform.h b/src/platforms/swlink/platform.h index 99c8fa3..4b26466 100644 --- a/src/platforms/swlink/platform.h +++ b/src/platforms/swlink/platform.h @@ -35,8 +35,8 @@ #include #include "gdb_packet.h" +#include "gpio.h" -#define INLINE_GPIO #define CDCACM_PACKET_SIZE 64 #define BOARD_IDENT "Black Magic Probe (SWLINK), (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" #define BOARD_IDENT_DFU "Black Magic (Upgrade), STM8S Discovery, (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" @@ -141,14 +141,6 @@ extern volatile uint32_t timeout_counter; extern jmp_buf fatal_error_jmpbuf; - -#define gpio_set_val(port, pin, val) do { \ - if(val) \ - gpio_set((port), (pin)); \ - else \ - gpio_clear((port), (pin)); \ -} while(0) - #define led_idle_run GPIO8 #define SET_RUN_STATE(state) {running_status = (state);} #define SET_IDLE_STATE(state) {gpio_set_val(LED_PORT, led_idle_run, state);} @@ -180,27 +172,8 @@ void uart_usb_buf_drain(uint8_t ep); #define sprintf siprintf #define vasprintf vasiprintf -#ifdef INLINE_GPIO -static inline void _gpio_set(uint32_t gpioport, uint16_t gpios) -{ - GPIO_BSRR(gpioport) = gpios; -} -#define gpio_set _gpio_set - -static inline void _gpio_clear(uint32_t gpioport, uint16_t gpios) -{ - GPIO_BRR(gpioport) = gpios; -} -#define gpio_clear _gpio_clear - -static inline uint16_t _gpio_get(uint32_t gpioport, uint16_t gpios) -{ - return (uint16_t)GPIO_IDR(gpioport) & gpios; -} -#define gpio_get _gpio_get -#endif +void disconnect_usb(void); +void assert_boot_pin(void); #endif -void disconnect_usb(void); -void assert_boot_pin(void); -- cgit v1.2.3 From 476f83b69ad86c71ee57c8633f09667e9caa0a5f Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sat, 28 Feb 2015 22:48:26 -0800 Subject: Move common USB stuff out of platform header files. --- src/include/traceswo.h | 28 ---------------------- src/include/usbuart.h | 33 -------------------------- src/platforms/f4discovery/platform.h | 14 ----------- src/platforms/native/platform.c | 1 + src/platforms/native/platform.h | 14 ----------- src/platforms/stlink/platform.h | 14 ----------- src/platforms/stm32/cdcacm.c | 5 ++-- src/platforms/stm32/cdcacm.h | 45 ++++++++++++++++++++++++++++++++++++ src/platforms/stm32/gdb_if.c | 3 +-- src/platforms/stm32/traceswo.c | 3 +-- src/platforms/stm32/traceswo.h | 28 ++++++++++++++++++++++ src/platforms/stm32/usbuart.c | 3 ++- src/platforms/stm32/usbuart.h | 33 ++++++++++++++++++++++++++ src/platforms/swlink/platform.h | 14 ----------- 14 files changed, 114 insertions(+), 124 deletions(-) delete mode 100644 src/include/traceswo.h delete mode 100644 src/include/usbuart.h create mode 100644 src/platforms/stm32/cdcacm.h create mode 100644 src/platforms/stm32/traceswo.h create mode 100644 src/platforms/stm32/usbuart.h (limited to 'src') diff --git a/src/include/traceswo.h b/src/include/traceswo.h deleted file mode 100644 index 5566f94..0000000 --- a/src/include/traceswo.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * This file is part of the Black Magic Debug project. - * - * Copyright (C) 2012 Black Sphere Technologies Ltd. - * Written by Gareth McMullin - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * 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, see . - */ -#ifndef __TRACESWO_H -#define __TRACESWO_H - -#include - -void traceswo_init(void); -void trace_buf_drain(usbd_device *dev, uint8_t ep); - -#endif diff --git a/src/include/usbuart.h b/src/include/usbuart.h deleted file mode 100644 index 39f7dcd..0000000 --- a/src/include/usbuart.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * This file is part of the Black Magic Debug project. - * - * Copyright (C) 2012 Black Sphere Technologies Ltd. - * Written by Gareth McMullin - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * 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, see . - */ -#ifndef __USBUART_H -#define __USBUART_H - -#include -#include -#include "general.h" - -void usbuart_init(void); - -void usbuart_set_line_coding(struct usb_cdc_line_coding *coding); -void usbuart_usb_out_cb(usbd_device *dev, uint8_t ep); -void usbuart_usb_in_cb(usbd_device *dev, uint8_t ep); - -#endif diff --git a/src/platforms/f4discovery/platform.h b/src/platforms/f4discovery/platform.h index dcad8a0..140e8d1 100644 --- a/src/platforms/f4discovery/platform.h +++ b/src/platforms/f4discovery/platform.h @@ -37,17 +37,12 @@ #include "gpio.h" #include "morse.h" -#define CDCACM_PACKET_SIZE 64 #define PLATFORM_HAS_TRACESWO #define BOARD_IDENT "Black Magic Probe (F4Discovery), (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" #define BOARD_IDENT_DFU "Black Magic (Upgrade) for F4Discovery, (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" #define DFU_IDENT "Black Magic Firmware Upgrade (F4Discovery" #define DFU_IFACE_STRING "@Internal Flash /0x08000000/1*016Ka,3*016Kg,1*064Kg,7*128Kg" -extern usbd_device *usbdev; -#define CDCACM_GDB_ENDPOINT 1 -#define CDCACM_UART_ENDPOINT 3 - /* Important pin mappings for STM32 implementation: * * LED0 = PD12 (Green LED : Running) @@ -186,15 +181,6 @@ static inline int platform_hwversion(void) return 0; } -/* */ -void cdcacm_init(void); -/* Returns current usb configuration, or 0 if not configured. */ -int cdcacm_get_config(void); -int cdcacm_get_dtr(void); - -/* */ -void uart_usb_buf_drain(uint8_t ep); - /* Use newlib provided integer only stdio functions */ #define sscanf siscanf #define sprintf siprintf diff --git a/src/platforms/native/platform.c b/src/platforms/native/platform.c index 3e269d9..3f61f5f 100644 --- a/src/platforms/native/platform.c +++ b/src/platforms/native/platform.c @@ -34,6 +34,7 @@ #include #include "jtag_scan.h" +#include "cdcacm.h" #include "usbuart.h" #include "morse.h" diff --git a/src/platforms/native/platform.h b/src/platforms/native/platform.h index 2fa1e84..321c3f3 100644 --- a/src/platforms/native/platform.h +++ b/src/platforms/native/platform.h @@ -38,7 +38,6 @@ #include "gpio.h" #include "morse.h" -#define CDCACM_PACKET_SIZE 64 #define PLATFORM_HAS_TRACESWO #define PLATFORM_HAS_POWER_SWITCH #define BOARD_IDENT "Black Magic Probe" @@ -48,10 +47,6 @@ #define DFU_IFACE_STRING "@Internal Flash /0x08000000/8*001Ka,120*001Kg" #define UPD_IFACE_STRING "@Internal Flash /0x08000000/8*001Kg" -extern usbd_device *usbdev; -#define CDCACM_GDB_ENDPOINT 1 -#define CDCACM_UART_ENDPOINT 3 - /* Important pin mappings for STM32 implementation: * * LED0 = PB2 (Yellow LED : Running) @@ -185,15 +180,6 @@ void platform_set_timeout(uint32_t ms); bool platform_timeout_expired(void); void platform_delay(uint32_t delay); -/* */ -void cdcacm_init(void); -/* Returns current usb configuration, or 0 if not configured. */ -int cdcacm_get_config(void); -int cdcacm_get_dtr(void); - -/* */ -void uart_usb_buf_drain(uint8_t ep); - /* Use newlib provided integer only stdio functions */ #define sscanf siscanf #define sprintf siprintf diff --git a/src/platforms/stlink/platform.h b/src/platforms/stlink/platform.h index a49e73a..a33ca06 100644 --- a/src/platforms/stlink/platform.h +++ b/src/platforms/stlink/platform.h @@ -37,7 +37,6 @@ #include "gdb_packet.h" #include "gpio.h" -#define CDCACM_PACKET_SIZE 64 #define BOARD_IDENT "Black Magic Probe (STLINK), (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" #define BOARD_IDENT_DFU "Black Magic (Upgrade) for STLink/Discovery, (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" #define BOARD_IDENT_UPD "Black Magic (DFU Upgrade) for STLink/Discovery, (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" @@ -45,10 +44,6 @@ #define DFU_IFACE_STRING "@Internal Flash /0x08000000/8*001Ka,56*001Kg" #define UPD_IFACE_STRING "@Internal Flash /0x08000000/8*001Kg" -extern usbd_device *usbdev; -#define CDCACM_GDB_ENDPOINT 1 -#define CDCACM_UART_ENDPOINT 3 - /* Important pin mappings for STM32 implementation: * * LED0 = PB2 (Yellow LED : Running) @@ -161,15 +156,6 @@ const char *platform_target_voltage(void); void platform_delay(uint32_t delay); void platform_srst_set_val(bool assert); -/* */ -void cdcacm_init(void); -/* Returns current usb configuration, or 0 if not configured. */ -int cdcacm_get_config(void); -int cdcacm_get_dtr(void); - -/* */ -void uart_usb_buf_drain(uint8_t ep); - /* Use newlib provided integer only stdio functions */ #define sscanf siscanf #define sprintf siprintf diff --git a/src/platforms/stm32/cdcacm.c b/src/platforms/stm32/cdcacm.c index 9694cf0..074b534 100644 --- a/src/platforms/stm32/cdcacm.c +++ b/src/platforms/stm32/cdcacm.c @@ -35,10 +35,11 @@ #include "platform.h" #include "gdb_if.h" +#include "cdcacm.h" #if defined(PLATFORM_HAS_TRACESWO) -#include +#include "traceswo.h" #endif -#include +#include "usbuart.h" #define DFU_IF_NO 4 diff --git a/src/platforms/stm32/cdcacm.h b/src/platforms/stm32/cdcacm.h new file mode 100644 index 0000000..f64399d --- /dev/null +++ b/src/platforms/stm32/cdcacm.h @@ -0,0 +1,45 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2015 Black Sphere Technologies Ltd. + * Written by Gareth McMullin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * 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, see . + */ + +/* This file implements a the USB Communications Device Class - Abstract + * Control Model (CDC-ACM) as defined in CDC PSTN subclass 1.2. + * A Device Firmware Upgrade (DFU 1.1) class interface is provided for + * field firmware upgrade. + * + * The device's unique id is used as the USB serial number string. + */ +#ifndef __CDCACM_H +#define __CDCACM_H + +#include + +#define CDCACM_PACKET_SIZE 64 + +#define CDCACM_GDB_ENDPOINT 1 +#define CDCACM_UART_ENDPOINT 3 + +extern usbd_device *usbdev; + +void cdcacm_init(void); +/* Returns current usb configuration, or 0 if not configured. */ +int cdcacm_get_config(void); +int cdcacm_get_dtr(void); + +#endif diff --git a/src/platforms/stm32/gdb_if.c b/src/platforms/stm32/gdb_if.c index c8208b3..6cc9084 100644 --- a/src/platforms/stm32/gdb_if.c +++ b/src/platforms/stm32/gdb_if.c @@ -23,8 +23,7 @@ * uses the USB CDC-ACM device bulk endpoints to implement the channel. */ #include "platform.h" -#include - +#include "cdcacm.h" #include "gdb_if.h" static uint32_t count_out; diff --git a/src/platforms/stm32/traceswo.c b/src/platforms/stm32/traceswo.c index 01ad728..29bae8f 100644 --- a/src/platforms/stm32/traceswo.c +++ b/src/platforms/stm32/traceswo.c @@ -37,10 +37,9 @@ #include #include -#include - #include #include "platform.h" +#include "cdcacm.h" void traceswo_init(void) { diff --git a/src/platforms/stm32/traceswo.h b/src/platforms/stm32/traceswo.h new file mode 100644 index 0000000..5566f94 --- /dev/null +++ b/src/platforms/stm32/traceswo.h @@ -0,0 +1,28 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2012 Black Sphere Technologies Ltd. + * Written by Gareth McMullin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * 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, see . + */ +#ifndef __TRACESWO_H +#define __TRACESWO_H + +#include + +void traceswo_init(void); +void trace_buf_drain(usbd_device *dev, uint8_t ep); + +#endif diff --git a/src/platforms/stm32/usbuart.c b/src/platforms/stm32/usbuart.c index f8f56bf..970a609 100644 --- a/src/platforms/stm32/usbuart.c +++ b/src/platforms/stm32/usbuart.c @@ -27,7 +27,8 @@ #include #include -#include +#include "platform.h" +#include "cdcacm.h" #define USBUART_TIMER_FREQ_HZ 1000000U /* 1us per tick */ #define USBUART_RUN_FREQ_HZ 5000U /* 200us (or 100 characters at 2Mbps) */ diff --git a/src/platforms/stm32/usbuart.h b/src/platforms/stm32/usbuart.h new file mode 100644 index 0000000..39f7dcd --- /dev/null +++ b/src/platforms/stm32/usbuart.h @@ -0,0 +1,33 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2012 Black Sphere Technologies Ltd. + * Written by Gareth McMullin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * 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, see . + */ +#ifndef __USBUART_H +#define __USBUART_H + +#include +#include +#include "general.h" + +void usbuart_init(void); + +void usbuart_set_line_coding(struct usb_cdc_line_coding *coding); +void usbuart_usb_out_cb(usbd_device *dev, uint8_t ep); +void usbuart_usb_in_cb(usbd_device *dev, uint8_t ep); + +#endif diff --git a/src/platforms/swlink/platform.h b/src/platforms/swlink/platform.h index 4b26466..26cb7a6 100644 --- a/src/platforms/swlink/platform.h +++ b/src/platforms/swlink/platform.h @@ -37,7 +37,6 @@ #include "gdb_packet.h" #include "gpio.h" -#define CDCACM_PACKET_SIZE 64 #define BOARD_IDENT "Black Magic Probe (SWLINK), (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" #define BOARD_IDENT_DFU "Black Magic (Upgrade), STM8S Discovery, (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" #define BOARD_IDENT_UPD "Black Magic (DFU Upgrade), STM8S Discovery, (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" @@ -45,10 +44,6 @@ #define DFU_IFACE_STRING "@Internal Flash /0x08000000/8*001Ka,56*001Kg" #define UPD_IFACE_STRING "@Internal Flash /0x08000000/8*001Kg" -extern usbd_device *usbdev; -#define CDCACM_GDB_ENDPOINT 1 -#define CDCACM_UART_ENDPOINT 3 - /* Pin mappings: * * nTRST = PB1 @@ -158,15 +153,6 @@ int platform_init(void); const char *platform_target_voltage(void); void platform_delay(uint32_t delay); -/* */ -void cdcacm_init(void); -/* Returns current usb configuration, or 0 if not configured. */ -int cdcacm_get_config(void); -int cdcacm_get_dtr(void); - -/* */ -void uart_usb_buf_drain(uint8_t ep); - /* Use newlib provided integer only stdio functions */ #define sscanf siscanf #define sprintf siprintf -- cgit v1.2.3 From 9d80641261cee52fdf1976caa41d4fd24c392c9a Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sun, 1 Mar 2015 20:15:31 -0800 Subject: Move common platform include to a common directory. --- src/Makefile | 2 +- src/platforms/common/cdcacm.h | 45 +++++++++++++++++++++++++++++++++++++++++ src/platforms/common/traceswo.h | 28 +++++++++++++++++++++++++ src/platforms/common/usbuart.h | 33 ++++++++++++++++++++++++++++++ src/platforms/stm32/cdcacm.h | 45 ----------------------------------------- src/platforms/stm32/traceswo.h | 28 ------------------------- src/platforms/stm32/usbuart.h | 33 ------------------------------ 7 files changed, 107 insertions(+), 107 deletions(-) create mode 100644 src/platforms/common/cdcacm.h create mode 100644 src/platforms/common/traceswo.h create mode 100644 src/platforms/common/usbuart.h delete mode 100644 src/platforms/stm32/cdcacm.h delete mode 100644 src/platforms/stm32/traceswo.h delete mode 100644 src/platforms/stm32/usbuart.h (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 25cf715..8b01854 100644 --- a/src/Makefile +++ b/src/Makefile @@ -7,7 +7,7 @@ BUILDDATE := `date +"%Y%m%d"` CFLAGS += -Wall -Wextra -Wno-pointer-sign -Wno-char-subscripts\ -Wno-sign-compare \ -O2 -std=gnu99 -g3 -DBUILDDATE=\"$(BUILDDATE)\"\ - -I. -Iinclude -I$(PLATFORM_DIR) \ + -I. -Iinclude -Iplatforms/common -I$(PLATFORM_DIR) \ -DVERSION_SUFFIX=\"`../scripts/setlocalversion`\" -MD SRC = \ diff --git a/src/platforms/common/cdcacm.h b/src/platforms/common/cdcacm.h new file mode 100644 index 0000000..f64399d --- /dev/null +++ b/src/platforms/common/cdcacm.h @@ -0,0 +1,45 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2015 Black Sphere Technologies Ltd. + * Written by Gareth McMullin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * 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, see . + */ + +/* This file implements a the USB Communications Device Class - Abstract + * Control Model (CDC-ACM) as defined in CDC PSTN subclass 1.2. + * A Device Firmware Upgrade (DFU 1.1) class interface is provided for + * field firmware upgrade. + * + * The device's unique id is used as the USB serial number string. + */ +#ifndef __CDCACM_H +#define __CDCACM_H + +#include + +#define CDCACM_PACKET_SIZE 64 + +#define CDCACM_GDB_ENDPOINT 1 +#define CDCACM_UART_ENDPOINT 3 + +extern usbd_device *usbdev; + +void cdcacm_init(void); +/* Returns current usb configuration, or 0 if not configured. */ +int cdcacm_get_config(void); +int cdcacm_get_dtr(void); + +#endif diff --git a/src/platforms/common/traceswo.h b/src/platforms/common/traceswo.h new file mode 100644 index 0000000..5566f94 --- /dev/null +++ b/src/platforms/common/traceswo.h @@ -0,0 +1,28 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2012 Black Sphere Technologies Ltd. + * Written by Gareth McMullin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * 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, see . + */ +#ifndef __TRACESWO_H +#define __TRACESWO_H + +#include + +void traceswo_init(void); +void trace_buf_drain(usbd_device *dev, uint8_t ep); + +#endif diff --git a/src/platforms/common/usbuart.h b/src/platforms/common/usbuart.h new file mode 100644 index 0000000..39f7dcd --- /dev/null +++ b/src/platforms/common/usbuart.h @@ -0,0 +1,33 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2012 Black Sphere Technologies Ltd. + * Written by Gareth McMullin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * 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, see . + */ +#ifndef __USBUART_H +#define __USBUART_H + +#include +#include +#include "general.h" + +void usbuart_init(void); + +void usbuart_set_line_coding(struct usb_cdc_line_coding *coding); +void usbuart_usb_out_cb(usbd_device *dev, uint8_t ep); +void usbuart_usb_in_cb(usbd_device *dev, uint8_t ep); + +#endif diff --git a/src/platforms/stm32/cdcacm.h b/src/platforms/stm32/cdcacm.h deleted file mode 100644 index f64399d..0000000 --- a/src/platforms/stm32/cdcacm.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * This file is part of the Black Magic Debug project. - * - * Copyright (C) 2015 Black Sphere Technologies Ltd. - * Written by Gareth McMullin - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * 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, see . - */ - -/* This file implements a the USB Communications Device Class - Abstract - * Control Model (CDC-ACM) as defined in CDC PSTN subclass 1.2. - * A Device Firmware Upgrade (DFU 1.1) class interface is provided for - * field firmware upgrade. - * - * The device's unique id is used as the USB serial number string. - */ -#ifndef __CDCACM_H -#define __CDCACM_H - -#include - -#define CDCACM_PACKET_SIZE 64 - -#define CDCACM_GDB_ENDPOINT 1 -#define CDCACM_UART_ENDPOINT 3 - -extern usbd_device *usbdev; - -void cdcacm_init(void); -/* Returns current usb configuration, or 0 if not configured. */ -int cdcacm_get_config(void); -int cdcacm_get_dtr(void); - -#endif diff --git a/src/platforms/stm32/traceswo.h b/src/platforms/stm32/traceswo.h deleted file mode 100644 index 5566f94..0000000 --- a/src/platforms/stm32/traceswo.h +++ /dev/null @@ -1,28 +0,0 @@ -/* - * This file is part of the Black Magic Debug project. - * - * Copyright (C) 2012 Black Sphere Technologies Ltd. - * Written by Gareth McMullin - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * 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, see . - */ -#ifndef __TRACESWO_H -#define __TRACESWO_H - -#include - -void traceswo_init(void); -void trace_buf_drain(usbd_device *dev, uint8_t ep); - -#endif diff --git a/src/platforms/stm32/usbuart.h b/src/platforms/stm32/usbuart.h deleted file mode 100644 index 39f7dcd..0000000 --- a/src/platforms/stm32/usbuart.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * This file is part of the Black Magic Debug project. - * - * Copyright (C) 2012 Black Sphere Technologies Ltd. - * Written by Gareth McMullin - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * 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, see . - */ -#ifndef __USBUART_H -#define __USBUART_H - -#include -#include -#include "general.h" - -void usbuart_init(void); - -void usbuart_set_line_coding(struct usb_cdc_line_coding *coding); -void usbuart_usb_out_cb(usbd_device *dev, uint8_t ep); -void usbuart_usb_in_cb(usbd_device *dev, uint8_t ep); - -#endif -- cgit v1.2.3 From 4d4813de87721528fc9a06174dd1da5c245ae2f3 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sun, 1 Mar 2015 22:16:04 -0800 Subject: Clean up includes everywhere. All source files include general.h first and before anything else. This inlcludes platform.h and platform_support.h No header file needs to include to include any of these, but should include any others needed for it's own declarations.--- src/adiv5.c | 5 ---- src/adiv5_jtagdp.c | 3 --- src/adiv5_swdp.c | 5 ---- src/arm7tdmi.c | 4 ---- src/command.c | 6 ----- src/cortexm.c | 7 ++---- src/crc32.c | 2 +- src/gdb_main.c | 11 --------- src/gdb_packet.c | 9 ++------ src/hex_utils.c | 4 +--- src/include/adiv5.h | 1 - src/include/arm7tdmi.h | 1 - src/include/command.h | 1 - src/include/cortexm.h | 20 ++++++++++++++++ src/include/crc32.h | 2 -- src/include/gdb_packet.h | 2 -- src/include/general.h | 12 +++++++--- src/include/jtag_scan.h | 2 -- src/include/jtagtap.h | 2 -- src/include/morse.h | 2 -- src/include/platform_support.h | 41 +++++++++++++++++++++++++++++++++ src/include/swdptap.h | 2 -- src/include/target.h | 2 -- src/jtag_scan.c | 7 ------ src/kinetis.c | 3 --- src/lmi.c | 3 --- src/lpc11xx.c | 21 +++++++++++++---- src/lpc43xx.c | 5 +--- src/main.c | 10 +++----- src/nrf51.c | 3 --- src/platforms/common/usbuart.h | 1 - src/platforms/f4discovery/platform.c | 22 +++++------------- src/platforms/f4discovery/platform.h | 14 ++--------- src/platforms/f4discovery/usbdfu.c | 6 ++--- src/platforms/launchpad-icdi/platform.c | 11 ++++----- src/platforms/launchpad-icdi/platform.h | 16 +------------ src/platforms/libftdi/jtagtap.c | 1 + src/platforms/libftdi/platform.c | 15 +++--------- src/platforms/libftdi/platform.h | 5 ---- src/platforms/libftdi/swdptap.c | 2 +- src/platforms/native/platform.c | 22 ++++-------------- src/platforms/native/platform.h | 22 ++---------------- src/platforms/stlink/platform.c | 22 ++++-------------- src/platforms/stlink/platform.h | 16 ++++--------- src/platforms/stm32/cdcacm.c | 2 +- src/platforms/stm32/dfu_f1.c | 5 ++-- src/platforms/stm32/dfu_f4.c | 6 ++--- src/platforms/stm32/dfucore.c | 2 +- src/platforms/stm32/gdb_if.c | 2 +- src/platforms/stm32/gpio.h | 10 ++++++++ src/platforms/stm32/jtagtap.c | 2 -- src/platforms/stm32/traceswo.c | 5 +--- src/platforms/stm32/usbuart.c | 2 +- src/platforms/swlink/platform.c | 21 ++++------------- src/platforms/swlink/platform.h | 16 ++----------- src/platforms/tm4c/cdcacm.c | 2 +- src/platforms/tm4c/gdb_if.c | 6 +++-- src/platforms/tm4c/jtagtap.c | 1 + src/platforms/tm4c/swdptap.c | 1 - src/platforms/tm4c/traceswo.c | 5 ---- src/platforms/tm4c/usbuart.c | 4 ++-- src/sam3x.c | 3 --- src/samd.c | 4 ---- src/stm32f1.c | 3 --- src/stm32f4.c | 3 --- src/stm32l1.c | 3 --- src/target.c | 2 -- 67 files changed, 167 insertions(+), 316 deletions(-) create mode 100644 src/include/platform_support.h (limited to 'src') diff --git a/src/adiv5.c b/src/adiv5.c index 6dcc919..361cd75 100644 --- a/src/adiv5.c +++ b/src/adiv5.c @@ -25,15 +25,10 @@ * Currently doesn't use ROM table for introspection, just assumes * the device is Cortex-M3. */ - -#include -#include - #include "general.h" #include "jtag_scan.h" #include "gdb_packet.h" #include "adiv5.h" - #include "target.h" #ifndef DO_RESET_SEQ diff --git a/src/adiv5_jtagdp.c b/src/adiv5_jtagdp.c index fd77a04..8f62a11 100644 --- a/src/adiv5_jtagdp.c +++ b/src/adiv5_jtagdp.c @@ -23,14 +23,11 @@ */ #include "general.h" -#include "platform.h" #include "adiv5.h" #include "jtag_scan.h" #include "jtagtap.h" #include "morse.h" -#include - #define JTAGDP_ACK_OK 0x02 #define JTAGDP_ACK_WAIT 0x01 diff --git a/src/adiv5_swdp.c b/src/adiv5_swdp.c index 6bafc91..9df362f 100644 --- a/src/adiv5_swdp.c +++ b/src/adiv5_swdp.c @@ -23,17 +23,12 @@ */ #include "general.h" -#include "platform.h" #include "adiv5.h" - #include "swdptap.h" #include "jtagtap.h" - #include "command.h" #include "morse.h" -#include - #define SWDP_ACK_OK 0x01 #define SWDP_ACK_WAIT 0x02 #define SWDP_ACK_FAULT 0x04 diff --git a/src/arm7tdmi.c b/src/arm7tdmi.c index 1c7b443..1721787 100644 --- a/src/arm7tdmi.c +++ b/src/arm7tdmi.c @@ -24,14 +24,10 @@ */ #include "general.h" -#include "platform.h" #include "target.h" #include "jtag_scan.h" #include "jtagtap.h" -#include -#include - /* TODO: * Skeleton target. * EmbeddedICE registers, halt/resume target. diff --git a/src/command.c b/src/command.c index 7c17864..f271085 100644 --- a/src/command.c +++ b/src/command.c @@ -22,18 +22,12 @@ * commands. */ -#include -#include - #include "general.h" - #include "command.h" #include "gdb_packet.h" - #include "jtag_scan.h" #include "target.h" #include "morse.h" - #include "adiv5.h" #ifdef PLATFORM_HAS_TRACESWO diff --git a/src/cortexm.c b/src/cortexm.c index 12914d3..a016342 100644 --- a/src/cortexm.c +++ b/src/cortexm.c @@ -28,11 +28,6 @@ * Issues: * There are way too many magic numbers used here. */ -#include -#include -#include -#include - #include "general.h" #include "jtagtap.h" #include "jtag_scan.h" @@ -42,6 +37,8 @@ #include "gdb_packet.h" #include "cortexm.h" +#include + static char cortexm_driver_str[] = "ARM Cortex-M"; static bool cortexm_vector_catch(target *t, int argc, char *argv[]); diff --git a/src/crc32.c b/src/crc32.c index 810a9dd..42d1d48 100644 --- a/src/crc32.c +++ b/src/crc32.c @@ -18,7 +18,7 @@ * along with this program. If not, see . */ -#include "platform.h" +#include "general.h" #include "target.h" #if !defined(STM32F1) && !defined(STM32F4) diff --git a/src/gdb_main.c b/src/gdb_main.c index 41ab84a..17ad9a5 100644 --- a/src/gdb_main.c +++ b/src/gdb_main.c @@ -24,26 +24,15 @@ * Originally written for GDB 6.8, updated and tested with GDB 7.2. */ -#include -#include -#include - -#include - -#include "platform.h" - #include "general.h" #include "hex_utils.h" #include "gdb_if.h" #include "gdb_packet.h" #include "gdb_main.h" - #include "jtagtap.h" #include "jtag_scan.h" #include "adiv5.h" - #include "target.h" - #include "command.h" #include "crc32.h" diff --git a/src/gdb_packet.c b/src/gdb_packet.c index d43be42..4dc934f 100644 --- a/src/gdb_packet.c +++ b/src/gdb_packet.c @@ -22,18 +22,13 @@ * reception and transmission as well as some convenience functions. */ -#define _GNU_SOURCE -#include -#include -#include - -#include - #include "general.h" #include "gdb_if.h" #include "gdb_packet.h" #include "hex_utils.h" +#include + int gdb_getpacket(unsigned char *packet, int size) { diff --git a/src/hex_utils.c b/src/hex_utils.c index e477281..45382ff 100644 --- a/src/hex_utils.c +++ b/src/hex_utils.c @@ -21,9 +21,7 @@ /* Convenience function to convert to/from ascii strings of hex digits. */ -#include -#include - +#include "general.h" #include "hex_utils.h" static char hexdigits[] = "0123456789abcdef"; diff --git a/src/include/adiv5.h b/src/include/adiv5.h index 0f17119..e0ce9cf 100644 --- a/src/include/adiv5.h +++ b/src/include/adiv5.h @@ -21,7 +21,6 @@ #ifndef __ADIV5_H #define __ADIV5_H -#include "general.h" #include "jtag_scan.h" #include "target.h" diff --git a/src/include/arm7tdmi.h b/src/include/arm7tdmi.h index ffcd6e9..fa7d586 100644 --- a/src/include/arm7tdmi.h +++ b/src/include/arm7tdmi.h @@ -21,7 +21,6 @@ #ifndef __ARM7TDMI_H #define __ARM7TDMI_H -#include "general.h" #include "jtag_scan.h" void arm7tdmi_jtag_handler(jtag_dev_t *dev); diff --git a/src/include/command.h b/src/include/command.h index 32b0d7b..3910bbb 100644 --- a/src/include/command.h +++ b/src/include/command.h @@ -21,7 +21,6 @@ #ifndef __COMMAND_H #define __COMMAND_H -#include "general.h" #include "target.h" int command_process(target *t, char *cmd); diff --git a/src/include/cortexm.h b/src/include/cortexm.h index f1fc07a..1fd77e6 100644 --- a/src/include/cortexm.h +++ b/src/include/cortexm.h @@ -1,6 +1,26 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2015 Gareth McMullin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * 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, see . + */ #ifndef __CORTEXM_H #define __CORTEXM_H +#include "target.h" + /* Private peripheral bus base address */ #define CORTEXM_PPB_BASE 0xE0000000 diff --git a/src/include/crc32.h b/src/include/crc32.h index 6cc00ea..9966d8d 100644 --- a/src/include/crc32.h +++ b/src/include/crc32.h @@ -21,8 +21,6 @@ #ifndef __CRC32_H #define __CRC32_H -#include "platform.h" - uint32_t crc32_calc(uint32_t crc, uint8_t data); uint32_t generic_crc32(struct target_s *target, uint32_t base, int len); diff --git a/src/include/gdb_packet.h b/src/include/gdb_packet.h index 9f5430f..222b86d 100644 --- a/src/include/gdb_packet.h +++ b/src/include/gdb_packet.h @@ -21,8 +21,6 @@ #ifndef __GDB_PACKET_H #define __GDB_PACKET_H -#include - int gdb_getpacket(unsigned char *packet, int size); void gdb_putpacket(unsigned char *packet, int size); #define gdb_putpacketz(packet) gdb_putpacket((packet), strlen(packet)) diff --git a/src/include/general.h b/src/include/general.h index b0721ac..b4e9aeb 100644 --- a/src/include/general.h +++ b/src/include/general.h @@ -21,15 +21,21 @@ #ifndef __GENERAL_H #define __GENERAL_H +#define _GNU_SOURCE +#include +#include +#include +#include +#include +#include + #include "platform.h" +#include "platform_support.h" #ifndef DEBUG #include #define DEBUG printf #endif -#include -#include - #endif diff --git a/src/include/jtag_scan.h b/src/include/jtag_scan.h index b425b95..aa006e7 100644 --- a/src/include/jtag_scan.h +++ b/src/include/jtag_scan.h @@ -21,8 +21,6 @@ #ifndef __JTAG_SCAN_H #define __JTAG_SCAN_H -#include "general.h" - #define JTAG_MAX_DEVS 5 #define JTAG_MAX_IR_LEN 16 diff --git a/src/include/jtagtap.h b/src/include/jtagtap.h index fd13f2b..0072594 100644 --- a/src/include/jtagtap.h +++ b/src/include/jtagtap.h @@ -21,8 +21,6 @@ #ifndef __JTAGTAP_H #define __JTAGTAP_H -#include "general.h" - /* Note: Signal names are as for the device under test. */ int jtagtap_init(void); diff --git a/src/include/morse.h b/src/include/morse.h index ac53893..5ba39b1 100644 --- a/src/include/morse.h +++ b/src/include/morse.h @@ -21,8 +21,6 @@ #ifndef __MORSE_H #define __MORSE_H -#include - extern const char *morse_msg; void morse(const char *msg, char repeat); diff --git a/src/include/platform_support.h b/src/include/platform_support.h new file mode 100644 index 0000000..cc88ab6 --- /dev/null +++ b/src/include/platform_support.h @@ -0,0 +1,41 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2015 Gareth McMullin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * 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, see . + */ + +#ifndef __PLATFORM_SUPPORT_H +#define __PLATFORM_SUPPORT_H + +#ifndef __GENERAL_H +# error "Include 'general.h' instead" +#endif + +#if defined(LIBFTDI) +void platform_init(int argc, char **argv); +#else +void platform_init(void); +#endif + +const char *platform_target_voltage(void); +int platform_hwversion(void); +void platform_delay(uint32_t delay); +void platform_srst_set_val(bool assert); +bool platform_target_get_power(void); +void platform_target_set_power(bool power); + +#endif + diff --git a/src/include/swdptap.h b/src/include/swdptap.h index 5bb0545..3263a1d 100644 --- a/src/include/swdptap.h +++ b/src/include/swdptap.h @@ -21,8 +21,6 @@ #ifndef __SWDPTAP_H #define __SWDPTAP_H -#include "general.h" - int swdptap_init(void); void swdptap_reset(void); diff --git a/src/include/target.h b/src/include/target.h index 50f1ebe..0e6d9c2 100644 --- a/src/include/target.h +++ b/src/include/target.h @@ -25,8 +25,6 @@ #ifndef __TARGET_H #define __TARGET_H -#include "general.h" - typedef struct target_s target; /* The destroy callback function will be called by target_list_free() just diff --git a/src/jtag_scan.c b/src/jtag_scan.c index 257e6c4..208a1db 100644 --- a/src/jtag_scan.c +++ b/src/jtag_scan.c @@ -22,19 +22,12 @@ * to detect devices on the scan chain and read their IDCODEs. * It depends on the low-level function provided by the platform's jtagtap.c. */ -#include -#include -#include - -#include #include "general.h" #include "jtagtap.h" #include "morse.h" #include "jtag_scan.h" - #include "gdb_packet.h" - #include "adiv5.h" #include "arm7tdmi.h" diff --git a/src/kinetis.c b/src/kinetis.c index 393bb18..4b7cf31 100644 --- a/src/kinetis.c +++ b/src/kinetis.c @@ -22,9 +22,6 @@ * the XML memory map and Flash memory programming. */ -#include -#include - #include "general.h" #include "adiv5.h" #include "target.h" diff --git a/src/lmi.c b/src/lmi.c index a251242..8d409d0 100644 --- a/src/lmi.c +++ b/src/lmi.c @@ -27,9 +27,6 @@ * Flash erase is very slow. */ -#include -#include - #include "general.h" #include "adiv5.h" #include "target.h" diff --git a/src/lpc11xx.c b/src/lpc11xx.c index ef26e78..d9e918e 100644 --- a/src/lpc11xx.c +++ b/src/lpc11xx.c @@ -1,8 +1,19 @@ - -#include -#include -#include - +/* + * This file is part of the Black Magic Debug project. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * 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, see . + */ #include "general.h" #include "adiv5.h" #include "target.h" diff --git a/src/lpc43xx.c b/src/lpc43xx.c index bfb96f7..3940fed 100644 --- a/src/lpc43xx.c +++ b/src/lpc43xx.c @@ -17,11 +17,8 @@ * along with this program. If not, see . */ -#include -#include -#include -#include "command.h" #include "general.h" +#include "command.h" #include "adiv5.h" #include "target.h" #include "gdb_packet.h" diff --git a/src/main.c b/src/main.c index 809d4bf..60db15c 100644 --- a/src/main.c +++ b/src/main.c @@ -22,26 +22,22 @@ * protocol loop. */ -#include -#include -#include - +#include "general.h" #include "gdb_if.h" #include "gdb_main.h" #include "jtagtap.h" #include "jtag_scan.h" - #include "target.h" int main(int argc, char **argv) { #if defined(LIBFTDI) - assert(platform_init(argc, argv) == 0); + platform_init(argc, argv); #else (void) argc; (void) argv; - assert(platform_init() == 0); + platform_init(); #endif PLATFORM_SET_FATAL_ERROR_RECOVERY(); diff --git a/src/nrf51.c b/src/nrf51.c index 7305d29..6c1a8b9 100644 --- a/src/nrf51.c +++ b/src/nrf51.c @@ -21,9 +21,6 @@ * the device, providing the XML memory map and Flash memory programming. */ -#include -#include - #include "general.h" #include "adiv5.h" #include "target.h" diff --git a/src/platforms/common/usbuart.h b/src/platforms/common/usbuart.h index 39f7dcd..51f5702 100644 --- a/src/platforms/common/usbuart.h +++ b/src/platforms/common/usbuart.h @@ -22,7 +22,6 @@ #include #include -#include "general.h" void usbuart_init(void); diff --git a/src/platforms/f4discovery/platform.c b/src/platforms/f4discovery/platform.c index e051564..cf6cdf3 100644 --- a/src/platforms/f4discovery/platform.c +++ b/src/platforms/f4discovery/platform.c @@ -22,7 +22,11 @@ * implementation. */ -#include "platform.h" +#include "general.h" +#include "cdcacm.h" +#include "usbuart.h" +#include "morse.h" + #include #include #include @@ -32,16 +36,12 @@ #include #include -#include "jtag_scan.h" -#include "usbuart.h" -#include "morse.h" - uint8_t running_status; volatile uint32_t timeout_counter; jmp_buf fatal_error_jmpbuf; -int platform_init(void) +void platform_init(void) { /* Check the USER button*/ rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPAEN); @@ -86,17 +86,7 @@ int platform_init(void) systick_counter_enable(); usbuart_init(); - cdcacm_init(); - - // Set recovery point - if (setjmp(fatal_error_jmpbuf)) { - return 0; // Do nothing on failure - } - - jtag_scan(NULL); - - return 0; } void platform_delay(uint32_t delay) diff --git a/src/platforms/f4discovery/platform.h b/src/platforms/f4discovery/platform.h index 140e8d1..f58205d 100644 --- a/src/platforms/f4discovery/platform.h +++ b/src/platforms/f4discovery/platform.h @@ -24,19 +24,12 @@ #ifndef __PLATFORM_H #define __PLATFORM_H -#include -#include -#include -#include -#include - -#include -#include - #include "gdb_packet.h" #include "gpio.h" #include "morse.h" +#include + #define PLATFORM_HAS_TRACESWO #define BOARD_IDENT "Black Magic Probe (F4Discovery), (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" #define BOARD_IDENT_DFU "Black Magic (Upgrade) for F4Discovery, (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" @@ -173,9 +166,6 @@ extern jmp_buf fatal_error_jmpbuf; longjmp(fatal_error_jmpbuf, (error)); \ } -int platform_init(void); -const char *platform_target_voltage(void); -void platform_delay(uint32_t delay); static inline int platform_hwversion(void) { return 0; diff --git a/src/platforms/f4discovery/usbdfu.c b/src/platforms/f4discovery/usbdfu.c index 7070ade..6a40295 100644 --- a/src/platforms/f4discovery/usbdfu.c +++ b/src/platforms/f4discovery/usbdfu.c @@ -17,14 +17,14 @@ * along with this program. If not, see . */ -#include +#include "general.h" +#include "usbdfu.h" + #include #include #include #include -#include "usbdfu.h" - void dfu_detach(void) { /* USB device must detach, we just reset... */ diff --git a/src/platforms/launchpad-icdi/platform.c b/src/platforms/launchpad-icdi/platform.c index 1e66e12..0e3fb85 100644 --- a/src/platforms/launchpad-icdi/platform.c +++ b/src/platforms/launchpad-icdi/platform.c @@ -1,5 +1,6 @@ -#include "platform.h" +#include "general.h" #include "gdb_if.h" +#include "cdcacm.h" #include "usbuart.h" #include @@ -26,14 +27,14 @@ void sys_tick_handler(void) trace_tick(); } -int +void platform_init(void) { int i; for(i=0; i<1000000; i++); rcc_sysclk_config(OSCSRC_MOSC, XTAL_16M, PLL_DIV_80MHZ); - + // Enable all JTAG ports and set pins to output periph_clock_enable(RCC_GPIOA); periph_clock_enable(RCC_GPIOB); @@ -59,10 +60,6 @@ platform_init(void) usbuart_init(); cdcacm_init(); - - //jtag_scan(NULL); - - return 0; } void platform_delay(uint32_t delay) diff --git a/src/platforms/launchpad-icdi/platform.h b/src/platforms/launchpad-icdi/platform.h index 8c343a8..5f686f4 100644 --- a/src/platforms/launchpad-icdi/platform.h +++ b/src/platforms/launchpad-icdi/platform.h @@ -1,16 +1,13 @@ #ifndef __PLATFORM_H #define __PLATFORM_H -#include +#include "gdb_packet.h" #include -#include #include #include -#include "gdb_packet.h" - #define CDCACM_PACKET_SIZE 64 #define BOARD_IDENT "Black Magic Probe (Launchpad ICDI), (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" #define BOARD_IDENT_DFU "Black Magic (Upgrade) for Launchpad, (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" @@ -110,8 +107,6 @@ extern usbd_driver lm4f_usb_driver; #define PLATFORM_HAS_TRACESWO -int platform_init(void); - inline static void gpio_set_val(uint32_t port, uint8_t pin, uint8_t val) { gpio_write(port, pin, val == 0 ? 0 : 0xff); } @@ -120,15 +115,6 @@ inline static uint8_t gpio_get(uint32_t port, uint8_t pin) { return !(gpio_read(port, pin) == 0); } -void platform_delay(uint32_t delay); -const char *platform_target_voltage(void); - -/* */ -void cdcacm_init(void); -/* Returns current usb configuration, or 0 if not configured. */ -int cdcacm_get_config(void); -int cdcacm_get_dtr(void); - #define disconnect_usb() do { usbd_disconnect(usbdev,1); nvic_disable_irq(USB_IRQ);} while(0) #define setup_vbus_irq() diff --git a/src/platforms/libftdi/jtagtap.c b/src/platforms/libftdi/jtagtap.c index 91f6ae2..c9bc876 100644 --- a/src/platforms/libftdi/jtagtap.c +++ b/src/platforms/libftdi/jtagtap.c @@ -69,6 +69,7 @@ void jtagtap_reset(void) void jtagtap_srst(bool assert) { + (void)assert; platform_buffer_flush(); //ftdi_write_data(ftdic, "\x80\x88\xAB", 3); //usleep(1000); diff --git a/src/platforms/libftdi/platform.c b/src/platforms/libftdi/platform.c index 723efa3..e53f011 100644 --- a/src/platforms/libftdi/platform.c +++ b/src/platforms/libftdi/platform.c @@ -17,14 +17,10 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -#include "platform.h" +#include "general.h" #include "gdb_if.h" -#include "jtag_scan.h" -#include -#include #include -#include struct ftdi_context *ftdic; @@ -121,7 +117,7 @@ static struct cable_desc_s { }, }; -int platform_init(int argc, char **argv) +void platform_init(int argc, char **argv) { int err; int c; @@ -149,7 +145,7 @@ int platform_init(int argc, char **argv) if (index == sizeof(cable_desc)/sizeof(cable_desc[0])){ fprintf(stderr, "No cable matching %s found\n",cablename); - return -1; + exit(-1); } if (cable_desc[index].dbus_data) @@ -212,12 +208,7 @@ int platform_init(int argc, char **argv) } assert(ftdi_write_data(ftdic, ftdi_init, 9) == 9); - assert(gdb_if_init() == 0); - - jtag_scan(NULL); - - return 0; } void platform_buffer_flush(void) diff --git a/src/platforms/libftdi/platform.h b/src/platforms/libftdi/platform.h index a95a3f4..135b2e3 100644 --- a/src/platforms/libftdi/platform.h +++ b/src/platforms/libftdi/platform.h @@ -21,7 +21,6 @@ #ifndef __PLATFORM_H #define __PLATFORM_H -#include #include #ifndef WIN32 @@ -42,10 +41,6 @@ extern struct ftdi_context *ftdic; -int platform_init(int argc, char **argv); -const char *platform_target_voltage(void); -void platform_delay(uint32_t delay); - void platform_buffer_flush(void); int platform_buffer_write(const uint8_t *data, int size); int platform_buffer_read(uint8_t *data, int size); diff --git a/src/platforms/libftdi/swdptap.c b/src/platforms/libftdi/swdptap.c index ef350de..eb6e65e 100644 --- a/src/platforms/libftdi/swdptap.c +++ b/src/platforms/libftdi/swdptap.c @@ -26,7 +26,7 @@ #include #include -#include "platform.h" +#include "general.h" #include "swdptap.h" static void swdptap_turnaround(uint8_t dir); diff --git a/src/platforms/native/platform.c b/src/platforms/native/platform.c index 3f61f5f..9b39238 100644 --- a/src/platforms/native/platform.c +++ b/src/platforms/native/platform.c @@ -22,7 +22,10 @@ * implementation. */ -#include "platform.h" +#include "general.h" +#include "cdcacm.h" +#include "usbuart.h" +#include "morse.h" #include #include @@ -33,11 +36,6 @@ #include #include -#include "jtag_scan.h" -#include "cdcacm.h" -#include "usbuart.h" -#include "morse.h" - uint8_t running_status; volatile uint32_t timeout_counter; @@ -62,7 +60,7 @@ int platform_hwversion(void) return hwversion; } -int platform_init(void) +void platform_init(void) { rcc_clock_setup_in_hse_8mhz_out_72mhz(); @@ -136,16 +134,6 @@ int platform_init(void) cdcacm_init(); usbuart_init(); - - /* Set recovery point */ - if (setjmp(fatal_error_jmpbuf)) { - /* Do nothing on failure */ - return 0; - } - - jtag_scan(NULL); - - return 0; } void platform_srst_set_val(bool assert) diff --git a/src/platforms/native/platform.h b/src/platforms/native/platform.h index 321c3f3..5688e60 100644 --- a/src/platforms/native/platform.h +++ b/src/platforms/native/platform.h @@ -24,20 +24,12 @@ #ifndef __PLATFORM_H #define __PLATFORM_H -#include -#include -#include - -#include -#include - -#include -#include - #include "gdb_packet.h" #include "gpio.h" #include "morse.h" +#include + #define PLATFORM_HAS_TRACESWO #define PLATFORM_HAS_POWER_SWITCH #define BOARD_IDENT "Black Magic Probe" @@ -173,13 +165,6 @@ extern jmp_buf fatal_error_jmpbuf; longjmp(fatal_error_jmpbuf, (error)); \ } while (0) -int platform_init(void); -const char *platform_target_voltage(void); -int platform_hwversion(void); -void platform_set_timeout(uint32_t ms); -bool platform_timeout_expired(void); -void platform_delay(uint32_t delay); - /* Use newlib provided integer only stdio functions */ #define sscanf siscanf #define sprintf siprintf @@ -188,9 +173,6 @@ void platform_delay(uint32_t delay); #define disconnect_usb() gpio_set_mode(USB_PU_PORT, GPIO_MODE_INPUT, 0, USB_PU_PIN); void assert_boot_pin(void); void setup_vbus_irq(void); -void platform_srst_set_val(bool assert); -bool platform_target_get_power(void); -void platform_target_set_power(bool power); #endif diff --git a/src/platforms/stlink/platform.c b/src/platforms/stlink/platform.c index 6ef8c77..6194d92 100644 --- a/src/platforms/stlink/platform.c +++ b/src/platforms/stlink/platform.c @@ -22,7 +22,10 @@ * implementation. */ -#include "platform.h" +#include "general.h" +#include "cdcacm.h" +#include "usbuart.h" + #include #include #include @@ -31,11 +34,6 @@ #include #include -#include "jtag_scan.h" -#include - -#include - uint8_t running_status; volatile uint32_t timeout_counter; @@ -68,7 +66,7 @@ int platform_hwversion(void) return hwversion; } -int platform_init(void) +void platform_init(void) { rcc_clock_setup_in_hse_8mhz_out_72mhz(); @@ -119,16 +117,6 @@ int platform_init(void) SCB_VTOR = 0x2000; /* Relocate interrupt vector table here */ cdcacm_init(); - - /* Set recovery point */ - if (setjmp(fatal_error_jmpbuf)) { - /* Do nothing on failure */ - return 0; - } - - jtag_scan(NULL); - - return 0; } void platform_delay(uint32_t delay) diff --git a/src/platforms/stlink/platform.h b/src/platforms/stlink/platform.h index a33ca06..5768817 100644 --- a/src/platforms/stlink/platform.h +++ b/src/platforms/stlink/platform.h @@ -24,18 +24,14 @@ #ifndef __PLATFORM_H #define __PLATFORM_H -#include +#include "gdb_packet.h" +#include "gpio.h" + #include #include - -#include #include #include -#include - -#include "gdb_packet.h" -#include "gpio.h" #define BOARD_IDENT "Black Magic Probe (STLINK), (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" #define BOARD_IDENT_DFU "Black Magic (Upgrade) for STLink/Discovery, (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" @@ -151,11 +147,6 @@ extern uint16_t led_idle_run; longjmp(fatal_error_jmpbuf, (error)); \ } while (0) -int platform_init(void); -const char *platform_target_voltage(void); -void platform_delay(uint32_t delay); -void platform_srst_set_val(bool assert); - /* Use newlib provided integer only stdio functions */ #define sscanf siscanf #define sprintf siprintf @@ -163,6 +154,7 @@ void platform_srst_set_val(bool assert); void disconnect_usb(void); void assert_boot_pin(void); +void setup_vbus_irq(void); #endif diff --git a/src/platforms/stm32/cdcacm.c b/src/platforms/stm32/cdcacm.c index 074b534..577925a 100644 --- a/src/platforms/stm32/cdcacm.c +++ b/src/platforms/stm32/cdcacm.c @@ -33,7 +33,7 @@ #include #include -#include "platform.h" +#include "general.h" #include "gdb_if.h" #include "cdcacm.h" #if defined(PLATFORM_HAS_TRACESWO) diff --git a/src/platforms/stm32/dfu_f1.c b/src/platforms/stm32/dfu_f1.c index bb1e274..abbdbe6 100644 --- a/src/platforms/stm32/dfu_f1.c +++ b/src/platforms/stm32/dfu_f1.c @@ -16,12 +16,11 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - -#include "platform.h" +#include "general.h" +#include "usbdfu.h" #include #include -#include "usbdfu.h" #define FLASH_OBP_RDP 0x1FFFF800 #define FLASH_OBP_WRP10 0x1FFFF808 diff --git a/src/platforms/stm32/dfu_f4.c b/src/platforms/stm32/dfu_f4.c index 1065938..2ececa0 100644 --- a/src/platforms/stm32/dfu_f4.c +++ b/src/platforms/stm32/dfu_f4.c @@ -16,8 +16,8 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ - -#include "platform.h" +#include "general.h" +#include "usbdfu.h" #if defined(STM32F2) # include @@ -26,8 +26,6 @@ #endif #include -#include "usbdfu.h" - static uint32_t sector_addr[] = { 0x8000000, 0x8004000, 0x8008000, 0x800c000, 0x8010000, 0x8020000, 0x8040000, 0x8060000, diff --git a/src/platforms/stm32/dfucore.c b/src/platforms/stm32/dfucore.c index 77cef4e..7b733d7 100644 --- a/src/platforms/stm32/dfucore.c +++ b/src/platforms/stm32/dfucore.c @@ -17,7 +17,7 @@ * along with this program. If not, see . */ -#include "platform.h" +#include "general.h" #include #if defined(STM32F1) diff --git a/src/platforms/stm32/gdb_if.c b/src/platforms/stm32/gdb_if.c index 6cc9084..286c66b 100644 --- a/src/platforms/stm32/gdb_if.c +++ b/src/platforms/stm32/gdb_if.c @@ -22,7 +22,7 @@ * Serial Debugging protocol is implemented. This implementation for STM32 * uses the USB CDC-ACM device bulk endpoints to implement the channel. */ -#include "platform.h" +#include "general.h" #include "cdcacm.h" #include "gdb_if.h" diff --git a/src/platforms/stm32/gpio.h b/src/platforms/stm32/gpio.h index 035f3c9..ee8275e 100644 --- a/src/platforms/stm32/gpio.h +++ b/src/platforms/stm32/gpio.h @@ -20,6 +20,16 @@ #ifndef __GPIO_H #define __GPIO_H +#include + +#ifndef STM32F4 +# include +# include +#else +# include +# include +#endif + #define INLINE_GPIO #define gpio_set_val(port, pin, val) do { \ diff --git a/src/platforms/stm32/jtagtap.c b/src/platforms/stm32/jtagtap.c index 2d09b84..3c45a81 100644 --- a/src/platforms/stm32/jtagtap.c +++ b/src/platforms/stm32/jtagtap.c @@ -23,9 +23,7 @@ #include #include "general.h" - #include "jtagtap.h" -#include "platform.h" int jtagtap_init(void) { diff --git a/src/platforms/stm32/traceswo.c b/src/platforms/stm32/traceswo.c index 29bae8f..a2e704d 100644 --- a/src/platforms/stm32/traceswo.c +++ b/src/platforms/stm32/traceswo.c @@ -32,15 +32,12 @@ * The core can then process the buffer to extract the frame. */ #include "general.h" +#include "cdcacm.h" #include #include #include -#include -#include "platform.h" -#include "cdcacm.h" - void traceswo_init(void) { TRACE_TIM_CLK_EN(); diff --git a/src/platforms/stm32/usbuart.c b/src/platforms/stm32/usbuart.c index 970a609..cce2904 100644 --- a/src/platforms/stm32/usbuart.c +++ b/src/platforms/stm32/usbuart.c @@ -27,7 +27,7 @@ #include #include -#include "platform.h" +#include "general.h" #include "cdcacm.h" #define USBUART_TIMER_FREQ_HZ 1000000U /* 1us per tick */ diff --git a/src/platforms/swlink/platform.c b/src/platforms/swlink/platform.c index 853cbc9..168ba2a 100644 --- a/src/platforms/swlink/platform.c +++ b/src/platforms/swlink/platform.c @@ -22,7 +22,10 @@ * implementation. */ -#include "platform.h" +#include "general.h" +#include "cdcacm.h" +#include "usbuart.h" + #include #include #include @@ -31,17 +34,12 @@ #include #include -#include "jtag_scan.h" -#include - -#include - uint8_t running_status; volatile uint32_t timeout_counter; jmp_buf fatal_error_jmpbuf; -int platform_init(void) +void platform_init(void) { uint32_t data; rcc_clock_setup_in_hse_8mhz_out_72mhz(); @@ -98,15 +96,6 @@ int platform_init(void) SCB_VTOR = 0x2000; // Relocate interrupt vector table here cdcacm_init(); - - // Set recovery point - if (setjmp(fatal_error_jmpbuf)) { - return 0; // Do nothing on failure - } - - jtag_scan(NULL); - - return 0; } void platform_delay(uint32_t delay) diff --git a/src/platforms/swlink/platform.h b/src/platforms/swlink/platform.h index 26cb7a6..dec5548 100644 --- a/src/platforms/swlink/platform.h +++ b/src/platforms/swlink/platform.h @@ -24,19 +24,11 @@ #ifndef __PLATFORM_H #define __PLATFORM_H -#include -#include -#include - -#include -#include - -#include -#include - #include "gdb_packet.h" #include "gpio.h" +#include + #define BOARD_IDENT "Black Magic Probe (SWLINK), (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" #define BOARD_IDENT_DFU "Black Magic (Upgrade), STM8S Discovery, (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" #define BOARD_IDENT_UPD "Black Magic (DFU Upgrade), STM8S Discovery, (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" @@ -149,10 +141,6 @@ extern jmp_buf fatal_error_jmpbuf; longjmp(fatal_error_jmpbuf, (error)); \ } -int platform_init(void); -const char *platform_target_voltage(void); -void platform_delay(uint32_t delay); - /* Use newlib provided integer only stdio functions */ #define sscanf siscanf #define sprintf siprintf diff --git a/src/platforms/tm4c/cdcacm.c b/src/platforms/tm4c/cdcacm.c index 041d85b..2677ad5 100644 --- a/src/platforms/tm4c/cdcacm.c +++ b/src/platforms/tm4c/cdcacm.c @@ -35,7 +35,7 @@ #include #include -#include "platform.h" +#include "general.h" #include "gdb_if.h" #if defined(PLATFORM_HAS_TRACESWO) #include diff --git a/src/platforms/tm4c/gdb_if.c b/src/platforms/tm4c/gdb_if.c index b14bbd3..7119638 100644 --- a/src/platforms/tm4c/gdb_if.c +++ b/src/platforms/tm4c/gdb_if.c @@ -22,10 +22,12 @@ * Serial Debugging protocol is implemented. This implementation for STM32 * uses the USB CDC-ACM device bulk endpoints to implement the channel. */ -#include "platform.h" -#include +#include "general.h" #include "gdb_if.h" +#include "cdcacm.h" + +#include static volatile uint32_t head_out, tail_out; static volatile uint32_t count_in; diff --git a/src/platforms/tm4c/jtagtap.c b/src/platforms/tm4c/jtagtap.c index f340b1e..e0bdd68 100644 --- a/src/platforms/tm4c/jtagtap.c +++ b/src/platforms/tm4c/jtagtap.c @@ -1,3 +1,4 @@ +#include "general.h" #include "jtagtap.h" int diff --git a/src/platforms/tm4c/swdptap.c b/src/platforms/tm4c/swdptap.c index 7004598..058f6ba 100644 --- a/src/platforms/tm4c/swdptap.c +++ b/src/platforms/tm4c/swdptap.c @@ -1,5 +1,4 @@ #include "general.h" -#include "platform.h" #include "swdptap.h" static void swdptap_turnaround(uint8_t dir) diff --git a/src/platforms/tm4c/traceswo.c b/src/platforms/tm4c/traceswo.c index eb63139..03c6d66 100644 --- a/src/platforms/tm4c/traceswo.c +++ b/src/platforms/tm4c/traceswo.c @@ -32,14 +32,9 @@ #include #include #include - #include - #include -#include -#include "platform.h" - void traceswo_init(void) { periph_clock_enable(RCC_GPIOD); diff --git a/src/platforms/tm4c/usbuart.c b/src/platforms/tm4c/usbuart.c index bb769f0..da82198 100644 --- a/src/platforms/tm4c/usbuart.c +++ b/src/platforms/tm4c/usbuart.c @@ -19,6 +19,8 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ +#include "general.h" +#include "cdcacm.h" #include #include @@ -27,8 +29,6 @@ #include #include -#include - #define FIFO_SIZE 128 /* RX Fifo buffer */ diff --git a/src/sam3x.c b/src/sam3x.c index e6b8f2e..ef99290 100644 --- a/src/sam3x.c +++ b/src/sam3x.c @@ -22,9 +22,6 @@ * the device, providing the XML memory map and Flash memory programming. */ -#include -#include - #include "general.h" #include "adiv5.h" #include "target.h" diff --git a/src/samd.c b/src/samd.c index b043c50..1a7a553 100644 --- a/src/samd.c +++ b/src/samd.c @@ -32,10 +32,6 @@ * particularly Sections 12. DSU and 20. NVMCTRL */ -#include -#include -#include - #include "general.h" #include "jtagtap.h" #include "adiv5.h" diff --git a/src/stm32f1.c b/src/stm32f1.c index bce00d3..017196a 100644 --- a/src/stm32f1.c +++ b/src/stm32f1.c @@ -29,9 +29,6 @@ * Programming manual - STM32F10xxx Flash memory microcontrollers */ -#include -#include - #include "general.h" #include "adiv5.h" #include "target.h" diff --git a/src/stm32f4.c b/src/stm32f4.c index 148c31b..bc3572f 100644 --- a/src/stm32f4.c +++ b/src/stm32f4.c @@ -30,9 +30,6 @@ * manual */ -#include -#include - #include "general.h" #include "adiv5.h" #include "target.h" diff --git a/src/stm32l1.c b/src/stm32l1.c index 0472885..227f67c 100644 --- a/src/stm32l1.c +++ b/src/stm32l1.c @@ -29,9 +29,6 @@ * Flash and EEPROM programming */ -#include -#include - #include "general.h" #include "adiv5.h" #include "target.h" diff --git a/src/target.c b/src/target.c index 2a68f23..4299a45 100644 --- a/src/target.c +++ b/src/target.c @@ -21,8 +21,6 @@ #include "general.h" #include "target.h" -#include - target *target_list = NULL; bool connect_assert_srst; -- cgit v1.2.3 From b07ffffcee53e18051b324eb59a2794044ce6f95 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Mon, 2 Mar 2015 10:16:33 -0800 Subject: Factor out common cdcacm.c from stm32 and tm4c. Cleaned up interface to enter bootloader and read serial number.--- src/Makefile | 2 +- src/include/platform_support.h | 1 + src/platforms/common/cdcacm.c | 554 ++++++++++++++++++++++++++++++ src/platforms/common/serialno.h | 26 ++ src/platforms/f4discovery/Makefile.inc | 1 + src/platforms/f4discovery/platform.c | 8 +- src/platforms/f4discovery/platform.h | 4 - src/platforms/launchpad-icdi/platform.c | 46 +++ src/platforms/launchpad-icdi/platform.h | 22 +- src/platforms/native/Makefile.inc | 1 + src/platforms/native/platform.c | 10 +- src/platforms/native/platform.h | 4 - src/platforms/stlink/Makefile.inc | 3 +- src/platforms/stlink/platform.c | 10 +- src/platforms/stlink/platform.h | 4 - src/platforms/stm32/cdcacm.c | 583 -------------------------------- src/platforms/stm32/serialno.c | 45 +++ src/platforms/swlink/Makefile.inc | 3 +- src/platforms/swlink/platform.c | 8 +- src/platforms/swlink/platform.h | 3 - src/platforms/tm4c/cdcacm.c | 577 ------------------------------- src/platforms/tm4c/traceswo.c | 1 + 22 files changed, 715 insertions(+), 1201 deletions(-) create mode 100644 src/platforms/common/cdcacm.c create mode 100644 src/platforms/common/serialno.h delete mode 100644 src/platforms/stm32/cdcacm.c create mode 100644 src/platforms/stm32/serialno.c delete mode 100644 src/platforms/tm4c/cdcacm.c (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 8b01854..09e0bf0 100644 --- a/src/Makefile +++ b/src/Makefile @@ -1,6 +1,6 @@ PROBE_HOST ?= native PLATFORM_DIR = platforms/$(PROBE_HOST) -VPATH += $(PLATFORM_DIR) +VPATH += platforms/common $(PLATFORM_DIR) BUILDDATE := `date +"%Y%m%d"` diff --git a/src/include/platform_support.h b/src/include/platform_support.h index cc88ab6..7d8443c 100644 --- a/src/include/platform_support.h +++ b/src/include/platform_support.h @@ -36,6 +36,7 @@ void platform_delay(uint32_t delay); void platform_srst_set_val(bool assert); bool platform_target_get_power(void); void platform_target_set_power(bool power); +void platform_request_boot(void); #endif diff --git a/src/platforms/common/cdcacm.c b/src/platforms/common/cdcacm.c new file mode 100644 index 0000000..8e95a9a --- /dev/null +++ b/src/platforms/common/cdcacm.c @@ -0,0 +1,554 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2011 Black Sphere Technologies Ltd. + * Written by Gareth McMullin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * 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, see . + */ + +/* This file implements a the USB Communications Device Class - Abstract + * Control Model (CDC-ACM) as defined in CDC PSTN subclass 1.2. + * A Device Firmware Upgrade (DFU 1.1) class interface is provided for + * field firmware upgrade. + * + * The device's unique id is used as the USB serial number string. + */ + +#include "general.h" +#include "gdb_if.h" +#include "cdcacm.h" +#if defined(PLATFORM_HAS_TRACESWO) +# include "traceswo.h" +#endif +#include "usbuart.h" +#include "serialno.h" + +#include +#include +#include +#include +#include +#include + +#define DFU_IF_NO 4 + +usbd_device * usbdev; + +static int configured; +static int cdcacm_gdb_dtr = 1; + + +static const struct usb_device_descriptor dev = { + .bLength = USB_DT_DEVICE_SIZE, + .bDescriptorType = USB_DT_DEVICE, + .bcdUSB = 0x0200, + .bDeviceClass = 0xEF, /* Miscellaneous Device */ + .bDeviceSubClass = 2, /* Common Class */ + .bDeviceProtocol = 1, /* Interface Association */ + .bMaxPacketSize0 = 64, + .idVendor = 0x1D50, + .idProduct = 0x6018, + .bcdDevice = 0x0100, + .iManufacturer = 1, + .iProduct = 2, + .iSerialNumber = 3, + .bNumConfigurations = 1, +}; + +/* This notification endpoint isn't implemented. According to CDC spec its + * optional, but its absence causes a NULL pointer dereference in Linux cdc_acm + * driver. */ +static const struct usb_endpoint_descriptor gdb_comm_endp[] = {{ + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 0x82, + .bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT, + .wMaxPacketSize = 16, + .bInterval = 255, +}}; + +static const struct usb_endpoint_descriptor gdb_data_endp[] = {{ + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 0x01, + .bmAttributes = USB_ENDPOINT_ATTR_BULK, + .wMaxPacketSize = CDCACM_PACKET_SIZE, + .bInterval = 1, +}, { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 0x81, + .bmAttributes = USB_ENDPOINT_ATTR_BULK, + .wMaxPacketSize = CDCACM_PACKET_SIZE, + .bInterval = 1, +}}; + +static const struct { + struct usb_cdc_header_descriptor header; + struct usb_cdc_call_management_descriptor call_mgmt; + struct usb_cdc_acm_descriptor acm; + struct usb_cdc_union_descriptor cdc_union; +} __attribute__((packed)) gdb_cdcacm_functional_descriptors = { + .header = { + .bFunctionLength = sizeof(struct usb_cdc_header_descriptor), + .bDescriptorType = CS_INTERFACE, + .bDescriptorSubtype = USB_CDC_TYPE_HEADER, + .bcdCDC = 0x0110, + }, + .call_mgmt = { + .bFunctionLength = + sizeof(struct usb_cdc_call_management_descriptor), + .bDescriptorType = CS_INTERFACE, + .bDescriptorSubtype = USB_CDC_TYPE_CALL_MANAGEMENT, + .bmCapabilities = 0, + .bDataInterface = 1, + }, + .acm = { + .bFunctionLength = sizeof(struct usb_cdc_acm_descriptor), + .bDescriptorType = CS_INTERFACE, + .bDescriptorSubtype = USB_CDC_TYPE_ACM, + .bmCapabilities = 2, /* SET_LINE_CODING supported */ + }, + .cdc_union = { + .bFunctionLength = sizeof(struct usb_cdc_union_descriptor), + .bDescriptorType = CS_INTERFACE, + .bDescriptorSubtype = USB_CDC_TYPE_UNION, + .bControlInterface = 0, + .bSubordinateInterface0 = 1, + } +}; + +static const struct usb_interface_descriptor gdb_comm_iface[] = {{ + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 0, + .bAlternateSetting = 0, + .bNumEndpoints = 1, + .bInterfaceClass = USB_CLASS_CDC, + .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, + .bInterfaceProtocol = USB_CDC_PROTOCOL_AT, + .iInterface = 4, + + .endpoint = gdb_comm_endp, + + .extra = &gdb_cdcacm_functional_descriptors, + .extralen = sizeof(gdb_cdcacm_functional_descriptors) +}}; + +static const struct usb_interface_descriptor gdb_data_iface[] = {{ + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 1, + .bAlternateSetting = 0, + .bNumEndpoints = 2, + .bInterfaceClass = USB_CLASS_DATA, + .bInterfaceSubClass = 0, + .bInterfaceProtocol = 0, + .iInterface = 0, + + .endpoint = gdb_data_endp, +}}; + +static const struct usb_iface_assoc_descriptor gdb_assoc = { + .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE, + .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, + .bFirstInterface = 0, + .bInterfaceCount = 2, + .bFunctionClass = USB_CLASS_CDC, + .bFunctionSubClass = USB_CDC_SUBCLASS_ACM, + .bFunctionProtocol = USB_CDC_PROTOCOL_AT, + .iFunction = 0, +}; + +/* Serial ACM interface */ +static const struct usb_endpoint_descriptor uart_comm_endp[] = {{ + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 0x84, + .bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT, + .wMaxPacketSize = 16, + .bInterval = 255, +}}; + +static const struct usb_endpoint_descriptor uart_data_endp[] = {{ + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 0x03, + .bmAttributes = USB_ENDPOINT_ATTR_BULK, + .wMaxPacketSize = CDCACM_PACKET_SIZE, + .bInterval = 1, +}, { + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 0x83, + .bmAttributes = USB_ENDPOINT_ATTR_BULK, + .wMaxPacketSize = CDCACM_PACKET_SIZE, + .bInterval = 1, +}}; + +static const struct { + struct usb_cdc_header_descriptor header; + struct usb_cdc_call_management_descriptor call_mgmt; + struct usb_cdc_acm_descriptor acm; + struct usb_cdc_union_descriptor cdc_union; +} __attribute__((packed)) uart_cdcacm_functional_descriptors = { + .header = { + .bFunctionLength = sizeof(struct usb_cdc_header_descriptor), + .bDescriptorType = CS_INTERFACE, + .bDescriptorSubtype = USB_CDC_TYPE_HEADER, + .bcdCDC = 0x0110, + }, + .call_mgmt = { + .bFunctionLength = + sizeof(struct usb_cdc_call_management_descriptor), + .bDescriptorType = CS_INTERFACE, + .bDescriptorSubtype = USB_CDC_TYPE_CALL_MANAGEMENT, + .bmCapabilities = 0, + .bDataInterface = 3, + }, + .acm = { + .bFunctionLength = sizeof(struct usb_cdc_acm_descriptor), + .bDescriptorType = CS_INTERFACE, + .bDescriptorSubtype = USB_CDC_TYPE_ACM, + .bmCapabilities = 2, /* SET_LINE_CODING supported*/ + }, + .cdc_union = { + .bFunctionLength = sizeof(struct usb_cdc_union_descriptor), + .bDescriptorType = CS_INTERFACE, + .bDescriptorSubtype = USB_CDC_TYPE_UNION, + .bControlInterface = 2, + .bSubordinateInterface0 = 3, + } +}; + +static const struct usb_interface_descriptor uart_comm_iface[] = {{ + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 2, + .bAlternateSetting = 0, + .bNumEndpoints = 1, + .bInterfaceClass = USB_CLASS_CDC, + .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, + .bInterfaceProtocol = USB_CDC_PROTOCOL_AT, + .iInterface = 5, + + .endpoint = uart_comm_endp, + + .extra = &uart_cdcacm_functional_descriptors, + .extralen = sizeof(uart_cdcacm_functional_descriptors) +}}; + +static const struct usb_interface_descriptor uart_data_iface[] = {{ + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 3, + .bAlternateSetting = 0, + .bNumEndpoints = 2, + .bInterfaceClass = USB_CLASS_DATA, + .bInterfaceSubClass = 0, + .bInterfaceProtocol = 0, + .iInterface = 0, + + .endpoint = uart_data_endp, +}}; + +static const struct usb_iface_assoc_descriptor uart_assoc = { + .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE, + .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, + .bFirstInterface = 2, + .bInterfaceCount = 2, + .bFunctionClass = USB_CLASS_CDC, + .bFunctionSubClass = USB_CDC_SUBCLASS_ACM, + .bFunctionProtocol = USB_CDC_PROTOCOL_AT, + .iFunction = 0, +}; + +const struct usb_dfu_descriptor dfu_function = { + .bLength = sizeof(struct usb_dfu_descriptor), + .bDescriptorType = DFU_FUNCTIONAL, + .bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_WILL_DETACH, + .wDetachTimeout = 255, + .wTransferSize = 1024, + .bcdDFUVersion = 0x011A, +}; + +const struct usb_interface_descriptor dfu_iface = { + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = DFU_IF_NO, + .bAlternateSetting = 0, + .bNumEndpoints = 0, + .bInterfaceClass = 0xFE, + .bInterfaceSubClass = 1, + .bInterfaceProtocol = 1, + .iInterface = 6, + + .extra = &dfu_function, + .extralen = sizeof(dfu_function), +}; + +static const struct usb_iface_assoc_descriptor dfu_assoc = { + .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE, + .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, + .bFirstInterface = 4, + .bInterfaceCount = 1, + .bFunctionClass = 0xFE, + .bFunctionSubClass = 1, + .bFunctionProtocol = 1, + .iFunction = 6, +}; + +#if defined(PLATFORM_HAS_TRACESWO) +static const struct usb_endpoint_descriptor trace_endp[] = {{ + .bLength = USB_DT_ENDPOINT_SIZE, + .bDescriptorType = USB_DT_ENDPOINT, + .bEndpointAddress = 0x85, + .bmAttributes = USB_ENDPOINT_ATTR_BULK, + .wMaxPacketSize = 64, + .bInterval = 0, +}}; + +const struct usb_interface_descriptor trace_iface = { + .bLength = USB_DT_INTERFACE_SIZE, + .bDescriptorType = USB_DT_INTERFACE, + .bInterfaceNumber = 5, + .bAlternateSetting = 0, + .bNumEndpoints = 1, + .bInterfaceClass = 0xFF, + .bInterfaceSubClass = 0xFF, + .bInterfaceProtocol = 0xFF, + .iInterface = 7, + + .endpoint = trace_endp, +}; + +static const struct usb_iface_assoc_descriptor trace_assoc = { + .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE, + .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, + .bFirstInterface = 5, + .bInterfaceCount = 1, + .bFunctionClass = 0xFF, + .bFunctionSubClass = 0xFF, + .bFunctionProtocol = 0xFF, + .iFunction = 7, +}; +#endif + +static const struct usb_interface ifaces[] = {{ + .num_altsetting = 1, + .iface_assoc = &gdb_assoc, + .altsetting = gdb_comm_iface, +}, { + .num_altsetting = 1, + .altsetting = gdb_data_iface, +}, { + .num_altsetting = 1, + .iface_assoc = &uart_assoc, + .altsetting = uart_comm_iface, +}, { + .num_altsetting = 1, + .altsetting = uart_data_iface, +}, { + .num_altsetting = 1, + .iface_assoc = &dfu_assoc, + .altsetting = &dfu_iface, +#if defined(PLATFORM_HAS_TRACESWO) +}, { + .num_altsetting = 1, + .iface_assoc = &trace_assoc, + .altsetting = &trace_iface, +#endif +}}; + +static const struct usb_config_descriptor config = { + .bLength = USB_DT_CONFIGURATION_SIZE, + .bDescriptorType = USB_DT_CONFIGURATION, + .wTotalLength = 0, +#if defined(PLATFORM_HAS_TRACESWO) + .bNumInterfaces = 6, +#else + .bNumInterfaces = 5, +#endif + .bConfigurationValue = 1, + .iConfiguration = 0, + .bmAttributes = 0x80, + .bMaxPower = 0x32, + + .interface = ifaces, +}; + +char serial_no[9]; + +static const char *usb_strings[] = { + "Black Sphere Technologies", + BOARD_IDENT, + serial_no, + "Black Magic GDB Server", + "Black Magic UART Port", + DFU_IDENT, +#if defined(PLATFORM_HAS_TRACESWO) + "Black Magic Trace Capture", +#endif +}; + +static void dfu_detach_complete(usbd_device *dev, struct usb_setup_data *req) +{ + (void)dev; + (void)req; + + platform_request_boot(); + + /* Reset core to enter bootloader */ + scb_reset_core(); +} + +static int cdcacm_control_request(usbd_device *dev, + struct usb_setup_data *req, uint8_t **buf, uint16_t *len, + void (**complete)(usbd_device *dev, struct usb_setup_data *req)) +{ + (void)dev; + (void)complete; + (void)buf; + (void)len; + + switch(req->bRequest) { + case USB_CDC_REQ_SET_CONTROL_LINE_STATE: + /* Ignore if not for GDB interface */ + if(req->wIndex != 0) + return 1; + + cdcacm_gdb_dtr = req->wValue & 1; + + return 1; + case USB_CDC_REQ_SET_LINE_CODING: + if(*len < sizeof(struct usb_cdc_line_coding)) + return 0; + + switch(req->wIndex) { + case 2: + usbuart_set_line_coding((struct usb_cdc_line_coding*)*buf); + case 0: + return 1; /* Ignore on GDB Port */ + default: + return 0; + } + case DFU_GETSTATUS: + if(req->wIndex == DFU_IF_NO) { + (*buf)[0] = DFU_STATUS_OK; + (*buf)[1] = 0; + (*buf)[2] = 0; + (*buf)[3] = 0; + (*buf)[4] = STATE_APP_IDLE; + (*buf)[5] = 0; /* iString not used here */ + *len = 6; + + return 1; + } + case DFU_DETACH: + if(req->wIndex == DFU_IF_NO) { + *complete = dfu_detach_complete; + return 1; + } + return 0; + } + return 0; +} + +int cdcacm_get_config(void) +{ + return configured; +} + +int cdcacm_get_dtr(void) +{ + return cdcacm_gdb_dtr; +} + +static void cdcacm_set_config(usbd_device *dev, uint16_t wValue) +{ + configured = wValue; + + /* GDB interface */ +#ifdef STM32F4 + usbd_ep_setup(dev, 0x01, USB_ENDPOINT_ATTR_BULK, + CDCACM_PACKET_SIZE, gdb_usb_out_cb); +#else + usbd_ep_setup(dev, 0x01, USB_ENDPOINT_ATTR_BULK, + CDCACM_PACKET_SIZE, NULL); +#endif + usbd_ep_setup(dev, 0x81, USB_ENDPOINT_ATTR_BULK, + CDCACM_PACKET_SIZE, NULL); + usbd_ep_setup(dev, 0x82, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL); + + /* Serial interface */ + usbd_ep_setup(dev, 0x03, USB_ENDPOINT_ATTR_BULK, + CDCACM_PACKET_SIZE, usbuart_usb_out_cb); + usbd_ep_setup(dev, 0x83, USB_ENDPOINT_ATTR_BULK, + CDCACM_PACKET_SIZE, usbuart_usb_in_cb); + usbd_ep_setup(dev, 0x84, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL); + +#if defined(PLATFORM_HAS_TRACESWO) + /* Trace interface */ + usbd_ep_setup(dev, 0x85, USB_ENDPOINT_ATTR_BULK, + 64, trace_buf_drain); +#endif + + usbd_register_control_callback(dev, + USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE, + USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, + cdcacm_control_request); + + /* Notify the host that DCD is asserted. + * Allows the use of /dev/tty* devices on *BSD/MacOS + */ + char buf[10]; + struct usb_cdc_notification *notif = (void*)buf; + /* We echo signals back to host as notification */ + notif->bmRequestType = 0xA1; + notif->bNotification = USB_CDC_NOTIFY_SERIAL_STATE; + notif->wValue = 0; + notif->wIndex = 0; + notif->wLength = 2; + buf[8] = 3; /* DCD | DSR */ + buf[9] = 0; + usbd_ep_write_packet(dev, 0x82, buf, 10); + notif->wIndex = 2; + usbd_ep_write_packet(dev, 0x84, buf, 10); +} + +/* We need a special large control buffer for this device: */ +uint8_t usbd_control_buffer[256]; + +void cdcacm_init(void) +{ + void exti15_10_isr(void); + + serialno_read(serial_no); + + usbdev = usbd_init(&USB_DRIVER, &dev, &config, usb_strings, + sizeof(usb_strings)/sizeof(char *), + usbd_control_buffer, sizeof(usbd_control_buffer)); + + usbd_register_set_config_callback(usbdev, cdcacm_set_config); + + nvic_set_priority(USB_IRQ, IRQ_PRI_USB); + nvic_enable_irq(USB_IRQ); +} + +void USB_ISR(void) +{ + usbd_poll(usbdev); +} + diff --git a/src/platforms/common/serialno.h b/src/platforms/common/serialno.h new file mode 100644 index 0000000..946dc20 --- /dev/null +++ b/src/platforms/common/serialno.h @@ -0,0 +1,26 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2015 Black Sphere Technologies Ltd. + * Written by Gareth McMullin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * 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, see . + */ +#ifndef __SERIALNO_H +#define __SERIALNO_H + +char *serialno_read(char *s); + +#endif + diff --git a/src/platforms/f4discovery/Makefile.inc b/src/platforms/f4discovery/Makefile.inc index 88575bb..21b4078 100644 --- a/src/platforms/f4discovery/Makefile.inc +++ b/src/platforms/f4discovery/Makefile.inc @@ -19,6 +19,7 @@ SRC += cdcacm.c \ platform.c \ traceswo.c \ usbuart.c \ + serialno.c \ all: blackmagic.bin diff --git a/src/platforms/f4discovery/platform.c b/src/platforms/f4discovery/platform.c index cf6cdf3..6e10ff4 100644 --- a/src/platforms/f4discovery/platform.c +++ b/src/platforms/f4discovery/platform.c @@ -46,7 +46,7 @@ void platform_init(void) /* Check the USER button*/ rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPAEN); if(gpio_get(GPIOA, GPIO0)) { - assert_boot_pin(); + platform_request_boot(); scb_reset_core(); } @@ -111,8 +111,12 @@ const char *platform_target_voltage(void) return "ABSENT!"; } -void assert_boot_pin(void) +void platform_request_boot(void) { + /* Disconnect USB cable */ + usbd_disconnect(usbdev, 1); + nvic_disable_irq(USB_IRQ); + /* Assert blue LED as indicator we are in the bootloader */ rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPDEN); gpio_mode_setup(LED_PORT, GPIO_MODE_OUTPUT, diff --git a/src/platforms/f4discovery/platform.h b/src/platforms/f4discovery/platform.h index f58205d..61753af 100644 --- a/src/platforms/f4discovery/platform.h +++ b/src/platforms/f4discovery/platform.h @@ -176,9 +176,5 @@ static inline int platform_hwversion(void) #define sprintf siprintf #define vasprintf vasiprintf -#define disconnect_usb() do {usbd_disconnect(usbdev,1); nvic_disable_irq(USB_IRQ);} while(0) -void assert_boot_pin(void); -#define setup_vbus_irq() - #endif diff --git a/src/platforms/launchpad-icdi/platform.c b/src/platforms/launchpad-icdi/platform.c index 0e3fb85..e689f0c 100644 --- a/src/platforms/launchpad-icdi/platform.c +++ b/src/platforms/launchpad-icdi/platform.c @@ -1,3 +1,19 @@ +/* + * This file is part of the Black Magic Debug project. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * 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, see . + */ #include "general.h" #include "gdb_if.h" #include "cdcacm.h" @@ -7,6 +23,7 @@ #include #include #include +#include #define SYSTICKHZ 100 #define SYSTICKMS (1000 / SYSTICKHZ) @@ -58,6 +75,13 @@ platform_init(void) nvic_enable_irq(NVIC_SYSTICK_IRQ); nvic_enable_irq(NVIC_UART0_IRQ); + periph_clock_enable(RCC_GPIOD); + __asm__("nop"); __asm__("nop"); __asm__("nop"); + gpio_mode_setup(GPIOD_BASE, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO4|GPIO5); + usb_enable_interrupts(USB_INT_RESET | USB_INT_DISCON | + USB_INT_RESUME | USB_INT_SUSPEND, + 0xff, 0xff); + usbuart_init(); cdcacm_init(); } @@ -73,3 +97,25 @@ const char *platform_target_voltage(void) return "not supported"; } +char *serialno_read(char *s) +{ + /* FIXME: Store a unique serial number somewhere and retreive here */ + uint32_t unique_id = 1; + int i; + + /* Fetch serial number from chip's unique ID */ + for(i = 0; i < 8; i++) { + s[7-i] = ((unique_id >> (4*i)) & 0xF) + '0'; + } + for(i = 0; i < 8; i++) + if(s[i] > '9') + s[i] += 'A' - '9' - 1; + s[8] = 0; + + return s; +} + +void platform_request_boot(void) +{ +} + diff --git a/src/platforms/launchpad-icdi/platform.h b/src/platforms/launchpad-icdi/platform.h index 5f686f4..eb3ac6e 100644 --- a/src/platforms/launchpad-icdi/platform.h +++ b/src/platforms/launchpad-icdi/platform.h @@ -1,3 +1,19 @@ +/* + * This file is part of the Black Magic Debug project. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * 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, see . + */ #ifndef __PLATFORM_H #define __PLATFORM_H @@ -8,16 +24,11 @@ #include #include -#define CDCACM_PACKET_SIZE 64 #define BOARD_IDENT "Black Magic Probe (Launchpad ICDI), (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" #define BOARD_IDENT_DFU "Black Magic (Upgrade) for Launchpad, (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" #define DFU_IDENT "Black Magic Firmware Upgrade (Launchpad)" #define DFU_IFACE_STRING "lolwut" -extern usbd_device *usbdev; -#define CDCACM_GDB_ENDPOINT 1 -#define CDCACM_UART_ENDPOINT 3 - extern jmp_buf fatal_error_jmpbuf; extern uint8_t running_status; extern volatile uint32_t timeout_counter; @@ -116,6 +127,5 @@ inline static uint8_t gpio_get(uint32_t port, uint8_t pin) { } #define disconnect_usb() do { usbd_disconnect(usbdev,1); nvic_disable_irq(USB_IRQ);} while(0) -#define setup_vbus_irq() #endif diff --git a/src/platforms/native/Makefile.inc b/src/platforms/native/Makefile.inc index cc4da0b..2270ff5 100644 --- a/src/platforms/native/Makefile.inc +++ b/src/platforms/native/Makefile.inc @@ -18,6 +18,7 @@ SRC += cdcacm.c \ platform.c \ traceswo.c \ usbuart.c \ + serialno.c \ all: blackmagic.bin blackmagic_dfu.bin blackmagic_dfu.hex diff --git a/src/platforms/native/platform.c b/src/platforms/native/platform.c index 9b39238..5c28747 100644 --- a/src/platforms/native/platform.c +++ b/src/platforms/native/platform.c @@ -42,6 +42,7 @@ volatile uint32_t timeout_counter; jmp_buf fatal_error_jmpbuf; static void adc_init(void); +static void setup_vbus_irq(void); /* Pins PB[7:5] are used to detect hardware revision. * 000 - Original production build. @@ -134,6 +135,7 @@ void platform_init(void) cdcacm_init(); usbuart_init(); + setup_vbus_irq(); } void platform_srst_set_val(bool assert) @@ -221,8 +223,12 @@ const char *platform_target_voltage(void) return ret; } -void assert_boot_pin(void) +void platform_request_boot(void) { + /* Disconnect USB cable */ + gpio_set_mode(USB_PU_PORT, GPIO_MODE_INPUT, 0, USB_PU_PIN); + + /* Drive boot request pin */ gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO12); gpio_clear(GPIOB, GPIO12); @@ -243,7 +249,7 @@ void exti15_10_isr(void) exti_reset_request(USB_VBUS_PIN); } -void setup_vbus_irq(void) +static void setup_vbus_irq(void) { nvic_set_priority(USB_VBUS_IRQ, IRQ_PRI_USB_VBUS); nvic_enable_irq(USB_VBUS_IRQ); diff --git a/src/platforms/native/platform.h b/src/platforms/native/platform.h index 5688e60..c0b4dba 100644 --- a/src/platforms/native/platform.h +++ b/src/platforms/native/platform.h @@ -170,9 +170,5 @@ extern jmp_buf fatal_error_jmpbuf; #define sprintf siprintf #define vasprintf vasiprintf -#define disconnect_usb() gpio_set_mode(USB_PU_PORT, GPIO_MODE_INPUT, 0, USB_PU_PIN); -void assert_boot_pin(void); -void setup_vbus_irq(void); - #endif diff --git a/src/platforms/stlink/Makefile.inc b/src/platforms/stlink/Makefile.inc index 5cfe726..52ad33b 100644 --- a/src/platforms/stlink/Makefile.inc +++ b/src/platforms/stlink/Makefile.inc @@ -16,7 +16,8 @@ VPATH += platforms/stm32 SRC += cdcacm.c \ platform.c \ - usbuart.c \ + usbuart.c \ + serialno.c \ all: blackmagic.bin blackmagic_dfu.bin blackmagic_dfu.hex dfu_upgrade.bin dfu_upgrade.hex diff --git a/src/platforms/stlink/platform.c b/src/platforms/stlink/platform.c index 6194d92..446fb47 100644 --- a/src/platforms/stlink/platform.c +++ b/src/platforms/stlink/platform.c @@ -149,7 +149,7 @@ const char *platform_target_voltage(void) return "unknown"; } -void disconnect_usb(void) +void platform_request_boot(void) { /* Disconnect USB cable by resetting USB Device and pulling USB_DP low*/ rcc_periph_reset_pulse(RST_USB); @@ -158,10 +158,8 @@ void disconnect_usb(void) gpio_clear(GPIOA, GPIO12); gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO12); -} -void assert_boot_pin(void) -{ + /* Assert bootloader pin */ uint32_t crl = GPIOA_CRL; rcc_periph_clock_enable(RCC_GPIOA); /* Enable Pull on GPIOA1. We don't rely on the external pin @@ -173,7 +171,3 @@ void assert_boot_pin(void) GPIOA_CRL = crl; } -void setup_vbus_irq(void) -{ -} - diff --git a/src/platforms/stlink/platform.h b/src/platforms/stlink/platform.h index 5768817..fcbe259 100644 --- a/src/platforms/stlink/platform.h +++ b/src/platforms/stlink/platform.h @@ -152,9 +152,5 @@ extern uint16_t led_idle_run; #define sprintf siprintf #define vasprintf vasiprintf -void disconnect_usb(void); -void assert_boot_pin(void); -void setup_vbus_irq(void); - #endif diff --git a/src/platforms/stm32/cdcacm.c b/src/platforms/stm32/cdcacm.c deleted file mode 100644 index 577925a..0000000 --- a/src/platforms/stm32/cdcacm.c +++ /dev/null @@ -1,583 +0,0 @@ -/* - * This file is part of the Black Magic Debug project. - * - * Copyright (C) 2011 Black Sphere Technologies Ltd. - * Written by Gareth McMullin - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * 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, see . - */ - -/* This file implements a the USB Communications Device Class - Abstract - * Control Model (CDC-ACM) as defined in CDC PSTN subclass 1.2. - * A Device Firmware Upgrade (DFU 1.1) class interface is provided for - * field firmware upgrade. - * - * The device's unique id is used as the USB serial number string. - */ - -#include -#include -#include -#include -#include -#include - -#include "general.h" -#include "gdb_if.h" -#include "cdcacm.h" -#if defined(PLATFORM_HAS_TRACESWO) -#include "traceswo.h" -#endif -#include "usbuart.h" - -#define DFU_IF_NO 4 - -usbd_device * usbdev; - -static char *get_dev_unique_id(char *serial_no); - -static int configured; -static int cdcacm_gdb_dtr = 1; - - -static const struct usb_device_descriptor dev = { - .bLength = USB_DT_DEVICE_SIZE, - .bDescriptorType = USB_DT_DEVICE, - .bcdUSB = 0x0200, - .bDeviceClass = 0xEF, /* Miscellaneous Device */ - .bDeviceSubClass = 2, /* Common Class */ - .bDeviceProtocol = 1, /* Interface Association */ - .bMaxPacketSize0 = 64, - .idVendor = 0x1D50, - .idProduct = 0x6018, - .bcdDevice = 0x0100, - .iManufacturer = 1, - .iProduct = 2, - .iSerialNumber = 3, - .bNumConfigurations = 1, -}; - -/* This notification endpoint isn't implemented. According to CDC spec its - * optional, but its absence causes a NULL pointer dereference in Linux cdc_acm - * driver. */ -static const struct usb_endpoint_descriptor gdb_comm_endp[] = {{ - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 0x82, - .bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT, - .wMaxPacketSize = 16, - .bInterval = 255, -}}; - -static const struct usb_endpoint_descriptor gdb_data_endp[] = {{ - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 0x01, - .bmAttributes = USB_ENDPOINT_ATTR_BULK, - .wMaxPacketSize = CDCACM_PACKET_SIZE, - .bInterval = 1, -}, { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 0x81, - .bmAttributes = USB_ENDPOINT_ATTR_BULK, - .wMaxPacketSize = CDCACM_PACKET_SIZE, - .bInterval = 1, -}}; - -static const struct { - struct usb_cdc_header_descriptor header; - struct usb_cdc_call_management_descriptor call_mgmt; - struct usb_cdc_acm_descriptor acm; - struct usb_cdc_union_descriptor cdc_union; -} __attribute__((packed)) gdb_cdcacm_functional_descriptors = { - .header = { - .bFunctionLength = sizeof(struct usb_cdc_header_descriptor), - .bDescriptorType = CS_INTERFACE, - .bDescriptorSubtype = USB_CDC_TYPE_HEADER, - .bcdCDC = 0x0110, - }, - .call_mgmt = { - .bFunctionLength = - sizeof(struct usb_cdc_call_management_descriptor), - .bDescriptorType = CS_INTERFACE, - .bDescriptorSubtype = USB_CDC_TYPE_CALL_MANAGEMENT, - .bmCapabilities = 0, - .bDataInterface = 1, - }, - .acm = { - .bFunctionLength = sizeof(struct usb_cdc_acm_descriptor), - .bDescriptorType = CS_INTERFACE, - .bDescriptorSubtype = USB_CDC_TYPE_ACM, - .bmCapabilities = 2, /* SET_LINE_CODING supported */ - }, - .cdc_union = { - .bFunctionLength = sizeof(struct usb_cdc_union_descriptor), - .bDescriptorType = CS_INTERFACE, - .bDescriptorSubtype = USB_CDC_TYPE_UNION, - .bControlInterface = 0, - .bSubordinateInterface0 = 1, - } -}; - -static const struct usb_interface_descriptor gdb_comm_iface[] = {{ - .bLength = USB_DT_INTERFACE_SIZE, - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = 0, - .bAlternateSetting = 0, - .bNumEndpoints = 1, - .bInterfaceClass = USB_CLASS_CDC, - .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, - .bInterfaceProtocol = USB_CDC_PROTOCOL_AT, - .iInterface = 4, - - .endpoint = gdb_comm_endp, - - .extra = &gdb_cdcacm_functional_descriptors, - .extralen = sizeof(gdb_cdcacm_functional_descriptors) -}}; - -static const struct usb_interface_descriptor gdb_data_iface[] = {{ - .bLength = USB_DT_INTERFACE_SIZE, - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = 1, - .bAlternateSetting = 0, - .bNumEndpoints = 2, - .bInterfaceClass = USB_CLASS_DATA, - .bInterfaceSubClass = 0, - .bInterfaceProtocol = 0, - .iInterface = 0, - - .endpoint = gdb_data_endp, -}}; - -static const struct usb_iface_assoc_descriptor gdb_assoc = { - .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE, - .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, - .bFirstInterface = 0, - .bInterfaceCount = 2, - .bFunctionClass = USB_CLASS_CDC, - .bFunctionSubClass = USB_CDC_SUBCLASS_ACM, - .bFunctionProtocol = USB_CDC_PROTOCOL_AT, - .iFunction = 0, -}; - -/* Serial ACM interface */ -static const struct usb_endpoint_descriptor uart_comm_endp[] = {{ - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 0x84, - .bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT, - .wMaxPacketSize = 16, - .bInterval = 255, -}}; - -static const struct usb_endpoint_descriptor uart_data_endp[] = {{ - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 0x03, - .bmAttributes = USB_ENDPOINT_ATTR_BULK, - .wMaxPacketSize = CDCACM_PACKET_SIZE, - .bInterval = 1, -}, { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 0x83, - .bmAttributes = USB_ENDPOINT_ATTR_BULK, - .wMaxPacketSize = CDCACM_PACKET_SIZE, - .bInterval = 1, -}}; - -static const struct { - struct usb_cdc_header_descriptor header; - struct usb_cdc_call_management_descriptor call_mgmt; - struct usb_cdc_acm_descriptor acm; - struct usb_cdc_union_descriptor cdc_union; -} __attribute__((packed)) uart_cdcacm_functional_descriptors = { - .header = { - .bFunctionLength = sizeof(struct usb_cdc_header_descriptor), - .bDescriptorType = CS_INTERFACE, - .bDescriptorSubtype = USB_CDC_TYPE_HEADER, - .bcdCDC = 0x0110, - }, - .call_mgmt = { - .bFunctionLength = - sizeof(struct usb_cdc_call_management_descriptor), - .bDescriptorType = CS_INTERFACE, - .bDescriptorSubtype = USB_CDC_TYPE_CALL_MANAGEMENT, - .bmCapabilities = 0, - .bDataInterface = 3, - }, - .acm = { - .bFunctionLength = sizeof(struct usb_cdc_acm_descriptor), - .bDescriptorType = CS_INTERFACE, - .bDescriptorSubtype = USB_CDC_TYPE_ACM, - .bmCapabilities = 2, /* SET_LINE_CODING supported*/ - }, - .cdc_union = { - .bFunctionLength = sizeof(struct usb_cdc_union_descriptor), - .bDescriptorType = CS_INTERFACE, - .bDescriptorSubtype = USB_CDC_TYPE_UNION, - .bControlInterface = 2, - .bSubordinateInterface0 = 3, - } -}; - -static const struct usb_interface_descriptor uart_comm_iface[] = {{ - .bLength = USB_DT_INTERFACE_SIZE, - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = 2, - .bAlternateSetting = 0, - .bNumEndpoints = 1, - .bInterfaceClass = USB_CLASS_CDC, - .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, - .bInterfaceProtocol = USB_CDC_PROTOCOL_AT, - .iInterface = 5, - - .endpoint = uart_comm_endp, - - .extra = &uart_cdcacm_functional_descriptors, - .extralen = sizeof(uart_cdcacm_functional_descriptors) -}}; - -static const struct usb_interface_descriptor uart_data_iface[] = {{ - .bLength = USB_DT_INTERFACE_SIZE, - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = 3, - .bAlternateSetting = 0, - .bNumEndpoints = 2, - .bInterfaceClass = USB_CLASS_DATA, - .bInterfaceSubClass = 0, - .bInterfaceProtocol = 0, - .iInterface = 0, - - .endpoint = uart_data_endp, -}}; - -static const struct usb_iface_assoc_descriptor uart_assoc = { - .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE, - .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, - .bFirstInterface = 2, - .bInterfaceCount = 2, - .bFunctionClass = USB_CLASS_CDC, - .bFunctionSubClass = USB_CDC_SUBCLASS_ACM, - .bFunctionProtocol = USB_CDC_PROTOCOL_AT, - .iFunction = 0, -}; - -const struct usb_dfu_descriptor dfu_function = { - .bLength = sizeof(struct usb_dfu_descriptor), - .bDescriptorType = DFU_FUNCTIONAL, - .bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_WILL_DETACH, - .wDetachTimeout = 255, - .wTransferSize = 1024, - .bcdDFUVersion = 0x011A, -}; - -const struct usb_interface_descriptor dfu_iface = { - .bLength = USB_DT_INTERFACE_SIZE, - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = DFU_IF_NO, - .bAlternateSetting = 0, - .bNumEndpoints = 0, - .bInterfaceClass = 0xFE, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 1, - .iInterface = 6, - - .extra = &dfu_function, - .extralen = sizeof(dfu_function), -}; - -static const struct usb_iface_assoc_descriptor dfu_assoc = { - .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE, - .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, - .bFirstInterface = 4, - .bInterfaceCount = 1, - .bFunctionClass = 0xFE, - .bFunctionSubClass = 1, - .bFunctionProtocol = 1, - .iFunction = 6, -}; - -#if defined(PLATFORM_HAS_TRACESWO) -static const struct usb_endpoint_descriptor trace_endp[] = {{ - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 0x85, - .bmAttributes = USB_ENDPOINT_ATTR_BULK, - .wMaxPacketSize = 64, - .bInterval = 0, -}}; - -const struct usb_interface_descriptor trace_iface = { - .bLength = USB_DT_INTERFACE_SIZE, - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = 5, - .bAlternateSetting = 0, - .bNumEndpoints = 1, - .bInterfaceClass = 0xFF, - .bInterfaceSubClass = 0xFF, - .bInterfaceProtocol = 0xFF, - .iInterface = 7, - - .endpoint = trace_endp, -}; - -static const struct usb_iface_assoc_descriptor trace_assoc = { - .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE, - .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, - .bFirstInterface = 5, - .bInterfaceCount = 1, - .bFunctionClass = 0xFF, - .bFunctionSubClass = 0xFF, - .bFunctionProtocol = 0xFF, - .iFunction = 7, -}; -#endif - -static const struct usb_interface ifaces[] = {{ - .num_altsetting = 1, - .iface_assoc = &gdb_assoc, - .altsetting = gdb_comm_iface, -}, { - .num_altsetting = 1, - .altsetting = gdb_data_iface, -}, { - .num_altsetting = 1, - .iface_assoc = &uart_assoc, - .altsetting = uart_comm_iface, -}, { - .num_altsetting = 1, - .altsetting = uart_data_iface, -}, { - .num_altsetting = 1, - .iface_assoc = &dfu_assoc, - .altsetting = &dfu_iface, -#if defined(PLATFORM_HAS_TRACESWO) -}, { - .num_altsetting = 1, - .iface_assoc = &trace_assoc, - .altsetting = &trace_iface, -#endif -}}; - -static const struct usb_config_descriptor config = { - .bLength = USB_DT_CONFIGURATION_SIZE, - .bDescriptorType = USB_DT_CONFIGURATION, - .wTotalLength = 0, -#if defined(PLATFORM_HAS_TRACESWO) - .bNumInterfaces = 6, -#else - .bNumInterfaces = 5, -#endif - .bConfigurationValue = 1, - .iConfiguration = 0, - .bmAttributes = 0x80, - .bMaxPower = 0x32, - - .interface = ifaces, -}; - -char serial_no[9]; - -static const char *usb_strings[] = { - "Black Sphere Technologies", - BOARD_IDENT, - serial_no, - "Black Magic GDB Server", - "Black Magic UART Port", - DFU_IDENT, -#if defined(PLATFORM_HAS_TRACESWO) - "Black Magic Trace Capture", -#endif -}; - -static void dfu_detach_complete(usbd_device *dev, struct usb_setup_data *req) -{ - (void)dev; - (void)req; - - /* Disconnect USB cable */ - disconnect_usb(); - - /* Assert boot-request pin */ - assert_boot_pin(); - - /* Reset core to enter bootloader */ - scb_reset_core(); -} - -static int cdcacm_control_request(usbd_device *dev, - struct usb_setup_data *req, uint8_t **buf, uint16_t *len, - void (**complete)(usbd_device *dev, struct usb_setup_data *req)) -{ - (void)dev; - (void)complete; - (void)buf; - (void)len; - - switch(req->bRequest) { - case USB_CDC_REQ_SET_CONTROL_LINE_STATE: - /* Ignore if not for GDB interface */ - if(req->wIndex != 0) - return 1; - - cdcacm_gdb_dtr = req->wValue & 1; - - return 1; - case USB_CDC_REQ_SET_LINE_CODING: - if(*len < sizeof(struct usb_cdc_line_coding)) - return 0; - - switch(req->wIndex) { - case 2: - usbuart_set_line_coding((struct usb_cdc_line_coding*)*buf); - case 0: - return 1; /* Ignore on GDB Port */ - default: - return 0; - } - case DFU_GETSTATUS: - if(req->wIndex == DFU_IF_NO) { - (*buf)[0] = DFU_STATUS_OK; - (*buf)[1] = 0; - (*buf)[2] = 0; - (*buf)[3] = 0; - (*buf)[4] = STATE_APP_IDLE; - (*buf)[5] = 0; /* iString not used here */ - *len = 6; - - return 1; - } - case DFU_DETACH: - if(req->wIndex == DFU_IF_NO) { - *complete = dfu_detach_complete; - return 1; - } - return 0; - } - return 0; -} - -int cdcacm_get_config(void) -{ - return configured; -} - -int cdcacm_get_dtr(void) -{ - return cdcacm_gdb_dtr; -} - -static void cdcacm_set_config(usbd_device *dev, uint16_t wValue) -{ - configured = wValue; - - /* GDB interface */ -#ifdef STM32F4 - usbd_ep_setup(dev, 0x01, USB_ENDPOINT_ATTR_BULK, - CDCACM_PACKET_SIZE, gdb_usb_out_cb); -#else - usbd_ep_setup(dev, 0x01, USB_ENDPOINT_ATTR_BULK, - CDCACM_PACKET_SIZE, NULL); -#endif - usbd_ep_setup(dev, 0x81, USB_ENDPOINT_ATTR_BULK, - CDCACM_PACKET_SIZE, NULL); - usbd_ep_setup(dev, 0x82, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL); - - /* Serial interface */ - usbd_ep_setup(dev, 0x03, USB_ENDPOINT_ATTR_BULK, - CDCACM_PACKET_SIZE, usbuart_usb_out_cb); - usbd_ep_setup(dev, 0x83, USB_ENDPOINT_ATTR_BULK, - CDCACM_PACKET_SIZE, usbuart_usb_in_cb); - usbd_ep_setup(dev, 0x84, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL); - -#if defined(PLATFORM_HAS_TRACESWO) - /* Trace interface */ - usbd_ep_setup(dev, 0x85, USB_ENDPOINT_ATTR_BULK, - 64, trace_buf_drain); -#endif - - usbd_register_control_callback(dev, - USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE, - USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, - cdcacm_control_request); - - /* Notify the host that DCD is asserted. - * Allows the use of /dev/tty* devices on *BSD/MacOS - */ - char buf[10]; - struct usb_cdc_notification *notif = (void*)buf; - /* We echo signals back to host as notification */ - notif->bmRequestType = 0xA1; - notif->bNotification = USB_CDC_NOTIFY_SERIAL_STATE; - notif->wValue = 0; - notif->wIndex = 0; - notif->wLength = 2; - buf[8] = 3; /* DCD | DSR */ - buf[9] = 0; - usbd_ep_write_packet(dev, 0x82, buf, 10); - notif->wIndex = 2; - usbd_ep_write_packet(dev, 0x84, buf, 10); -} - -/* We need a special large control buffer for this device: */ -uint8_t usbd_control_buffer[256]; - -void cdcacm_init(void) -{ - void exti15_10_isr(void); - - get_dev_unique_id(serial_no); - - usbdev = usbd_init(&USB_DRIVER, &dev, &config, usb_strings, - sizeof(usb_strings)/sizeof(char *), - usbd_control_buffer, sizeof(usbd_control_buffer)); - - usbd_register_set_config_callback(usbdev, cdcacm_set_config); - - nvic_set_priority(USB_IRQ, IRQ_PRI_USB); - nvic_enable_irq(USB_IRQ); - setup_vbus_irq(); -} - -void USB_ISR(void) -{ - usbd_poll(usbdev); -} - -static char *get_dev_unique_id(char *s) -{ -#if defined(STM32F4) - volatile uint32_t *unique_id_p = (volatile uint32_t *)0x1FFF7A10; -#else - volatile uint32_t *unique_id_p = (volatile uint32_t *)0x1FFFF7E8; -#endif - uint32_t unique_id = *unique_id_p + - *(unique_id_p + 1) + - *(unique_id_p + 2); - int i; - - /* Fetch serial number from chip's unique ID */ - for(i = 0; i < 8; i++) { - s[7-i] = ((unique_id >> (4*i)) & 0xF) + '0'; - } - for(i = 0; i < 8; i++) - if(s[i] > '9') - s[i] += 'A' - '9' - 1; - s[8] = 0; - - return s; -} diff --git a/src/platforms/stm32/serialno.c b/src/platforms/stm32/serialno.c new file mode 100644 index 0000000..ef28ed2 --- /dev/null +++ b/src/platforms/stm32/serialno.c @@ -0,0 +1,45 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2015 Black Sphere Technologies Ltd. + * Written by Gareth McMullin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * 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, see . + */ +#include "general.h" + +char *serialno_read(char *s) +{ +#if defined(STM32F4) + volatile uint32_t *unique_id_p = (volatile uint32_t *)0x1FFF7A10; +#else + volatile uint32_t *unique_id_p = (volatile uint32_t *)0x1FFFF7E8; +#endif + uint32_t unique_id = *unique_id_p + + *(unique_id_p + 1) + + *(unique_id_p + 2); + int i; + + /* Fetch serial number from chip's unique ID */ + for(i = 0; i < 8; i++) { + s[7-i] = ((unique_id >> (4*i)) & 0xF) + '0'; + } + for(i = 0; i < 8; i++) + if(s[i] > '9') + s[i] += 'A' - '9' - 1; + s[8] = 0; + + return s; +} + diff --git a/src/platforms/swlink/Makefile.inc b/src/platforms/swlink/Makefile.inc index ff349db..b68b1ab 100644 --- a/src/platforms/swlink/Makefile.inc +++ b/src/platforms/swlink/Makefile.inc @@ -16,7 +16,8 @@ VPATH += platforms/stm32 SRC += cdcacm.c \ platform.c \ - usbuart.c \ + usbuart.c \ + serialno.c \ all: blackmagic.bin blackmagic_dfu.bin blackmagic_dfu.hex diff --git a/src/platforms/swlink/platform.c b/src/platforms/swlink/platform.c index 168ba2a..1b9a76e 100644 --- a/src/platforms/swlink/platform.c +++ b/src/platforms/swlink/platform.c @@ -118,7 +118,7 @@ const char *platform_target_voltage(void) return "unknown"; } -void disconnect_usb(void) +void platform_request_boot(void) { /* Disconnect USB cable by resetting USB Device and pulling USB_DP low*/ rcc_periph_reset_pulse(RST_USB); @@ -127,10 +127,8 @@ void disconnect_usb(void) gpio_clear(GPIOA, GPIO12); gpio_set_mode(GPIOA, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO12); -} -void assert_boot_pin(void) -{ + /* Assert bootloader pin */ uint32_t crl = GPIOA_CRL; rcc_periph_clock_enable(RCC_GPIOA); /* Enable Pull on GPIOA1. We don't rely on the external pin @@ -141,4 +139,4 @@ void assert_boot_pin(void) crl |= 0x80; GPIOA_CRL = crl; } -void setup_vbus_irq(void){}; + diff --git a/src/platforms/swlink/platform.h b/src/platforms/swlink/platform.h index dec5548..6ee4a9c 100644 --- a/src/platforms/swlink/platform.h +++ b/src/platforms/swlink/platform.h @@ -146,8 +146,5 @@ extern jmp_buf fatal_error_jmpbuf; #define sprintf siprintf #define vasprintf vasiprintf -void disconnect_usb(void); -void assert_boot_pin(void); - #endif diff --git a/src/platforms/tm4c/cdcacm.c b/src/platforms/tm4c/cdcacm.c deleted file mode 100644 index 2677ad5..0000000 --- a/src/platforms/tm4c/cdcacm.c +++ /dev/null @@ -1,577 +0,0 @@ -/* - * This file is part of the Black Magic Debug project. - * - * Copyright (C) 2011 Black Sphere Technologies Ltd. - * Written by Gareth McMullin - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * 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, see . - */ - -/* This file implements a the USB Communications Device Class - Abstract - * Control Model (CDC-ACM) as defined in CDC PSTN subclass 1.2. - * A Device Firmware Upgrade (DFU 1.1) class interface is provided for - * field firmware upgrade. - * - * The device's unique id is used as the USB serial number string. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "general.h" -#include "gdb_if.h" -#if defined(PLATFORM_HAS_TRACESWO) -#include -#endif -#include - -#define DFU_IF_NO 4 - -usbd_device * usbdev; - -static char *get_dev_unique_id(char *serial_no); - -static int configured; -static int cdcacm_gdb_dtr = 1; - - -static const struct usb_device_descriptor dev = { - .bLength = USB_DT_DEVICE_SIZE, - .bDescriptorType = USB_DT_DEVICE, - .bcdUSB = 0x0200, - .bDeviceClass = 0xEF, /* Miscellaneous Device */ - .bDeviceSubClass = 2, /* Common Class */ - .bDeviceProtocol = 1, /* Interface Association */ - .bMaxPacketSize0 = 64, - .idVendor = 0x1D50, - .idProduct = 0x6018, - .bcdDevice = 0x0100, - .iManufacturer = 1, - .iProduct = 2, - .iSerialNumber = 3, - .bNumConfigurations = 1, -}; - -/* This notification endpoint isn't implemented. According to CDC spec its - * optional, but its absence causes a NULL pointer dereference in Linux cdc_acm - * driver. */ -static const struct usb_endpoint_descriptor gdb_comm_endp[] = {{ - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 0x82, - .bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT, - .wMaxPacketSize = 16, - .bInterval = 255, -}}; - -static const struct usb_endpoint_descriptor gdb_data_endp[] = {{ - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 0x01, - .bmAttributes = USB_ENDPOINT_ATTR_BULK, - .wMaxPacketSize = CDCACM_PACKET_SIZE, - .bInterval = 1, -}, { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 0x81, - .bmAttributes = USB_ENDPOINT_ATTR_BULK, - .wMaxPacketSize = CDCACM_PACKET_SIZE, - .bInterval = 1, -}}; - -static const struct { - struct usb_cdc_header_descriptor header; - struct usb_cdc_call_management_descriptor call_mgmt; - struct usb_cdc_acm_descriptor acm; - struct usb_cdc_union_descriptor cdc_union; -} __attribute__((packed)) gdb_cdcacm_functional_descriptors = { - .header = { - .bFunctionLength = sizeof(struct usb_cdc_header_descriptor), - .bDescriptorType = CS_INTERFACE, - .bDescriptorSubtype = USB_CDC_TYPE_HEADER, - .bcdCDC = 0x0110, - }, - .call_mgmt = { - .bFunctionLength = - sizeof(struct usb_cdc_call_management_descriptor), - .bDescriptorType = CS_INTERFACE, - .bDescriptorSubtype = USB_CDC_TYPE_CALL_MANAGEMENT, - .bmCapabilities = 0, - .bDataInterface = 1, - }, - .acm = { - .bFunctionLength = sizeof(struct usb_cdc_acm_descriptor), - .bDescriptorType = CS_INTERFACE, - .bDescriptorSubtype = USB_CDC_TYPE_ACM, - .bmCapabilities = 2, /* SET_LINE_CODING supported */ - }, - .cdc_union = { - .bFunctionLength = sizeof(struct usb_cdc_union_descriptor), - .bDescriptorType = CS_INTERFACE, - .bDescriptorSubtype = USB_CDC_TYPE_UNION, - .bControlInterface = 0, - .bSubordinateInterface0 = 1, - } -}; - -static const struct usb_interface_descriptor gdb_comm_iface[] = {{ - .bLength = USB_DT_INTERFACE_SIZE, - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = 0, - .bAlternateSetting = 0, - .bNumEndpoints = 1, - .bInterfaceClass = USB_CLASS_CDC, - .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, - .bInterfaceProtocol = USB_CDC_PROTOCOL_AT, - .iInterface = 4, - - .endpoint = gdb_comm_endp, - - .extra = &gdb_cdcacm_functional_descriptors, - .extralen = sizeof(gdb_cdcacm_functional_descriptors) -}}; - -static const struct usb_interface_descriptor gdb_data_iface[] = {{ - .bLength = USB_DT_INTERFACE_SIZE, - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = 1, - .bAlternateSetting = 0, - .bNumEndpoints = 2, - .bInterfaceClass = USB_CLASS_DATA, - .bInterfaceSubClass = 0, - .bInterfaceProtocol = 0, - .iInterface = 0, - - .endpoint = gdb_data_endp, -}}; - -static const struct usb_iface_assoc_descriptor gdb_assoc = { - .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE, - .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, - .bFirstInterface = 0, - .bInterfaceCount = 2, - .bFunctionClass = USB_CLASS_CDC, - .bFunctionSubClass = USB_CDC_SUBCLASS_ACM, - .bFunctionProtocol = USB_CDC_PROTOCOL_AT, - .iFunction = 0, -}; - -/* Serial ACM interface */ -static const struct usb_endpoint_descriptor uart_comm_endp[] = {{ - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 0x84, - .bmAttributes = USB_ENDPOINT_ATTR_INTERRUPT, - .wMaxPacketSize = 16, - .bInterval = 255, -}}; - -static const struct usb_endpoint_descriptor uart_data_endp[] = {{ - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 0x03, - .bmAttributes = USB_ENDPOINT_ATTR_BULK, - .wMaxPacketSize = CDCACM_PACKET_SIZE, - .bInterval = 1, -}, { - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 0x83, - .bmAttributes = USB_ENDPOINT_ATTR_BULK, - .wMaxPacketSize = CDCACM_PACKET_SIZE, - .bInterval = 1, -}}; - -static const struct { - struct usb_cdc_header_descriptor header; - struct usb_cdc_call_management_descriptor call_mgmt; - struct usb_cdc_acm_descriptor acm; - struct usb_cdc_union_descriptor cdc_union; -} __attribute__((packed)) uart_cdcacm_functional_descriptors = { - .header = { - .bFunctionLength = sizeof(struct usb_cdc_header_descriptor), - .bDescriptorType = CS_INTERFACE, - .bDescriptorSubtype = USB_CDC_TYPE_HEADER, - .bcdCDC = 0x0110, - }, - .call_mgmt = { - .bFunctionLength = - sizeof(struct usb_cdc_call_management_descriptor), - .bDescriptorType = CS_INTERFACE, - .bDescriptorSubtype = USB_CDC_TYPE_CALL_MANAGEMENT, - .bmCapabilities = 0, - .bDataInterface = 3, - }, - .acm = { - .bFunctionLength = sizeof(struct usb_cdc_acm_descriptor), - .bDescriptorType = CS_INTERFACE, - .bDescriptorSubtype = USB_CDC_TYPE_ACM, - .bmCapabilities = 2, /* SET_LINE_CODING supported*/ - }, - .cdc_union = { - .bFunctionLength = sizeof(struct usb_cdc_union_descriptor), - .bDescriptorType = CS_INTERFACE, - .bDescriptorSubtype = USB_CDC_TYPE_UNION, - .bControlInterface = 2, - .bSubordinateInterface0 = 3, - } -}; - -static const struct usb_interface_descriptor uart_comm_iface[] = {{ - .bLength = USB_DT_INTERFACE_SIZE, - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = 2, - .bAlternateSetting = 0, - .bNumEndpoints = 1, - .bInterfaceClass = USB_CLASS_CDC, - .bInterfaceSubClass = USB_CDC_SUBCLASS_ACM, - .bInterfaceProtocol = USB_CDC_PROTOCOL_AT, - .iInterface = 5, - - .endpoint = uart_comm_endp, - - .extra = &uart_cdcacm_functional_descriptors, - .extralen = sizeof(uart_cdcacm_functional_descriptors) -}}; - -static const struct usb_interface_descriptor uart_data_iface[] = {{ - .bLength = USB_DT_INTERFACE_SIZE, - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = 3, - .bAlternateSetting = 0, - .bNumEndpoints = 2, - .bInterfaceClass = USB_CLASS_DATA, - .bInterfaceSubClass = 0, - .bInterfaceProtocol = 0, - .iInterface = 0, - - .endpoint = uart_data_endp, -}}; - -static const struct usb_iface_assoc_descriptor uart_assoc = { - .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE, - .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, - .bFirstInterface = 2, - .bInterfaceCount = 2, - .bFunctionClass = USB_CLASS_CDC, - .bFunctionSubClass = USB_CDC_SUBCLASS_ACM, - .bFunctionProtocol = USB_CDC_PROTOCOL_AT, - .iFunction = 0, -}; - -const struct usb_dfu_descriptor dfu_function = { - .bLength = sizeof(struct usb_dfu_descriptor), - .bDescriptorType = DFU_FUNCTIONAL, - .bmAttributes = USB_DFU_CAN_DOWNLOAD | USB_DFU_WILL_DETACH, - .wDetachTimeout = 255, - .wTransferSize = 1024, - .bcdDFUVersion = 0x011A, -}; - -const struct usb_interface_descriptor dfu_iface = { - .bLength = USB_DT_INTERFACE_SIZE, - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = DFU_IF_NO, - .bAlternateSetting = 0, - .bNumEndpoints = 0, - .bInterfaceClass = 0xFE, - .bInterfaceSubClass = 1, - .bInterfaceProtocol = 1, - .iInterface = 6, - - .extra = &dfu_function, - .extralen = sizeof(dfu_function), -}; - -static const struct usb_iface_assoc_descriptor dfu_assoc = { - .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE, - .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, - .bFirstInterface = 4, - .bInterfaceCount = 1, - .bFunctionClass = 0xFE, - .bFunctionSubClass = 1, - .bFunctionProtocol = 1, - .iFunction = 6, -}; - -#if defined(PLATFORM_HAS_TRACESWO) -static const struct usb_endpoint_descriptor trace_endp[] = {{ - .bLength = USB_DT_ENDPOINT_SIZE, - .bDescriptorType = USB_DT_ENDPOINT, - .bEndpointAddress = 0x85, - .bmAttributes = USB_ENDPOINT_ATTR_BULK, - .wMaxPacketSize = 64, - .bInterval = 0, -}}; - -const struct usb_interface_descriptor trace_iface = { - .bLength = USB_DT_INTERFACE_SIZE, - .bDescriptorType = USB_DT_INTERFACE, - .bInterfaceNumber = 5, - .bAlternateSetting = 0, - .bNumEndpoints = 1, - .bInterfaceClass = 0xFF, - .bInterfaceSubClass = 0xFF, - .bInterfaceProtocol = 0xFF, - .iInterface = 7, - - .endpoint = trace_endp, -}; - -static const struct usb_iface_assoc_descriptor trace_assoc = { - .bLength = USB_DT_INTERFACE_ASSOCIATION_SIZE, - .bDescriptorType = USB_DT_INTERFACE_ASSOCIATION, - .bFirstInterface = 5, - .bInterfaceCount = 1, - .bFunctionClass = 0xFF, - .bFunctionSubClass = 0xFF, - .bFunctionProtocol = 0xFF, - .iFunction = 7, -}; -#endif - -static const struct usb_interface ifaces[] = {{ - .num_altsetting = 1, - .iface_assoc = &gdb_assoc, - .altsetting = gdb_comm_iface, -}, { - .num_altsetting = 1, - .altsetting = gdb_data_iface, -}, { - .num_altsetting = 1, - .iface_assoc = &uart_assoc, - .altsetting = uart_comm_iface, -}, { - .num_altsetting = 1, - .altsetting = uart_data_iface, -}, { - .num_altsetting = 1, - .iface_assoc = &dfu_assoc, - .altsetting = &dfu_iface, -#if defined(PLATFORM_HAS_TRACESWO) -}, { - .num_altsetting = 1, - .iface_assoc = &trace_assoc, - .altsetting = &trace_iface, -#endif -}}; - -static const struct usb_config_descriptor config = { - .bLength = USB_DT_CONFIGURATION_SIZE, - .bDescriptorType = USB_DT_CONFIGURATION, - .wTotalLength = 0, -#if defined(PLATFORM_HAS_TRACESWO) - .bNumInterfaces = 6, -#else - .bNumInterfaces = 5, -#endif - .bConfigurationValue = 1, - .iConfiguration = 0, - .bmAttributes = 0x80, - .bMaxPower = 0x32, - - .interface = ifaces, -}; - -char serial_no[9]; - -static const char *usb_strings[] = { - "Black Sphere Technologies", - BOARD_IDENT, - serial_no, - "Black Magic GDB Server", - "Black Magic UART Port", - DFU_IDENT, -#if defined(PLATFORM_HAS_TRACESWO) - "Black Magic Trace Capture", -#endif -}; - -static void dfu_detach_complete(usbd_device *dev, struct usb_setup_data *req) -{ - (void)dev; - (void)req; - - /* Disconnect USB cable */ - disconnect_usb(); - - /* Assert boot-request pin */ - //assert_boot_pin(); - - /* Reset core to enter bootloader */ - scb_reset_core(); -} - -static int cdcacm_control_request(usbd_device *dev, - struct usb_setup_data *req, uint8_t **buf, uint16_t *len, - void (**complete)(usbd_device *dev, struct usb_setup_data *req)) -{ - (void)dev; - (void)complete; - (void)buf; - (void)len; - - switch(req->bRequest) { - case USB_CDC_REQ_SET_CONTROL_LINE_STATE: - /* Ignore if not for GDB interface */ - if(req->wIndex != 0) - return 1; - - cdcacm_gdb_dtr = req->wValue & 1; - - return 1; - case USB_CDC_REQ_SET_LINE_CODING: - if(*len < sizeof(struct usb_cdc_line_coding)) - return 0; - - switch(req->wIndex) { - case 2: - usbuart_set_line_coding((struct usb_cdc_line_coding*)*buf); - case 0: - return 1; /* Ignore on GDB Port */ - default: - return 0; - } - case DFU_GETSTATUS: - if(req->wIndex == DFU_IF_NO) { - (*buf)[0] = DFU_STATUS_OK; - (*buf)[1] = 0; - (*buf)[2] = 0; - (*buf)[3] = 0; - (*buf)[4] = STATE_APP_IDLE; - (*buf)[5] = 0; /* iString not used here */ - *len = 6; - - return 1; - } - case DFU_DETACH: - if(req->wIndex == DFU_IF_NO) { - *complete = dfu_detach_complete; - return 1; - } - return 0; - } - return 0; -} - -int cdcacm_get_config(void) -{ - return configured; -} - -int cdcacm_get_dtr(void) -{ - return cdcacm_gdb_dtr; -} - -static void cdcacm_set_config(usbd_device *dev, uint16_t wValue) -{ - configured = wValue; - - /* GDB interface */ - usbd_ep_setup(dev, 0x01, USB_ENDPOINT_ATTR_BULK, - CDCACM_PACKET_SIZE, gdb_usb_out_cb); - usbd_ep_setup(dev, 0x81, USB_ENDPOINT_ATTR_BULK, - CDCACM_PACKET_SIZE, NULL); - usbd_ep_setup(dev, 0x82, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL); - - /* Serial interface */ - usbd_ep_setup(dev, 0x03, USB_ENDPOINT_ATTR_BULK, - CDCACM_PACKET_SIZE, usbuart_usb_out_cb); - usbd_ep_setup(dev, 0x83, USB_ENDPOINT_ATTR_BULK, - CDCACM_PACKET_SIZE, usbuart_usb_in_cb); - usbd_ep_setup(dev, 0x84, USB_ENDPOINT_ATTR_INTERRUPT, 16, NULL); - -#if defined(PLATFORM_HAS_TRACESWO) - /* Trace interface */ - usbd_ep_setup(dev, 0x85, USB_ENDPOINT_ATTR_BULK, - 64, trace_buf_drain); -#endif - - usbd_register_control_callback(dev, - USB_REQ_TYPE_CLASS | USB_REQ_TYPE_INTERFACE, - USB_REQ_TYPE_TYPE | USB_REQ_TYPE_RECIPIENT, - cdcacm_control_request); - - /* Notify the host that DCD is asserted. - * Allows the use of /dev/tty* devices on *BSD/MacOS - */ - char buf[10]; - struct usb_cdc_notification *notif = (void*)buf; - /* We echo signals back to host as notification */ - notif->bmRequestType = 0xA1; - notif->bNotification = USB_CDC_NOTIFY_SERIAL_STATE; - notif->wValue = 0; - notif->wIndex = 0; - notif->wLength = 2; - buf[8] = 3; /* DCD | DSR */ - buf[9] = 0; - usbd_ep_write_packet(dev, 0x82, buf, 10); - notif->wIndex = 2; - usbd_ep_write_packet(dev, 0x84, buf, 10); -} - -/* We need a special large control buffer for this device: */ -uint8_t usbd_control_buffer[256]; - -void cdcacm_init(void) -{ - get_dev_unique_id(serial_no); - - periph_clock_enable(RCC_GPIOD); - __asm__("nop"); __asm__("nop"); __asm__("nop"); - gpio_mode_setup(GPIOD_BASE, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO4|GPIO5); - - usbdev = usbd_init(&USB_DRIVER, &dev, &config, usb_strings, - sizeof(usb_strings)/sizeof(char *), - usbd_control_buffer, sizeof(usbd_control_buffer)); - - usbd_register_set_config_callback(usbdev, cdcacm_set_config); - - usb_enable_interrupts(USB_INT_RESET|USB_INT_DISCON|USB_INT_RESUME|USB_INT_SUSPEND, - 0xff, 0xff); - nvic_set_priority(USB_IRQ, IRQ_PRI_USB); - nvic_enable_irq(USB_IRQ); - setup_vbus_irq(); -} - -void USB_ISR(void) -{ - usbd_poll(usbdev); -} - -static char *get_dev_unique_id(char *s) -{ - /* FIXME: Store a unique serial number somewhere and retreive here */ - uint32_t unique_id = 1; - int i; - - /* Fetch serial number from chip's unique ID */ - for(i = 0; i < 8; i++) { - s[7-i] = ((unique_id >> (4*i)) & 0xF) + '0'; - } - for(i = 0; i < 8; i++) - if(s[i] > '9') - s[i] += 'A' - '9' - 1; - s[8] = 0; - - return s; -} diff --git a/src/platforms/tm4c/traceswo.c b/src/platforms/tm4c/traceswo.c index 03c6d66..3e43a3b 100644 --- a/src/platforms/tm4c/traceswo.c +++ b/src/platforms/tm4c/traceswo.c @@ -28,6 +28,7 @@ */ #include "general.h" +#include "cdcacm.h" #include #include -- cgit v1.2.3 From 3e466f2d23401df610cb0f94a226317c2dc38751 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Mon, 2 Mar 2015 21:59:04 -0800 Subject: Factor out timing routines common to all STM32 targets. --- src/include/platform_support.h | 2 ++ src/platforms/f4discovery/Makefile.inc | 1 + src/platforms/f4discovery/platform.c | 30 +--------------- src/platforms/f4discovery/platform.h | 4 +-- src/platforms/native/Makefile.inc | 1 + src/platforms/native/platform.c | 29 +-------------- src/platforms/native/platform.h | 4 +-- src/platforms/stlink/Makefile.inc | 1 + src/platforms/stlink/platform.c | 28 ++------------- src/platforms/stlink/platform.h | 6 ++-- src/platforms/stm32/gdb_if.c | 4 +-- src/platforms/stm32/timing.c | 65 ++++++++++++++++++++++++++++++++++ src/platforms/stm32/timing.h | 27 ++++++++++++++ src/platforms/swlink/Makefile.inc | 1 + src/platforms/swlink/platform.c | 33 ++--------------- src/platforms/swlink/platform.h | 9 +++-- 16 files changed, 116 insertions(+), 129 deletions(-) create mode 100644 src/platforms/stm32/timing.c create mode 100644 src/platforms/stm32/timing.h (limited to 'src') diff --git a/src/include/platform_support.h b/src/include/platform_support.h index 7d8443c..2bfbe65 100644 --- a/src/include/platform_support.h +++ b/src/include/platform_support.h @@ -32,6 +32,8 @@ void platform_init(void); const char *platform_target_voltage(void); int platform_hwversion(void); +void platform_timeout_set(uint32_t ms); +bool platform_timeout_is_expired(void); void platform_delay(uint32_t delay); void platform_srst_set_val(bool assert); bool platform_target_get_power(void); diff --git a/src/platforms/f4discovery/Makefile.inc b/src/platforms/f4discovery/Makefile.inc index 21b4078..d8f7754 100644 --- a/src/platforms/f4discovery/Makefile.inc +++ b/src/platforms/f4discovery/Makefile.inc @@ -20,6 +20,7 @@ SRC += cdcacm.c \ traceswo.c \ usbuart.c \ serialno.c \ + timing.c \ all: blackmagic.bin diff --git a/src/platforms/f4discovery/platform.c b/src/platforms/f4discovery/platform.c index 6e10ff4..e85ebd5 100644 --- a/src/platforms/f4discovery/platform.c +++ b/src/platforms/f4discovery/platform.c @@ -28,7 +28,6 @@ #include "morse.h" #include -#include #include #include #include @@ -36,9 +35,6 @@ #include #include -uint8_t running_status; -volatile uint32_t timeout_counter; - jmp_buf fatal_error_jmpbuf; void platform_init(void) @@ -77,35 +73,11 @@ void platform_init(void) GPIO_PUPD_NONE, LED_UART | LED_IDLE_RUN | LED_ERROR | LED_BOOTLOADER); - /* Setup heartbeat timer */ - systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); - systick_set_reload(168000000/(10*8)); /* Interrupt us at 10 Hz */ - SCB_SHPR(11) &= ~((15 << 4) & 0xff); - SCB_SHPR(11) |= ((14 << 4) & 0xff); - systick_interrupt_enable(); - systick_counter_enable(); - + platform_timing_init(); usbuart_init(); cdcacm_init(); } -void platform_delay(uint32_t delay) -{ - timeout_counter = delay; - while(timeout_counter); -} - -void sys_tick_handler(void) -{ - if(running_status) - gpio_toggle(LED_PORT, LED_IDLE_RUN); - - if(timeout_counter) - timeout_counter--; - - SET_ERROR_STATE(morse_update()); -} - const char *platform_target_voltage(void) { return "ABSENT!"; diff --git a/src/platforms/f4discovery/platform.h b/src/platforms/f4discovery/platform.h index 61753af..3c5c582 100644 --- a/src/platforms/f4discovery/platform.h +++ b/src/platforms/f4discovery/platform.h @@ -27,6 +27,7 @@ #include "gdb_packet.h" #include "gpio.h" #include "morse.h" +#include "timing.h" #include @@ -140,9 +141,6 @@ #define DEBUG(...) -extern uint8_t running_status; -extern volatile uint32_t timeout_counter; - extern jmp_buf fatal_error_jmpbuf; #define gpio_set_val(port, pin, val) do { \ diff --git a/src/platforms/native/Makefile.inc b/src/platforms/native/Makefile.inc index 2270ff5..8b76a53 100644 --- a/src/platforms/native/Makefile.inc +++ b/src/platforms/native/Makefile.inc @@ -19,6 +19,7 @@ SRC += cdcacm.c \ traceswo.c \ usbuart.c \ serialno.c \ + timing.c \ all: blackmagic.bin blackmagic_dfu.bin blackmagic_dfu.hex diff --git a/src/platforms/native/platform.c b/src/platforms/native/platform.c index 5c28747..ac54b4b 100644 --- a/src/platforms/native/platform.c +++ b/src/platforms/native/platform.c @@ -28,7 +28,6 @@ #include "morse.h" #include -#include #include #include #include @@ -36,9 +35,6 @@ #include #include -uint8_t running_status; -volatile uint32_t timeout_counter; - jmp_buf fatal_error_jmpbuf; static void adc_init(void); @@ -115,14 +111,6 @@ void platform_init(void) GPIO_CNF_INPUT_PULL_UPDOWN, PWR_BR_PIN); } - /* Setup heartbeat timer */ - systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); - systick_set_reload(900000); /* Interrupt us at 10 Hz */ - SCB_SHPR(11) &= ~((15 << 4) & 0xff); - SCB_SHPR(11) |= ((14 << 4) & 0xff); - systick_interrupt_enable(); - systick_counter_enable(); - if (platform_hwversion() > 0) { adc_init(); } else { @@ -133,6 +121,7 @@ void platform_init(void) /* Relocate interrupt vector table here */ SCB_VTOR = 0x2000; + platform_timing_init(); cdcacm_init(); usbuart_init(); setup_vbus_irq(); @@ -161,22 +150,6 @@ void platform_target_set_power(bool power) gpio_set_val(PWR_BR_PORT, PWR_BR_PIN, !power); } } -void platform_delay(uint32_t delay) -{ - timeout_counter = delay; - while(timeout_counter); -} - -void sys_tick_handler(void) -{ - if(running_status) - gpio_toggle(LED_PORT, LED_IDLE_RUN); - - if(timeout_counter) - timeout_counter--; - - SET_ERROR_STATE(morse_update()); -} static void adc_init(void) { diff --git a/src/platforms/native/platform.h b/src/platforms/native/platform.h index c0b4dba..ae9bcef 100644 --- a/src/platforms/native/platform.h +++ b/src/platforms/native/platform.h @@ -27,6 +27,7 @@ #include "gdb_packet.h" #include "gpio.h" #include "morse.h" +#include "timing.h" #include @@ -146,9 +147,6 @@ #define DEBUG(...) -extern uint8_t running_status; -extern volatile uint32_t timeout_counter; - extern jmp_buf fatal_error_jmpbuf; #define SET_RUN_STATE(state) {running_status = (state);} diff --git a/src/platforms/stlink/Makefile.inc b/src/platforms/stlink/Makefile.inc index 52ad33b..f2ebce5 100644 --- a/src/platforms/stlink/Makefile.inc +++ b/src/platforms/stlink/Makefile.inc @@ -18,6 +18,7 @@ SRC += cdcacm.c \ platform.c \ usbuart.c \ serialno.c \ + timing.c \ all: blackmagic.bin blackmagic_dfu.bin blackmagic_dfu.hex dfu_upgrade.bin dfu_upgrade.hex diff --git a/src/platforms/stlink/platform.c b/src/platforms/stlink/platform.c index 446fb47..fb10faa 100644 --- a/src/platforms/stlink/platform.c +++ b/src/platforms/stlink/platform.c @@ -27,7 +27,6 @@ #include "usbuart.h" #include -#include #include #include #include @@ -104,25 +103,11 @@ void platform_init(void) gpio_set_mode(LED_PORT, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, led_idle_run); - /* Setup heartbeat timer */ - systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); - systick_set_reload(900000); /* Interrupt us at 10 Hz */ - SCB_SHPR(11) &= ~((15 << 4) & 0xff); - SCB_SHPR(11) |= ((14 << 4) & 0xff); - systick_interrupt_enable(); - systick_counter_enable(); - - usbuart_init(); - SCB_VTOR = 0x2000; /* Relocate interrupt vector table here */ + platform_timing_init(); cdcacm_init(); -} - -void platform_delay(uint32_t delay) -{ - timeout_counter = delay; - while (timeout_counter); + usbuart_init(); } void platform_srst_set_val(bool assert) @@ -135,15 +120,6 @@ void platform_srst_set_val(bool assert) gpio_set(SRST_PORT, pin); } -void sys_tick_handler(void) -{ - if(running_status) - gpio_toggle(LED_PORT, led_idle_run); - - if(timeout_counter) - timeout_counter--; -} - const char *platform_target_voltage(void) { return "unknown"; diff --git a/src/platforms/stlink/platform.h b/src/platforms/stlink/platform.h index fcbe259..f026db3 100644 --- a/src/platforms/stlink/platform.h +++ b/src/platforms/stlink/platform.h @@ -26,6 +26,7 @@ #include "gdb_packet.h" #include "gpio.h" +#include "timing.h" #include #include @@ -129,14 +130,13 @@ #define DEBUG(...) -extern uint8_t running_status; -extern volatile uint32_t timeout_counter; - extern jmp_buf fatal_error_jmpbuf; extern uint16_t led_idle_run; +#define LED_IDLE_RUN led_idle_run #define SET_RUN_STATE(state) {running_status = (state);} #define SET_IDLE_STATE(state) {gpio_set_val(LED_PORT, led_idle_run, state);} +#define SET_ERROR_STATE(x) #define PLATFORM_SET_FATAL_ERROR_RECOVERY() {setjmp(fatal_error_jmpbuf);} #define PLATFORM_FATAL_ERROR(error) do { \ diff --git a/src/platforms/stm32/gdb_if.c b/src/platforms/stm32/gdb_if.c index 286c66b..52922e7 100644 --- a/src/platforms/stm32/gdb_if.c +++ b/src/platforms/stm32/gdb_if.c @@ -113,7 +113,7 @@ unsigned char gdb_if_getchar(void) unsigned char gdb_if_getchar_to(int timeout) { - timeout_counter = timeout/100; + platform_timeout_set(timeout); if (!(out_ptr < count_out)) do { /* Detach if port closed */ @@ -121,7 +121,7 @@ unsigned char gdb_if_getchar_to(int timeout) return 0x04; gdb_if_update_buf(); - } while(timeout_counter && !(out_ptr < count_out)); + } while (!platform_timeout_is_expired() && !(out_ptr < count_out)); if(out_ptr < count_out) return gdb_if_getchar(); diff --git a/src/platforms/stm32/timing.c b/src/platforms/stm32/timing.c new file mode 100644 index 0000000..cac22ca --- /dev/null +++ b/src/platforms/stm32/timing.c @@ -0,0 +1,65 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2015 Gareth McMullin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * 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, see . + */ +#include "general.h" + +#include +#include + +uint8_t running_status; + +static volatile uint32_t timeout_counter; + +void platform_timing_init(void) +{ + /* Setup heartbeat timer */ + systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); + systick_set_reload(900000); /* Interrupt us at 10 Hz */ + SCB_SHPR(11) &= ~((15 << 4) & 0xff); + SCB_SHPR(11) |= ((14 << 4) & 0xff); + systick_interrupt_enable(); + systick_counter_enable(); +} + +void platform_timeout_set(uint32_t ms) +{ + timeout_counter = ms / 100; +} + +bool platform_timeout_is_expired(void) +{ + return timeout_counter == 0; +} + +void platform_delay(uint32_t delay) +{ + platform_timeout_set(delay); + while (platform_timeout_is_expired()); +} + +void sys_tick_handler(void) +{ + if(running_status) + gpio_toggle(LED_PORT, LED_IDLE_RUN); + + if(timeout_counter) + timeout_counter--; + + SET_ERROR_STATE(morse_update()); +} + diff --git a/src/platforms/stm32/timing.h b/src/platforms/stm32/timing.h new file mode 100644 index 0000000..0178ff5 --- /dev/null +++ b/src/platforms/stm32/timing.h @@ -0,0 +1,27 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2015 Gareth McMullin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * 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, see . + */ +#ifndef __TIMING_H +#define __TIMING_H + +extern uint8_t running_status; + +void platform_timing_init(void); + +#endif + diff --git a/src/platforms/swlink/Makefile.inc b/src/platforms/swlink/Makefile.inc index b68b1ab..f891cb0 100644 --- a/src/platforms/swlink/Makefile.inc +++ b/src/platforms/swlink/Makefile.inc @@ -18,6 +18,7 @@ SRC += cdcacm.c \ platform.c \ usbuart.c \ serialno.c \ + timing.c \ all: blackmagic.bin blackmagic_dfu.bin blackmagic_dfu.hex diff --git a/src/platforms/swlink/platform.c b/src/platforms/swlink/platform.c index 1b9a76e..cbdae0c 100644 --- a/src/platforms/swlink/platform.c +++ b/src/platforms/swlink/platform.c @@ -27,16 +27,12 @@ #include "usbuart.h" #include -#include #include #include #include #include #include -uint8_t running_status; -volatile uint32_t timeout_counter; - jmp_buf fatal_error_jmpbuf; void platform_init(void) @@ -72,7 +68,7 @@ void platform_init(void) GPIO_CNF_INPUT_PULL_UPDOWN, NRST_PIN); gpio_set_mode(LED_PORT, GPIO_MODE_OUTPUT_2_MHZ, - GPIO_CNF_OUTPUT_PUSHPULL, led_idle_run); + GPIO_CNF_OUTPUT_PUSHPULL, LED_IDLE_RUN); /* Remap TIM2 TIM2_REMAP[1] * TIM2_CH1_ETR -> PA15 (TDI, set as output above) @@ -83,34 +79,11 @@ void platform_init(void) data |= AFIO_MAPR_TIM2_REMAP_PARTIAL_REMAP1; AFIO_MAPR = data; - /* Setup heartbeat timer */ - systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8); - systick_set_reload(900000); /* Interrupt us at 10 Hz */ - SCB_SHPR(11) &= ~((15 << 4) & 0xff); - SCB_SHPR(11) |= ((14 << 4) & 0xff); - systick_interrupt_enable(); - systick_counter_enable(); - - usbuart_init(); - SCB_VTOR = 0x2000; // Relocate interrupt vector table here + platform_timing_init(); cdcacm_init(); -} - -void platform_delay(uint32_t delay) -{ - timeout_counter = delay; - while(timeout_counter); -} - -void sys_tick_handler(void) -{ - if(running_status) - gpio_toggle(LED_PORT, led_idle_run); - - if(timeout_counter) - timeout_counter--; + usbuart_init(); } const char *platform_target_voltage(void) diff --git a/src/platforms/swlink/platform.h b/src/platforms/swlink/platform.h index 6ee4a9c..27cc299 100644 --- a/src/platforms/swlink/platform.h +++ b/src/platforms/swlink/platform.h @@ -26,6 +26,7 @@ #include "gdb_packet.h" #include "gpio.h" +#include "timing.h" #include @@ -69,6 +70,7 @@ #define SWCLK_PIN TCK_PIN #define LED_PORT GPIOA +#define LED_IDLE_RUN GPIO8 /* Use PC14 for a "dummy" uart led. So we can observere at least with scope*/ #define LED_PORT_UART GPIOC #define LED_UART GPIO14 @@ -123,14 +125,11 @@ #define DEBUG(...) -extern uint8_t running_status; -extern volatile uint32_t timeout_counter; - extern jmp_buf fatal_error_jmpbuf; -#define led_idle_run GPIO8 #define SET_RUN_STATE(state) {running_status = (state);} -#define SET_IDLE_STATE(state) {gpio_set_val(LED_PORT, led_idle_run, state);} +#define SET_IDLE_STATE(state) {gpio_set_val(LED_PORT, LED_IDLE_RUN, state);} +#define SET_ERROR_STATE(x) #define PLATFORM_SET_FATAL_ERROR_RECOVERY() {setjmp(fatal_error_jmpbuf);} #define PLATFORM_FATAL_ERROR(error) { \ -- cgit v1.2.3 From 87b8f330f097b5519605748bd96cbecd18fc5250 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Mon, 2 Mar 2015 22:20:25 -0800 Subject: Add a makefile target to build all platforms. --- src/Makefile | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 09e0bf0..f56f7c5 100644 --- a/src/Makefile +++ b/src/Makefile @@ -47,10 +47,24 @@ OBJ = $(SRC:.c=.o) blackmagic: $(OBJ) $(CC) -o $@ $^ $(LDFLAGS) -.PHONY: clean host_clean +.PHONY: clean host_clean all_platforms clean: host_clean -$(RM) *.o *.d *~ blackmagic $(HOSTFILES) -$(RM) platforms/*/*.o platforms/*/*.d mapfile +all_platforms: + for i in platforms/*/Makefile.inc ; do \ + export DIRNAME=`dirname $$i` ;\ + export PROBE_HOST=`basename $$DIRNAME` ;\ + export CFLAGS=-Werror ;\ + echo $$PROBE_HOST ;\ + $(MAKE) clean ;\ + $(MAKE) ;\ + if [ -f blackmagic.bin ]; then \ + mv blackmagic.bin blackmagic-$$PROBE_HOST.bin ;\ + fi ;\ + done + -include *.d + -- cgit v1.2.3 From 2e37db22703e38b01b7e22c667bbea1dbd19f8cf Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Mon, 2 Mar 2015 23:14:43 -0800 Subject: Error on any failure on 'make all_platforms' --- src/Makefile | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/Makefile b/src/Makefile index f56f7c5..3a29b7b 100644 --- a/src/Makefile +++ b/src/Makefile @@ -54,6 +54,7 @@ clean: host_clean -$(RM) platforms/*/*.o platforms/*/*.d mapfile all_platforms: + set -e ;\ for i in platforms/*/Makefile.inc ; do \ export DIRNAME=`dirname $$i` ;\ export PROBE_HOST=`basename $$DIRNAME` ;\ -- cgit v1.2.3 From c731c6ece343c48296355b8cfde58067c2f44853 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Tue, 3 Mar 2015 21:39:29 -0800 Subject: Make F4 conditionals check STM32F4, not F4DISCOVERY. --- src/platforms/stm32/gpio.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/platforms/stm32/gpio.h b/src/platforms/stm32/gpio.h index ee8275e..d39fd4f 100644 --- a/src/platforms/stm32/gpio.h +++ b/src/platforms/stm32/gpio.h @@ -43,7 +43,7 @@ static inline void _gpio_set(uint32_t gpioport, uint16_t gpios) { GPIO_BSRR(gpioport) = gpios; -#ifdef F4DISCOVERY +#ifdef STM32F4 GPIO_BSRR(gpioport) = gpios; #endif } @@ -51,7 +51,7 @@ static inline void _gpio_set(uint32_t gpioport, uint16_t gpios) static inline void _gpio_clear(uint32_t gpioport, uint16_t gpios) { -#ifndef F4DISCOVERY +#ifndef STM32F4 GPIO_BRR(gpioport) = gpios; #else GPIO_BSRR(gpioport) = gpios<<16; -- cgit v1.2.3 From c8f469c868c63f21692a8d61733bf6305a92110f Mon Sep 17 00:00:00 2001 From: David Lawrence Date: Wed, 4 Feb 2015 15:45:52 -0500 Subject: SAM4S: Erase flash in 8K instead of 16K chunks. --- src/sam3x.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/sam3x.c b/src/sam3x.c index ef99290..902f267 100644 --- a/src/sam3x.c +++ b/src/sam3x.c @@ -291,26 +291,27 @@ static int sam3x_flash_erase(struct target_s *target, uint32_t addr, int len) uint32_t base = sam3x_flash_base(target, addr, &offset); /* The SAM4S is the only supported device with a page erase command. - * Erasing is done in 16-page chunks. arg[15:2] contains the page - * number and arg[1:0] contains 0x2, indicating 16-page chunks. + * Erasing is done in 8-page chunks. arg[15:2] contains the page + * number and arg[1:0] contains 0x1, indicating 8-page chunks. */ if (strcmp(target->driver, "Atmel SAM4S") == 0) { unsigned chunk = offset / SAM4_PAGE_SIZE; - /* Fail if the start address is not 16-page-aligned. */ - if (chunk % 16 != 0) + + /* Fail if the start address is not 8-page-aligned. */ + if (chunk % 8 != 0) return -1; - /* Note that the length might not be a multiple of 16 pages. + /* Note that the length might not be a multiple of 8 pages. * In this case, we will erase a few extra pages at the end. */ while (len > 0) { - int16_t arg = (chunk << 2) | 0x2; + int16_t arg = chunk | 0x1; if(sam3x_flash_cmd(target, base, EEFC_FCR_FCMD_EPA, arg)) return -1; - len -= SAM4_PAGE_SIZE * 16; - addr += SAM4_PAGE_SIZE * 16; - chunk += 16; + len -= SAM4_PAGE_SIZE * 8; + addr += SAM4_PAGE_SIZE * 8; + chunk += 8; } return 0; -- cgit v1.2.3 From 1eac78b1c8bd8096c7a8c4c175119f47924cbb6e Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Fri, 6 Mar 2015 14:36:24 -0800 Subject: Move targets to make bin and hex files to toplevel makefile. --- src/Makefile | 6 ++++++ src/platforms/f4discovery/Makefile.inc | 3 --- src/platforms/launchpad-icdi/Makefile.inc | 2 -- src/platforms/native/Makefile.inc | 8 -------- src/platforms/stlink/Makefile.inc | 15 --------------- src/platforms/swlink/Makefile.inc | 9 --------- 6 files changed, 6 insertions(+), 37 deletions(-) (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 3a29b7b..5295576 100644 --- a/src/Makefile +++ b/src/Makefile @@ -47,6 +47,12 @@ OBJ = $(SRC:.c=.o) blackmagic: $(OBJ) $(CC) -o $@ $^ $(LDFLAGS) +%.bin: % + $(OBJCOPY) -O binary $^ $@ + +%.hex: % + $(OBJCOPY) -O ihex $^ $@ + .PHONY: clean host_clean all_platforms clean: host_clean diff --git a/src/platforms/f4discovery/Makefile.inc b/src/platforms/f4discovery/Makefile.inc index d8f7754..01b3f61 100644 --- a/src/platforms/f4discovery/Makefile.inc +++ b/src/platforms/f4discovery/Makefile.inc @@ -24,8 +24,5 @@ SRC += cdcacm.c \ all: blackmagic.bin -blackmagic.bin: blackmagic - $(OBJCOPY) -O binary $^ $@ - host_clean: -rm blackmagic.bin diff --git a/src/platforms/launchpad-icdi/Makefile.inc b/src/platforms/launchpad-icdi/Makefile.inc index 8a0f9a3..e46b727 100644 --- a/src/platforms/launchpad-icdi/Makefile.inc +++ b/src/platforms/launchpad-icdi/Makefile.inc @@ -19,5 +19,3 @@ SRC += cdcacm.c \ all: blackmagic.bin -blackmagic.bin: blackmagic - $(OBJCOPY) -O binary $^ $@ diff --git a/src/platforms/native/Makefile.inc b/src/platforms/native/Makefile.inc index 8b76a53..b5c5c33 100644 --- a/src/platforms/native/Makefile.inc +++ b/src/platforms/native/Makefile.inc @@ -23,17 +23,9 @@ SRC += cdcacm.c \ all: blackmagic.bin blackmagic_dfu.bin blackmagic_dfu.hex -blackmagic.bin: blackmagic - $(OBJCOPY) -O binary $^ $@ - blackmagic_dfu: usbdfu.o dfucore.o dfu_f1.o $(CC) $^ -o $@ $(LDFLAGS_BOOT) -blackmagic_dfu.bin: blackmagic_dfu - $(OBJCOPY) -O binary $^ $@ - -blackmagic_dfu.hex: blackmagic_dfu - $(OBJCOPY) -O ihex $^ $@ host_clean: -rm blackmagic.bin blackmagic_dfu blackmagic_dfu.bin blackmagic_dfu.hex diff --git a/src/platforms/stlink/Makefile.inc b/src/platforms/stlink/Makefile.inc index f2ebce5..5b2e61f 100644 --- a/src/platforms/stlink/Makefile.inc +++ b/src/platforms/stlink/Makefile.inc @@ -22,27 +22,12 @@ SRC += cdcacm.c \ all: blackmagic.bin blackmagic_dfu.bin blackmagic_dfu.hex dfu_upgrade.bin dfu_upgrade.hex -blackmagic.bin: blackmagic - $(OBJCOPY) -O binary $^ $@ - blackmagic_dfu: usbdfu.o dfucore.o dfu_f1.o $(CC) $^ -o $@ $(LDFLAGS_BOOT) -blackmagic_dfu.bin: blackmagic_dfu - $(OBJCOPY) -O binary $^ $@ - -blackmagic_dfu.hex: blackmagic_dfu - $(OBJCOPY) -O ihex $^ $@ - dfu_upgrade: dfu_upgrade.o dfucore.o dfu_f1.o $(CC) $^ -o $@ $(LDFLAGS) -dfu_upgrade.bin: dfu_upgrade - $(OBJCOPY) -O binary $^ $@ - -dfu_upgrade.hex: dfu_upgrade - $(OBJCOPY) -O ihex $^ $@ - host_clean: -rm blackmagic.bin blackmagic_dfu blackmagic_dfu.bin blackmagic_dfu.hex dfu_upgrade dfu_upgrade.bin dfu_upgrade.hex diff --git a/src/platforms/swlink/Makefile.inc b/src/platforms/swlink/Makefile.inc index f891cb0..c415ecd 100644 --- a/src/platforms/swlink/Makefile.inc +++ b/src/platforms/swlink/Makefile.inc @@ -22,18 +22,9 @@ SRC += cdcacm.c \ all: blackmagic.bin blackmagic_dfu.bin blackmagic_dfu.hex -blackmagic.bin: blackmagic - $(OBJCOPY) -O binary $^ $@ - blackmagic_dfu: usbdfu.o dfucore.o dfu_f1.o $(CC) $^ -o $@ $(LDFLAGS_BOOT) -blackmagic_dfu.bin: blackmagic_dfu - $(OBJCOPY) -O binary $^ $@ - -blackmagic_dfu.hex: blackmagic_dfu - $(OBJCOPY) -O ihex $^ $@ - host_clean: -rm blackmagic.bin blackmagic_dfu blackmagic_dfu.bin blackmagic_dfu.hex -- cgit v1.2.3 From 0d99e22a26599f03ac8243c61799d7be3351ece0 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sat, 7 Mar 2015 10:32:52 -0800 Subject: Quieten build system. --- Makefile | 17 +++++++++++------ src/Makefile | 31 ++++++++++++++++++++++--------- src/platforms/f4discovery/Makefile.inc | 2 +- src/platforms/native/Makefile.inc | 6 +++--- src/platforms/stlink/Makefile.inc | 8 +++++--- src/platforms/swlink/Makefile.inc | 5 +++-- 6 files changed, 45 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/Makefile b/Makefile index 5a8365e..358c687 100644 --- a/Makefile +++ b/Makefile @@ -1,13 +1,18 @@ +ifneq ($(V), 1) +MFLAGS += --no-print-dir +Q := @ +endif + all: - @if [ ! -f libopencm3/Makefile ]; then \ + $(Q)if [ ! -f libopencm3/Makefile ]; then \ echo "Initialising git submodules..." ;\ git submodule init ;\ git submodule update ;\ fi - $(MAKE) -C libopencm3 lib - $(MAKE) -C src + $(Q)$(MAKE) $(MFLAGS) -C libopencm3 lib + $(Q)$(MAKE) $(MFLAGS) -C src -%: - $(MAKE) -C libopencm3 $@ - $(MAKE) -C src $@ +clean: + $(Q)$(MAKE) $(MFLAGS) -C libopencm3 $@ + $(Q)$(MAKE) $(MFLAGS) -C src $@ diff --git a/src/Makefile b/src/Makefile index 5295576..2d3e6b7 100644 --- a/src/Makefile +++ b/src/Makefile @@ -2,6 +2,11 @@ PROBE_HOST ?= native PLATFORM_DIR = platforms/$(PROBE_HOST) VPATH += platforms/common $(PLATFORM_DIR) +ifneq ($(V), 1) +MAKEFLAGS += --no-print-dir +Q := @ +endif + BUILDDATE := `date +"%Y%m%d"` CFLAGS += -Wall -Wextra -Wno-pointer-sign -Wno-char-subscripts\ @@ -45,29 +50,37 @@ include $(PLATFORM_DIR)/Makefile.inc OBJ = $(SRC:.c=.o) blackmagic: $(OBJ) - $(CC) -o $@ $^ $(LDFLAGS) + @echo " LD $@" + $(Q)$(CC) -o $@ $^ $(LDFLAGS) + +%.o: %.c + @echo " CC $<" + $(Q)$(CC) $(CFLAGS) -c $< -o $@ %.bin: % - $(OBJCOPY) -O binary $^ $@ + @echo " OBJCOPY $@" + $(Q)$(OBJCOPY) -O binary $^ $@ %.hex: % - $(OBJCOPY) -O ihex $^ $@ + @echo " OBJCOPY $@" + $(Q)$(OBJCOPY) -O ihex $^ $@ .PHONY: clean host_clean all_platforms clean: host_clean - -$(RM) *.o *.d *~ blackmagic $(HOSTFILES) - -$(RM) platforms/*/*.o platforms/*/*.d mapfile + $(Q)echo " CLEAN" + -$(Q)$(RM) -f *.o *.d *~ blackmagic $(HOSTFILES) + -$(Q)$(RM) -f platforms/*/*.o platforms/*/*.d mapfile all_platforms: - set -e ;\ + $(Q)set -e ;\ for i in platforms/*/Makefile.inc ; do \ export DIRNAME=`dirname $$i` ;\ export PROBE_HOST=`basename $$DIRNAME` ;\ export CFLAGS=-Werror ;\ - echo $$PROBE_HOST ;\ - $(MAKE) clean ;\ - $(MAKE) ;\ + echo "Building for hardware platform: $$PROBE_HOST" ;\ + $(MAKE) $(MAKEFLAGS) clean ;\ + $(MAKE) $(MAKEFLAGS);\ if [ -f blackmagic.bin ]; then \ mv blackmagic.bin blackmagic-$$PROBE_HOST.bin ;\ fi ;\ diff --git a/src/platforms/f4discovery/Makefile.inc b/src/platforms/f4discovery/Makefile.inc index 01b3f61..e2bebfd 100644 --- a/src/platforms/f4discovery/Makefile.inc +++ b/src/platforms/f4discovery/Makefile.inc @@ -25,4 +25,4 @@ SRC += cdcacm.c \ all: blackmagic.bin host_clean: - -rm blackmagic.bin + -$(Q)$(RM) blackmagic.bin diff --git a/src/platforms/native/Makefile.inc b/src/platforms/native/Makefile.inc index b5c5c33..6ec60b1 100644 --- a/src/platforms/native/Makefile.inc +++ b/src/platforms/native/Makefile.inc @@ -24,9 +24,9 @@ SRC += cdcacm.c \ all: blackmagic.bin blackmagic_dfu.bin blackmagic_dfu.hex blackmagic_dfu: usbdfu.o dfucore.o dfu_f1.o - $(CC) $^ -o $@ $(LDFLAGS_BOOT) - + @echo " LD $@" + $(Q)$(CC) $^ -o $@ $(LDFLAGS_BOOT) host_clean: - -rm blackmagic.bin blackmagic_dfu blackmagic_dfu.bin blackmagic_dfu.hex + -$(Q)$(RM) -f blackmagic.bin blackmagic_dfu blackmagic_dfu.bin blackmagic_dfu.hex diff --git a/src/platforms/stlink/Makefile.inc b/src/platforms/stlink/Makefile.inc index 5b2e61f..40635cf 100644 --- a/src/platforms/stlink/Makefile.inc +++ b/src/platforms/stlink/Makefile.inc @@ -23,11 +23,13 @@ SRC += cdcacm.c \ all: blackmagic.bin blackmagic_dfu.bin blackmagic_dfu.hex dfu_upgrade.bin dfu_upgrade.hex blackmagic_dfu: usbdfu.o dfucore.o dfu_f1.o - $(CC) $^ -o $@ $(LDFLAGS_BOOT) + @echo " LD $@" + $(Q)$(CC) $^ -o $@ $(LDFLAGS_BOOT) dfu_upgrade: dfu_upgrade.o dfucore.o dfu_f1.o - $(CC) $^ -o $@ $(LDFLAGS) + @echo " LD $@" + $(Q)$(CC) $^ -o $@ $(LDFLAGS) host_clean: - -rm blackmagic.bin blackmagic_dfu blackmagic_dfu.bin blackmagic_dfu.hex dfu_upgrade dfu_upgrade.bin dfu_upgrade.hex + -$(Q)$(RM) blackmagic.bin blackmagic_dfu blackmagic_dfu.bin blackmagic_dfu.hex dfu_upgrade dfu_upgrade.bin dfu_upgrade.hex diff --git a/src/platforms/swlink/Makefile.inc b/src/platforms/swlink/Makefile.inc index c415ecd..ca793d4 100644 --- a/src/platforms/swlink/Makefile.inc +++ b/src/platforms/swlink/Makefile.inc @@ -23,8 +23,9 @@ SRC += cdcacm.c \ all: blackmagic.bin blackmagic_dfu.bin blackmagic_dfu.hex blackmagic_dfu: usbdfu.o dfucore.o dfu_f1.o - $(CC) $^ -o $@ $(LDFLAGS_BOOT) + @echo " LD $@" + $(Q)$(CC) $^ -o $@ $(LDFLAGS_BOOT) host_clean: - -rm blackmagic.bin blackmagic_dfu blackmagic_dfu.bin blackmagic_dfu.hex + -$(Q)$(RM) blackmagic.bin blackmagic_dfu blackmagic_dfu.bin blackmagic_dfu.hex -- cgit v1.2.3 From e0a8ce5a887cb31f38077cd22271fd894070e0e9 Mon Sep 17 00:00:00 2001 From: Marc Singer Date: Fri, 19 Dec 2014 16:25:22 -0800 Subject: STM32L0x target support. Target support for stm32l0's and stm32l1's including option bytes and data EEPROM. This module will superceed the previous stm32l1 driver. o Program flash write and erase. o Options modification and interpretive status. o Stubs for program flash writes and erases. Stubs are modestly faster than non-stub version. The stm32l0 will not execute stubs when the MCU has crashed. A monitor option may be used to force non-stub flash writes. o Stubs generated from C++ code and converted to arrays of half-words. o Writes to data EEPROM supoprted when loading segments. o EEPROM data monitor command to write words. o Stubs supported on stm32l1. --- flashstub/README | 16 +- flashstub/code-to-array.pl | 24 + flashstub/stm32l05x-nvm-prog-erase.cc | 93 +++ flashstub/stm32l05x-nvm-prog-erase.stub | 159 +++++ flashstub/stm32l05x-nvm-prog-write.cc | 112 ++++ flashstub/stm32l05x-nvm-prog-write.stub | 201 ++++++ src/Makefile | 1 + src/cortexm.c | 1 + src/include/stm32lx-nvm.h | 201 ++++++ src/include/target.h | 1 + src/stm32l0.c | 1076 +++++++++++++++++++++++++++++++ 11 files changed, 1881 insertions(+), 4 deletions(-) create mode 100755 flashstub/code-to-array.pl create mode 100644 flashstub/stm32l05x-nvm-prog-erase.cc create mode 100644 flashstub/stm32l05x-nvm-prog-erase.stub create mode 100644 flashstub/stm32l05x-nvm-prog-write.cc create mode 100644 flashstub/stm32l05x-nvm-prog-write.stub create mode 100644 src/include/stm32lx-nvm.h create mode 100644 src/stm32l0.c (limited to 'src') diff --git a/flashstub/README b/flashstub/README index 05172a4..155c8d9 100644 --- a/flashstub/README +++ b/flashstub/README @@ -1,5 +1,13 @@ -These are the assembler routines for executing a flash write -on the supported targets. They are kept here for reference, but -are not used, as the compiled binary code is included in the -target drivers. +Flash Stubs +=========== +For most of the targets, these are assembler routines for executing +a flash write on the supported targets. They are kept here for +reference, but are not used, as the compiled binary code is included +in the target drivers. + +For the STM32l0x, the stubs are written in C++ and emitted as arrays +of half-words for inclusion in the target driver. The use of a higher +level language allows more detailed code and for easy revisions. +These stubs communicate with the driver through a structure defined in +the src/include/stm32l0-nvm.h header. diff --git a/flashstub/code-to-array.pl b/flashstub/code-to-array.pl new file mode 100755 index 0000000..5333e31 --- /dev/null +++ b/flashstub/code-to-array.pl @@ -0,0 +1,24 @@ +#!/usr/bin/perl +# +# Convert the output of objdump to an array of bytes are can include +# into our program. + +while (<>) { + if (m/^\s*([0-9a-fA-F]+):\s*([0-9a-fA-F]+)(.*)/) { + my $addr = "0x$1"; + my $value = $2; + if (length ($value) == 4) { + print " [$addr/2] = 0x$value, // $_"; + } + else { + my $lsb = substr ($value, 4, 4); + my $msb = substr ($value, 0, 4); + print " [$addr/2] = 0x$lsb, // $_"; + print " [$addr/2 + 1] = 0x$msb,\n"; + } + } + else { + print "// ", $_; + } +} + diff --git a/flashstub/stm32l05x-nvm-prog-erase.cc b/flashstub/stm32l05x-nvm-prog-erase.cc new file mode 100644 index 0000000..28c11a3 --- /dev/null +++ b/flashstub/stm32l05x-nvm-prog-erase.cc @@ -0,0 +1,93 @@ +/* @file stm32l05x-nvm-prog-erase.cc + * + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2014 Woollysoft + * Written by Marc Singer + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * 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, see . + */ + +/* ----------- + DESCRIPTION + ----------- + + NVM program flash erase stub for STM32L05x, a Cortex-M0+ core. The + stub uses SRAM to host the code fragment to perform the erase. + + This stub works with the STM32L1xx given a few options. + + If you plan to modify this routine and emit a new stub, make sure + to audit the code. We don't have a stack so we cannot make calls + that save the link pointer. IOW, the inline functions should be be + inlined. + +*/ + +#include +#include +#include "../src/include/stm32lx-nvm.h" + +/* Erase a region of flash. In the event that the erase is misaligned + with respect to pages, it will erase the pages that contain the + requested range of bytes. */ +extern "C" void __attribute((naked)) stm32l05x_nvm_prog_erase () { + // Leave room for INFO at second word of routine + __asm volatile ("b 0f\n\t" + ".align 2\n\t" + ".word 0\n\t" + ".word 0\n\t" + ".word 0\n\t" + ".word 0\n\t" + ".word 0\n\t" + "0:"); + + auto& nvm = Nvm (Info.nvm); + + // Align to the start of the first page so that we make sure to erase + // all of the target pages. + auto remainder = reinterpret_cast (Info.destination) + & (Info.page_size - 1); + Info.size += remainder; + Info.destination -= remainder/sizeof (*Info.destination); + + if (!unlock (nvm)) + goto quit; + + nvm.sr = STM32Lx_NVM_SR_ERR_M; // Clear errors + + // Enable erasing + nvm.pecr = STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE; + if ((nvm.pecr & (STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE)) + != (STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE)) + goto quit; + + while (Info.size > 0) { + *Info.destination = 0; // Initiate erase + + Info.destination += Info.page_size/sizeof (*Info.destination); + Info.size -= Info.page_size; + } + +quit: + lock (nvm); + __asm volatile ("bkpt"); +} + +/* + Local Variables: + compile-command: "/opt/arm/arm-none-eabi-g++ -mcpu=cortex-m0plus -g -c -std=c++11 -mthumb -o stm32l05x-nvm-prog-erase.o -Os -Wa,-ahndl=stm32l05x-nvm-prog-erase.lst stm32l05x-nvm-prog-erase.cc ; /opt/arm/arm-none-eabi-objdump -S stm32l05x-nvm-prog-erase.o | ./code-to-array.pl > stm32l05x-nvm-prog-erase.stub" + End: + +*/ diff --git a/flashstub/stm32l05x-nvm-prog-erase.stub b/flashstub/stm32l05x-nvm-prog-erase.stub new file mode 100644 index 0000000..ebb6fbb --- /dev/null +++ b/flashstub/stm32l05x-nvm-prog-erase.stub @@ -0,0 +1,159 @@ +// +// stm32l05x-nvm-prog-erase.o: file format elf32-littlearm +// +// +// Disassembly of section .text: +// +// 00000000 : +// ".word 0\n\t" +// ".word 0\n\t" +// ".word 0\n\t" +// ".word 0\n\t" +// ".word 0\n\t" +// "0:"); + [0x0/2] = 0xe00a, // 0: e00a b.n 18 + [0x2/2] = 0x46c0, // 2: 46c0 nop ; (mov r8, r8) +// ... +// +// auto& nvm = Nvm (Info.nvm); + [0x18/2] = 0x491a, // 18: 491a ldr r1, [pc, #104] ; (84 ) +// +// // Align to the start of the first page so that we make sure to erase +// // all of the target pages. +// auto remainder = reinterpret_cast (Info.destination) +// & (Info.page_size - 1); + [0x1a/2] = 0x8a08, // 1a: 8a08 ldrh r0, [r1, #16] + [0x1c/2] = 0x680c, // 1c: 680c ldr r4, [r1, #0] +// Info.size += remainder; + [0x1e/2] = 0x684d, // 1e: 684d ldr r5, [r1, #4] +// auto& nvm = Nvm (Info.nvm); +// +// // Align to the start of the first page so that we make sure to erase +// // all of the target pages. +// auto remainder = reinterpret_cast (Info.destination) +// & (Info.page_size - 1); + [0x20/2] = 0x1e42, // 20: 1e42 subs r2, r0, #1 + [0x22/2] = 0x4022, // 22: 4022 ands r2, r4 +// Info.size += remainder; + [0x24/2] = 0x1955, // 24: 1955 adds r5, r2, r5 +// Info.destination -= remainder/sizeof (*Info.destination); + [0x26/2] = 0x0892, // 26: 0892 lsrs r2, r2, #2 + [0x28/2] = 0x0092, // 28: 0092 lsls r2, r2, #2 + [0x2a/2] = 0x1aa2, // 2a: 1aa2 subs r2, r4, r2 + [0x2c/2] = 0x600a, // 2c: 600a str r2, [r1, #0] +// #define Nvm(nvm) (*reinterpret_cast(nvm)) +// #define Info (*reinterpret_cast(STM32Lx_STUB_INFO_PHYS)) +// +// namespace { +// inline __attribute((always_inline)) bool unlock (STM32::NVM& nvm) { +// nvm.pecr = STM32Lx_NVM_PECR_PELOCK; // Lock to guarantee unlock + [0x2e/2] = 0x2201, // 2e: 2201 movs r2, #1 +// ".word 0\n\t" +// ".word 0\n\t" +// ".word 0\n\t" +// "0:"); +// +// auto& nvm = Nvm (Info.nvm); + [0x30/2] = 0x68cb, // 30: 68cb ldr r3, [r1, #12] +// +// // Align to the start of the first page so that we make sure to erase +// // all of the target pages. +// auto remainder = reinterpret_cast (Info.destination) +// & (Info.page_size - 1); +// Info.size += remainder; + [0x32/2] = 0x604d, // 32: 604d str r5, [r1, #4] + [0x34/2] = 0x605a, // 34: 605a str r2, [r3, #4] +// nvm.pkeyr = STM32::NVM::PKEY1; + [0x36/2] = 0x4a14, // 36: 4a14 ldr r2, [pc, #80] ; (88 ) + [0x38/2] = 0x60da, // 38: 60da str r2, [r3, #12] +// nvm.pkeyr = STM32::NVM::PKEY2; + [0x3a/2] = 0x4a14, // 3a: 4a14 ldr r2, [pc, #80] ; (8c ) + [0x3c/2] = 0x60da, // 3c: 60da str r2, [r3, #12] +// nvm.prgkeyr = STM32::NVM::PRGKEY1; + [0x3e/2] = 0x4a14, // 3e: 4a14 ldr r2, [pc, #80] ; (90 ) + [0x40/2] = 0x611a, // 40: 611a str r2, [r3, #16] +// nvm.prgkeyr = STM32::NVM::PRGKEY2; + [0x42/2] = 0x4a14, // 42: 4a14 ldr r2, [pc, #80] ; (94 ) + [0x44/2] = 0x611a, // 44: 611a str r2, [r3, #16] +// return !(nvm.pecr & STM32Lx_NVM_PECR_PRGLOCK); + [0x46/2] = 0x685a, // 46: 685a ldr r2, [r3, #4] +// Info.destination -= remainder/sizeof (*Info.destination); +// +// if (!unlock (nvm)) + [0x48/2] = 0x0792, // 48: 0792 lsls r2, r2, #30 + [0x4a/2] = 0xd502, // 4a: d502 bpl.n 52 +// } +// inline __attribute((always_inline)) void lock (STM32::NVM& nvm) { +// nvm.pecr = STM32Lx_NVM_PECR_PELOCK; } + [0x4c/2] = 0x2201, // 4c: 2201 movs r2, #1 + [0x4e/2] = 0x605a, // 4e: 605a str r2, [r3, #4] +// Info.size -= Info.page_size; +// } +// +// quit: +// lock (nvm); +// __asm volatile ("bkpt"); + [0x50/2] = 0xbe00, // 50: be00 bkpt 0x0000 +// Info.destination -= remainder/sizeof (*Info.destination); +// +// if (!unlock (nvm)) +// goto quit; +// +// nvm.sr = STM32Lx_NVM_SR_ERR_M; // Clear errors + [0x52/2] = 0x4a11, // 52: 4a11 ldr r2, [pc, #68] ; (98 ) + [0x54/2] = 0x619a, // 54: 619a str r2, [r3, #24] +// +// // Enable erasing +// nvm.pecr = STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE; + [0x56/2] = 0x2282, // 56: 2282 movs r2, #130 ; 0x82 + [0x58/2] = 0x0092, // 58: 0092 lsls r2, r2, #2 + [0x5a/2] = 0x605a, // 5a: 605a str r2, [r3, #4] +// if ((nvm.pecr & (STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE)) + [0x5c/2] = 0x685c, // 5c: 685c ldr r4, [r3, #4] + [0x5e/2] = 0x4014, // 5e: 4014 ands r4, r2 + [0x60/2] = 0x4294, // 60: 4294 cmp r4, r2 + [0x62/2] = 0xd1f3, // 62: d1f3 bne.n 4c +// goto quit; +// +// while (Info.size > 0) { +// *Info.destination = 0; // Initiate erase +// +// Info.destination += Info.page_size/sizeof (*Info.destination); + [0x64/2] = 0x0884, // 64: 0884 lsrs r4, r0, #2 + [0x66/2] = 0x00a4, // 66: 00a4 lsls r4, r4, #2 +// nvm.pecr = STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE; +// if ((nvm.pecr & (STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE)) +// != (STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE)) +// goto quit; +// +// while (Info.size > 0) { + [0x68/2] = 0x684d, // 68: 684d ldr r5, [r1, #4] + [0x6a/2] = 0x4a06, // 6a: 4a06 ldr r2, [pc, #24] ; (84 ) + [0x6c/2] = 0x2d00, // 6c: 2d00 cmp r5, #0 + [0x6e/2] = 0xdded, // 6e: dded ble.n 4c +// *Info.destination = 0; // Initiate erase + [0x70/2] = 0x2600, // 70: 2600 movs r6, #0 + [0x72/2] = 0x6815, // 72: 6815 ldr r5, [r2, #0] + [0x74/2] = 0x602e, // 74: 602e str r6, [r5, #0] +// +// Info.destination += Info.page_size/sizeof (*Info.destination); + [0x76/2] = 0x6815, // 76: 6815 ldr r5, [r2, #0] + [0x78/2] = 0x192d, // 78: 192d adds r5, r5, r4 + [0x7a/2] = 0x6015, // 7a: 6015 str r5, [r2, #0] +// Info.size -= Info.page_size; + [0x7c/2] = 0x6855, // 7c: 6855 ldr r5, [r2, #4] + [0x7e/2] = 0x1a2d, // 7e: 1a2d subs r5, r5, r0 + [0x80/2] = 0x6055, // 80: 6055 str r5, [r2, #4] + [0x82/2] = 0xe7f1, // 82: e7f1 b.n 68 + [0x84/2] = 0x0004, // 84: 20000004 .word 0x20000004 + [0x84/2 + 1] = 0x2000, + [0x88/2] = 0xcdef, // 88: 89abcdef .word 0x89abcdef + [0x88/2 + 1] = 0x89ab, + [0x8c/2] = 0x0405, // 8c: 02030405 .word 0x02030405 + [0x8c/2 + 1] = 0x0203, + [0x90/2] = 0xaebf, // 90: 8c9daebf .word 0x8c9daebf + [0x90/2 + 1] = 0x8c9d, + [0x94/2] = 0x1516, // 94: 13141516 .word 0x13141516 + [0x94/2 + 1] = 0x1314, + [0x98/2] = 0x0700, // 98: 00010700 .word 0x00010700 + [0x98/2 + 1] = 0x0001, diff --git a/flashstub/stm32l05x-nvm-prog-write.cc b/flashstub/stm32l05x-nvm-prog-write.cc new file mode 100644 index 0000000..78799d9 --- /dev/null +++ b/flashstub/stm32l05x-nvm-prog-write.cc @@ -0,0 +1,112 @@ +/* @file stm32l05x-nvm-prog-write.cc + * + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2014 Woollysoft + * Written by Marc Singer + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * 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, see . + */ + +/* ----------- + DESCRIPTION + ----------- + + NVM program flash writing stub for STM32L05x, a Cortex-M0+ core. + The stub uses SRAM to host the code fragment and source data to + perform a write to flash. + + This stub works with the STM32L1xx given a few options. + + If you plan to modify this routine and emit a new stub, make sure + to audit the code. We don't have a stack so we cannot make calls + that save the link pointer. IOW, the inline functions should be be + inlined. + +*/ + +#include +#include +#include "../src/include/stm32lx-nvm.h" + +/* Write a block of bytes to flash. The called is responsible for + making sure that the address are aligned and that the count is an + even multiple of words. */ +extern "C" void __attribute((naked)) stm32l05x_nvm_prog_write () { + // Leave room for INFO at second word of routine + __asm volatile ("b 0f\n\t" + ".align 2\n\t" + ".word 0\n\t" + ".word 0\n\t" + ".word 0\n\t" + ".word 0\n\t" + ".word 0\n\t" + "0:"); + + auto& nvm = Nvm (Info.nvm); + + if (!unlock (nvm)) + goto quit; + + nvm.sr = STM32Lx_NVM_SR_ERR_M; // Clear errors + + while (Info.size > 0) { + + // Either we're not half-page aligned or we have less than a half + // page to write + if (Info.size < Info.page_size/2 + || (reinterpret_cast (Info.destination) + & (Info.page_size/2 - 1))) { + nvm.pecr = (Info.options & OPT_STM32L1) ? 0 + : STM32Lx_NVM_PECR_PROG; // Word programming + size_t c = Info.page_size/2 + - (reinterpret_cast (Info.destination) + & (Info.page_size/2 - 1)); + if (c > Info.size) + c = Info.size; + Info.size -= c; + c /= 4; + while (c--) { + uint32_t v = *Info.source++; + *Info.destination++ = v; + if (nvm.sr & STM32Lx_NVM_SR_ERR_M) + goto quit; + } + } + // Or we are writing a half-page(s) + else { + nvm.pecr = STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_FPRG; // Half-page prg + size_t c = Info.size & ~(Info.page_size/2 - 1); + Info.size -= c; + c /= 4; + while (c--) { + uint32_t v = *Info.source++; + *Info.destination++ = v; + } + if (nvm.sr & STM32Lx_NVM_SR_ERR_M) + goto quit; + } + } + +quit: + lock (nvm); + __asm volatile ("bkpt"); +} + +/* + Local Variables: + compile-command: "/opt/arm/arm-none-eabi-g++ -mcpu=cortex-m0plus -g -c -std=c++11 -mthumb -o stm32l05x-nvm-prog-write.o -Os -Wa,-ahndl=stm32l05x-nvm-prog-write.lst stm32l05x-nvm-prog-write.cc ; /opt/arm/arm-none-eabi-objdump -S stm32l05x-nvm-prog-write.o | ./code-to-array.pl > stm32l05x-nvm-prog-write.stub" + End: + +*/ diff --git a/flashstub/stm32l05x-nvm-prog-write.stub b/flashstub/stm32l05x-nvm-prog-write.stub new file mode 100644 index 0000000..6fd661f --- /dev/null +++ b/flashstub/stm32l05x-nvm-prog-write.stub @@ -0,0 +1,201 @@ +// +// stm32l05x-nvm-prog-write.o: file format elf32-littlearm +// +// +// Disassembly of section .text: +// +// 00000000 : +// ".word 0\n\t" +// ".word 0\n\t" +// ".word 0\n\t" +// ".word 0\n\t" +// ".word 0\n\t" +// "0:"); + [0x0/2] = 0xe00a, // 0: e00a b.n 18 + [0x2/2] = 0x46c0, // 2: 46c0 nop ; (mov r8, r8) +// ... +// #define Nvm(nvm) (*reinterpret_cast(nvm)) +// #define Info (*reinterpret_cast(STM32Lx_STUB_INFO_PHYS)) +// +// namespace { +// inline __attribute((always_inline)) bool unlock (STM32::NVM& nvm) { +// nvm.pecr = STM32Lx_NVM_PECR_PELOCK; // Lock to guarantee unlock + [0x18/2] = 0x2201, // 18: 2201 movs r2, #1 +// +// auto& nvm = Nvm (Info.nvm); + [0x1a/2] = 0x4b2a, // 1a: 4b2a ldr r3, [pc, #168] ; (c4 ) + [0x1c/2] = 0x68d9, // 1c: 68d9 ldr r1, [r3, #12] + [0x1e/2] = 0x604a, // 1e: 604a str r2, [r1, #4] +// nvm.pkeyr = STM32::NVM::PKEY1; + [0x20/2] = 0x4a29, // 20: 4a29 ldr r2, [pc, #164] ; (c8 ) + [0x22/2] = 0x60ca, // 22: 60ca str r2, [r1, #12] +// nvm.pkeyr = STM32::NVM::PKEY2; + [0x24/2] = 0x4a29, // 24: 4a29 ldr r2, [pc, #164] ; (cc ) + [0x26/2] = 0x60ca, // 26: 60ca str r2, [r1, #12] +// nvm.prgkeyr = STM32::NVM::PRGKEY1; + [0x28/2] = 0x4a29, // 28: 4a29 ldr r2, [pc, #164] ; (d0 ) + [0x2a/2] = 0x610a, // 2a: 610a str r2, [r1, #16] +// nvm.prgkeyr = STM32::NVM::PRGKEY2; + [0x2c/2] = 0x4a29, // 2c: 4a29 ldr r2, [pc, #164] ; (d4 ) + [0x2e/2] = 0x610a, // 2e: 610a str r2, [r1, #16] +// return !(nvm.pecr & STM32Lx_NVM_PECR_PRGLOCK); + [0x30/2] = 0x684a, // 30: 684a ldr r2, [r1, #4] +// +// if (!unlock (nvm)) + [0x32/2] = 0x0792, // 32: 0792 lsls r2, r2, #30 + [0x34/2] = 0xd502, // 34: d502 bpl.n 3c +// } +// inline __attribute((always_inline)) void lock (STM32::NVM& nvm) { +// nvm.pecr = STM32Lx_NVM_PECR_PELOCK; } + [0x36/2] = 0x2301, // 36: 2301 movs r3, #1 + [0x38/2] = 0x604b, // 38: 604b str r3, [r1, #4] +// } +// } +// +// quit: +// lock (nvm); +// __asm volatile ("bkpt"); + [0x3a/2] = 0xbe00, // 3a: be00 bkpt 0x0000 +// auto& nvm = Nvm (Info.nvm); +// +// if (!unlock (nvm)) +// goto quit; +// +// nvm.sr = STM32Lx_NVM_SR_ERR_M; // Clear errors + [0x3c/2] = 0x4826, // 3c: 4826 ldr r0, [pc, #152] ; (d8 ) + [0x3e/2] = 0x6188, // 3e: 6188 str r0, [r1, #24] +// +// while (Info.size > 0) { + [0x40/2] = 0x685d, // 40: 685d ldr r5, [r3, #4] + [0x42/2] = 0x4e20, // 42: 4e20 ldr r6, [pc, #128] ; (c4 ) + [0x44/2] = 0x2d00, // 44: 2d00 cmp r5, #0 + [0x46/2] = 0xddf6, // 46: ddf6 ble.n 36 +// +// // Either we're not half-page aligned or we have less than a half +// // page to write +// if (Info.size < Info.page_size/2 + [0x48/2] = 0x8a32, // 48: 8a32 ldrh r2, [r6, #16] + [0x4a/2] = 0x0852, // 4a: 0852 lsrs r2, r2, #1 + [0x4c/2] = 0x1e54, // 4c: 1e54 subs r4, r2, #1 + [0x4e/2] = 0x4295, // 4e: 4295 cmp r5, r2 + [0x50/2] = 0xdb02, // 50: db02 blt.n 58 +// || (reinterpret_cast (Info.destination) + [0x52/2] = 0x6837, // 52: 6837 ldr r7, [r6, #0] + [0x54/2] = 0x4227, // 54: 4227 tst r7, r4 + [0x56/2] = 0xd01d, // 56: d01d beq.n 94 +// & (Info.page_size/2 - 1))) { +// nvm.pecr = (Info.options & OPT_STM32L1) ? 0 +// : STM32Lx_NVM_PECR_PROG; // Word programming + [0x58/2] = 0x2602, // 58: 2602 movs r6, #2 +// // Either we're not half-page aligned or we have less than a half +// // page to write +// if (Info.size < Info.page_size/2 +// || (reinterpret_cast (Info.destination) +// & (Info.page_size/2 - 1))) { +// nvm.pecr = (Info.options & OPT_STM32L1) ? 0 + [0x5a/2] = 0x8a5f, // 5a: 8a5f ldrh r7, [r3, #18] +// : STM32Lx_NVM_PECR_PROG; // Word programming + [0x5c/2] = 0x4037, // 5c: 4037 ands r7, r6 + [0x5e/2] = 0x427e, // 5e: 427e negs r6, r7 + [0x60/2] = 0x417e, // 60: 417e adcs r6, r7 + [0x62/2] = 0x00f6, // 62: 00f6 lsls r6, r6, #3 + [0x64/2] = 0x604e, // 64: 604e str r6, [r1, #4] +// size_t c = Info.page_size/2 +// - (reinterpret_cast (Info.destination) +// & (Info.page_size/2 - 1)); + [0x66/2] = 0x681e, // 66: 681e ldr r6, [r3, #0] + [0x68/2] = 0x4034, // 68: 4034 ands r4, r6 + [0x6a/2] = 0x1b12, // 6a: 1b12 subs r2, r2, r4 + [0x6c/2] = 0x42aa, // 6c: 42aa cmp r2, r5 + [0x6e/2] = 0xd900, // 6e: d900 bls.n 72 + [0x70/2] = 0x1c2a, // 70: 1c2a adds r2, r5, #0 +// if (c > Info.size) +// c = Info.size; +// Info.size -= c; + [0x72/2] = 0x1aad, // 72: 1aad subs r5, r5, r2 + [0x74/2] = 0x605d, // 74: 605d str r5, [r3, #4] +// c /= 4; + [0x76/2] = 0x0892, // 76: 0892 lsrs r2, r2, #2 +// while (c--) { + [0x78/2] = 0x3a01, // 78: 3a01 subs r2, #1 + [0x7a/2] = 0xd3e1, // 7a: d3e1 bcc.n 40 +// uint32_t v = *Info.source++; + [0x7c/2] = 0x689c, // 7c: 689c ldr r4, [r3, #8] + [0x7e/2] = 0x1d25, // 7e: 1d25 adds r5, r4, #4 + [0x80/2] = 0x609d, // 80: 609d str r5, [r3, #8] + [0x82/2] = 0x6825, // 82: 6825 ldr r5, [r4, #0] +// *Info.destination++ = v; + [0x84/2] = 0x681c, // 84: 681c ldr r4, [r3, #0] + [0x86/2] = 0x1d26, // 86: 1d26 adds r6, r4, #4 + [0x88/2] = 0x601e, // 88: 601e str r6, [r3, #0] + [0x8a/2] = 0x6025, // 8a: 6025 str r5, [r4, #0] +// if (nvm.sr & STM32Lx_NVM_SR_ERR_M) + [0x8c/2] = 0x698c, // 8c: 698c ldr r4, [r1, #24] + [0x8e/2] = 0x4204, // 8e: 4204 tst r4, r0 + [0x90/2] = 0xd0f2, // 90: d0f2 beq.n 78 + [0x92/2] = 0xe7d0, // 92: e7d0 b.n 36 +// goto quit; +// } +// } +// // Or we are writing a half-page(s) +// else { +// nvm.pecr = STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_FPRG; // Half-page prg + [0x94/2] = 0x2481, // 94: 2481 movs r4, #129 ; 0x81 +// size_t c = Info.size & ~(Info.page_size/2 - 1); + [0x96/2] = 0x4252, // 96: 4252 negs r2, r2 + [0x98/2] = 0x402a, // 98: 402a ands r2, r5 +// Info.size -= c; + [0x9a/2] = 0x1aad, // 9a: 1aad subs r5, r5, r2 +// goto quit; +// } +// } +// // Or we are writing a half-page(s) +// else { +// nvm.pecr = STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_FPRG; // Half-page prg + [0x9c/2] = 0x00e4, // 9c: 00e4 lsls r4, r4, #3 + [0x9e/2] = 0x604c, // 9e: 604c str r4, [r1, #4] +// size_t c = Info.size & ~(Info.page_size/2 - 1); +// Info.size -= c; +// c /= 4; + [0xa0/2] = 0x0892, // a0: 0892 lsrs r2, r2, #2 +// } +// // Or we are writing a half-page(s) +// else { +// nvm.pecr = STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_FPRG; // Half-page prg +// size_t c = Info.size & ~(Info.page_size/2 - 1); +// Info.size -= c; + [0xa2/2] = 0x6075, // a2: 6075 str r5, [r6, #4] +// c /= 4; +// while (c--) { + [0xa4/2] = 0x3a01, // a4: 3a01 subs r2, #1 + [0xa6/2] = 0xd308, // a6: d308 bcc.n ba +// uint32_t v = *Info.source++; + [0xa8/2] = 0x689c, // a8: 689c ldr r4, [r3, #8] + [0xaa/2] = 0x1d25, // aa: 1d25 adds r5, r4, #4 + [0xac/2] = 0x609d, // ac: 609d str r5, [r3, #8] + [0xae/2] = 0x6825, // ae: 6825 ldr r5, [r4, #0] +// *Info.destination++ = v; + [0xb0/2] = 0x681c, // b0: 681c ldr r4, [r3, #0] + [0xb2/2] = 0x1d26, // b2: 1d26 adds r6, r4, #4 + [0xb4/2] = 0x601e, // b4: 601e str r6, [r3, #0] + [0xb6/2] = 0x6025, // b6: 6025 str r5, [r4, #0] + [0xb8/2] = 0xe7f4, // b8: e7f4 b.n a4 +// } +// if (nvm.sr & STM32Lx_NVM_SR_ERR_M) + [0xba/2] = 0x698a, // ba: 698a ldr r2, [r1, #24] + [0xbc/2] = 0x4202, // bc: 4202 tst r2, r0 + [0xbe/2] = 0xd0bf, // be: d0bf beq.n 40 + [0xc0/2] = 0xe7b9, // c0: e7b9 b.n 36 + [0xc2/2] = 0x46c0, // c2: 46c0 nop ; (mov r8, r8) + [0xc4/2] = 0x0004, // c4: 20000004 .word 0x20000004 + [0xc4/2 + 1] = 0x2000, + [0xc8/2] = 0xcdef, // c8: 89abcdef .word 0x89abcdef + [0xc8/2 + 1] = 0x89ab, + [0xcc/2] = 0x0405, // cc: 02030405 .word 0x02030405 + [0xcc/2 + 1] = 0x0203, + [0xd0/2] = 0xaebf, // d0: 8c9daebf .word 0x8c9daebf + [0xd0/2 + 1] = 0x8c9d, + [0xd4/2] = 0x1516, // d4: 13141516 .word 0x13141516 + [0xd4/2 + 1] = 0x1314, + [0xd8/2] = 0x0700, // d8: 00010700 .word 0x00010700 + [0xd8/2 + 1] = 0x0001, diff --git a/src/Makefile b/src/Makefile index 2d3e6b7..7a1f141 100644 --- a/src/Makefile +++ b/src/Makefile @@ -41,6 +41,7 @@ SRC = \ samd.c \ stm32f1.c \ stm32f4.c \ + stm32l0.c \ stm32l1.c \ swdptap.c \ target.c \ diff --git a/src/cortexm.c b/src/cortexm.c index a016342..71d0c6c 100644 --- a/src/cortexm.c +++ b/src/cortexm.c @@ -251,6 +251,7 @@ cortexm_probe(struct target_s *target) PROBE(stm32f1_probe); PROBE(stm32f4_probe); + PROBE(stm32l0_probe); /* STM32L0xx & STM32L1xx */ PROBE(stm32l1_probe); PROBE(lpc11xx_probe); PROBE(lpc43xx_probe); diff --git a/src/include/stm32lx-nvm.h b/src/include/stm32lx-nvm.h new file mode 100644 index 0000000..126f2ab --- /dev/null +++ b/src/include/stm32lx-nvm.h @@ -0,0 +1,201 @@ +/* @file stm32lx-nvm.h + * + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2014 Woollysoft + * Written by Marc Singer + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * 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, see . + */ + +#if !defined (STM32Lx_NVM_H_INCLUDED) +# define STM32Lx_NVM_H_INCLUDED + +/* ----- Includes */ + +#include + +/* ----- Macros */ + +/* ----- Types */ + +enum { + STM32Lx_STUB_PHYS = 0x20000000ul, + STM32Lx_STUB_INFO_PHYS = 0x20000004ul, + STM32Lx_STUB_DATA_PHYS = (0x20000000ul + 1024), + STM32Lx_STUB_DATA_MAX = 2048, + + STM32Lx_NVM_OPT_PHYS = 0x1ff80000ul, + STM32Lx_NVM_EEPROM_PHYS = 0x08080000ul, + + STM32L0_NVM_PHYS = 0x40022000ul, + STM32L0_NVM_PROG_PAGE_SIZE = 128, + STM32L0_NVM_DATA_PAGE_SIZE = 4, + STM32L0_NVM_OPT_SIZE = 12, + STM32L0_NVM_EEPROM_SIZE = 2*1024, + + STM32L1_NVM_PHYS = 0x40023c00ul, + STM32L1_NVM_PROG_PAGE_SIZE = 256, + STM32L1_NVM_DATA_PAGE_SIZE = 4, + STM32L1_NVM_OPT_SIZE = 32, + STM32L1_NVM_EEPROM_SIZE = 16*1024, + + STM32Lx_NVM_PEKEY1 = 0x89abcdeful, + STM32Lx_NVM_PEKEY2 = 0x02030405ul, + STM32Lx_NVM_PRGKEY1 = 0x8c9daebful, + STM32Lx_NVM_PRGKEY2 = 0x13141516ul, + STM32Lx_NVM_OPTKEY1 = 0xfbead9c8ul, + STM32Lx_NVM_OPTKEY2 = 0x24252627ul, + + STM32Lx_NVM_PECR_OBL_LAUNCH = (1<<18), + STM32Lx_NVM_PECR_ERRIE = (1<<17), + STM32Lx_NVM_PECR_EOPIE = (1<<16), + STM32Lx_NVM_PECR_FPRG = (1<<10), + STM32Lx_NVM_PECR_ERASE = (1<< 9), + STM32Lx_NVM_PECR_FIX = (1<< 8), /* FTDW */ + STM32Lx_NVM_PECR_DATA = (1<< 4), + STM32Lx_NVM_PECR_PROG = (1<< 3), + STM32Lx_NVM_PECR_OPTLOCK = (1<< 2), + STM32Lx_NVM_PECR_PRGLOCK = (1<< 1), + STM32Lx_NVM_PECR_PELOCK = (1<< 0), + + STM32Lx_NVM_SR_FWWERR = (1<<17), + STM32Lx_NVM_SR_NOTZEROERR = (1<<16), + STM32Lx_NVM_SR_RDERR = (1<<13), + STM32Lx_NVM_SR_OPTVER = (1<<11), + STM32Lx_NVM_SR_SIZERR = (1<<10), + STM32Lx_NVM_SR_PGAERR = (1<<9), + STM32Lx_NVM_SR_WRPERR = (1<<8), + STM32Lx_NVM_SR_READY = (1<<3), + STM32Lx_NVM_SR_HWOFF = (1<<2), + STM32Lx_NVM_SR_EOP = (1<<1), + STM32Lx_NVM_SR_BSY = (1<<0), + STM32Lx_NVM_SR_ERR_M = ( STM32Lx_NVM_SR_WRPERR + | STM32Lx_NVM_SR_PGAERR + | STM32Lx_NVM_SR_SIZERR + | STM32Lx_NVM_SR_NOTZEROERR), + + STM32L0_NVM_OPTR_BOOT1 = (1<<31), + STM32L0_NVM_OPTR_WDG_SW = (1<<20), + STM32L0_NVM_OPTR_WPRMOD = (1<<8), + STM32L0_NVM_OPTR_RDPROT_S = (0), + STM32L0_NVM_OPTR_RDPROT_M = (0xff), + STM32L0_NVM_OPTR_RDPROT_0 = (0xaa), + STM32L0_NVM_OPTR_RDPROT_2 = (0xcc), + + STM32L1_NVM_OPTR_nBFB2 = (1<<23), + STM32L1_NVM_OPTR_nRST_STDBY = (1<<22), + STM32L1_NVM_OPTR_nRST_STOP = (1<<21), + STM32L1_NVM_OPTR_WDG_SW = (1<<20), + STM32L1_NVM_OPTR_BOR_LEV_S = (16), + STM32L1_NVM_OPTR_BOR_LEV_M = (0xf), + STM32L1_NVM_OPTR_SPRMOD = (1<<8), + STM32L1_NVM_OPTR_RDPROT_S = (0), + STM32L1_NVM_OPTR_RDPROT_M = (0xff), + STM32L1_NVM_OPTR_RDPROT_0 = (0xaa), + STM32L1_NVM_OPTR_RDPROT_2 = (0xcc), + +}; + +#if defined (__cplusplus) + +namespace STM32 { + struct NVM { + volatile uint32_t acr; + volatile uint32_t pecr; + volatile uint32_t pdkeyr; + volatile uint32_t pkeyr; + volatile uint32_t prgkeyr; + volatile uint32_t optkeyr; + volatile uint32_t sr; + volatile uint32_t optr; + volatile uint32_t wrprot; + + static constexpr uint32_t PKEY1 = 0x89abcdef; + static constexpr uint32_t PKEY2 = 0x02030405; + static constexpr uint32_t PRGKEY1 = 0x8c9daebf; + static constexpr uint32_t PRGKEY2 = 0x13141516; + static constexpr uint32_t OPTKEY1 = 0xfbead9c8; + static constexpr uint32_t OPTKEY2 = 0x24252627; + static constexpr uint32_t PDKEY1 = 0x04152637; + static constexpr uint32_t PDKEY2 = 0xfafbfcfd; + }; + + static_assert(sizeof (NVM) == 9*4, "NVM size error"); +} +using stm32lx_stub_pointer_t = uint32_t*; + +#define Nvm(nvm) (*reinterpret_cast(nvm)) +#define Info (*reinterpret_cast(STM32Lx_STUB_INFO_PHYS)) + +namespace { + inline __attribute((always_inline)) bool unlock (STM32::NVM& nvm) { + nvm.pecr = STM32Lx_NVM_PECR_PELOCK; // Lock to guarantee unlock + nvm.pkeyr = STM32::NVM::PKEY1; + nvm.pkeyr = STM32::NVM::PKEY2; + nvm.prgkeyr = STM32::NVM::PRGKEY1; + nvm.prgkeyr = STM32::NVM::PRGKEY2; + return !(nvm.pecr & STM32Lx_NVM_PECR_PRGLOCK); + } + inline __attribute((always_inline)) void lock (STM32::NVM& nvm) { + nvm.pecr = STM32Lx_NVM_PECR_PELOCK; } + +} + +#else + +typedef uint32_t stm32lx_stub_pointer_t; + +struct stm32lx_nvm { + volatile uint32_t acr; + volatile uint32_t pecr; + volatile uint32_t pdkeyr; + volatile uint32_t pekeyr; + volatile uint32_t prgkeyr; + volatile uint32_t optkeyr; + volatile uint32_t sr; + volatile uint32_t optr; /* or obr */ + volatile uint32_t wrprot; /* or wprot1 */ +}; + +#define STM32Lx_NVM(p) (*(struct stm32lx_nvm*) (p)) +#define STM32Lx_NVM_PECR(p) ((uint32_t) &STM32Lx_NVM(p).pecr) +#define STM32Lx_NVM_PEKEYR(p) ((uint32_t) &STM32Lx_NVM(p).pekeyr) +#define STM32Lx_NVM_PRGKEYR(p) ((uint32_t) &STM32Lx_NVM(p).prgkeyr) +#define STM32Lx_NVM_OPTKEYR(p) ((uint32_t) &STM32Lx_NVM(p).optkeyr) +#define STM32Lx_NVM_SR(p) ((uint32_t) &STM32Lx_NVM(p).sr) +#define STM32Lx_NVM_OPTR(p) ((uint32_t) &STM32Lx_NVM(p).optr) + +#endif + +enum { + OPT_STM32L1 = 1<<1, +}; + +struct stm32lx_nvm_stub_info { + stm32lx_stub_pointer_t destination; + int32_t size; + stm32lx_stub_pointer_t source; + uint32_t nvm; + uint16_t page_size; + uint16_t options; +} __attribute__((packed)); + +/* ----- Globals */ + +/* ----- Prototypes */ + + + +#endif /* STM32Lx_NVM_H_INCLUDED */ diff --git a/src/include/target.h b/src/include/target.h index 0e6d9c2..a2369e3 100644 --- a/src/include/target.h +++ b/src/include/target.h @@ -216,6 +216,7 @@ void target_add_commands(target *t, const struct command_s *cmds, const char *na bool cortexm_probe(struct target_s *target); bool stm32f1_probe(struct target_s *target); bool stm32f4_probe(struct target_s *target); +bool stm32l0_probe(struct target_s *target); bool stm32l1_probe(struct target_s *target); bool lmi_probe(struct target_s *target); bool lpc11xx_probe(struct target_s *target); diff --git a/src/stm32l0.c b/src/stm32l0.c new file mode 100644 index 0000000..0f6dcdb --- /dev/null +++ b/src/stm32l0.c @@ -0,0 +1,1076 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2014,2015 Marc Singer + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * 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, see . + */ + +/* Description + ----------- + + This is an implementation of the target-specific functions for the + STM32L0x[1] and STM32L1x[2] families of ST Microelectronics MCUs, + Cortex M0+ SOCs. The NVM interface is substantially similar to the + STM32L1x parts. This module is written to better generalize the + NVM interface and to provide more features. + + [1] ST Microelectronics Document RM0377 (DocID025942), "Reference + manual for Ultra-low-power STM32L0x1 advanced ARM-based 32-bit + MCUs," April 2014. + + [2] ST Microelectronics Document RM0038 (DocID15965, "..."Reference + manual for STM32L100xx, STM32L151xx, STM32L152xx and STM32L162xx + advanced ARM®-based 32-bit MCUs, " July 2014 + + + NOTES + ===== + + o Stubbed and non-stubbed NVM operation functions. The STM32L0xx + appears to behave differently from other STM32 cores. When it + enters a fault state it will not exit this state without a + reset. However, the reset will immediately enter a fault state + if program flash is erased. When in this state, it will not + permit execution of code in RAM in the way that other cores + will. Changing the PC to the start of RAM and single stepping + will immediately HardFault. + + The stub functions can be both faster and simpler because they + have direct access to the MCU. So, to permit stub operation in + the best circumstances, the NVM operation functions will check + the MCU state and either execute the stub or non-stub version + accordingly. The user can override stubs as well with a command + in case the detection feature fails. + + o Erase would be more efficient if we checked for non-blank-ness + before initiating an erase. This would have to be done in a stub + for efficiency. + + o Mass erase broken. The method for performing a mass erase is to + set the options for read protection, reload the option bytes, set + options for no protection, and then reload the option bytes + again. The command fails because we lose contact with the target + when we perform the option byte reload. For the time being, the + command is disabled. + + o Errors. We probably should clear SR errors immediately after + detecting them. If we don't then we always must wait for the NVM + module to complete the last operation before we can start another. + + o There are minor inconsistencies between the stm32l0 and the + stm32l1 in when handling NVM operations. + + o When we erase or write individual words (not half-pages) on the + stm32l0, we set the PROG bit. On the stm32l1 the PROG bit is + only set when erasing. This is not documented in the register + summaries, but in the functional quick reference. + + o On the STM32L1xx, PECR can only be changed when the NVM + hardware is idle. The STM32L0xx allows the PECR to be updated + while an operation is in progress. + + o Performance. The throughput for writing is not high. We suspect + it may be possible to improve throughput significantly by increasing + the MCU clock. The code, as is, offers a simplicity without + undue knowledge of the inner workings of the MCUs. Increasing + clock frequencies would require substantial knowledge of the + clock tree. + + 0x1ff80000: 0x00aa 0xff55 OK + 0x1ff80004: 0x8070 0x7f8f OK + 0x1ff80008: 0x0000 0xffff OK + OPTR: 0x807000aa, RDPROT 0, WPRMOD 0, WDG_SW 1, BOOT1 1 + + + Options code +p *(int*)0x40022004 = 1 +p *(int*)0x4002200c = 0x89abcdef +p *(int*)0x4002200c = 0x02030405 +p *(int*)0x40022014 = 0xfbead9c8 +p *(int*)0x40022014 = 0x24252627 +p *(int*)0x40022004 = 0x10 +x/4wx 0x40022000 +p *(int*)0x1ff80000 = 0xff5500aa + + l1 program +p *(int*)0x40023c04 = 1 +p *(int*)0x40023c0c = 0x89abcdef +p *(int*)0x40023c0c = 0x02030405 +p *(int*)0x40023c10 = 0x8c9daebf +p *(int*)0x40023c10 = 0x13141516 + + +p *(int*)0x40023c14 = 0xfbead9c8 +p *(int*)0x40023c14 = 0x24252627 + +*/ + +#define CONFIG_STM32L1 /* Include support for STM32L1 */ + +#include +#include +#include + +#include "general.h" +#include "adiv5.h" +#include "target.h" +#include "command.h" + +#include "stm32lx-nvm.h" + +static int inhibit_stubs; + +static int stm32lx_nvm_erase (struct target_s* target, + uint32_t addr, int len); +static int stm32lx_nvm_write (struct target_s* target, + uint32_t destination, + const uint8_t* source, + int size); + +static int stm32lx_nvm_prog_erase (struct target_s* target, + uint32_t addr, int len); +static int stm32lx_nvm_prog_write (struct target_s* target, + uint32_t destination, + const uint8_t* source, + int size); + +static int stm32lx_nvm_prog_erase_stubbed (struct target_s* target, + uint32_t addr, int len); +static int stm32lx_nvm_prog_write_stubbed (struct target_s* target, + uint32_t destination, + const uint8_t* source, + int size); + +static int stm32lx_nvm_data_erase (struct target_s* target, + uint32_t addr, int len); +static int stm32lx_nvm_data_write (struct target_s* target, + uint32_t destination, + const uint8_t* source, + int size); + +//static bool stm32l0_cmd_erase_mass (target* t, int argc, char** argv); +static bool stm32lx_cmd_option (target* t, int argc, char** argv); +static bool stm32lx_cmd_eeprom (target* t, int argc, char** argv); +//static bool stm32l0_cmd_reset (target* t, int argc, char** argv); +static bool stm32lx_cmd_stubs (target* t, int argc, char** argv); + +static const struct command_s stm32lx_cmd_list[] = { + { "stubs", (cmd_handler) stm32lx_cmd_stubs, + "Enable/disable NVM operation stubs" }, +// { "erase_mass", (cmd_handler) stm32l0_cmd_erase_mass, +// "Erase NVM flash and data" }, +// { "reset", (cmd_handler) stm32l0_cmd_reset, "Reset target" }, + { "option", (cmd_handler) stm32lx_cmd_option, + "Manipulate option bytes"}, + { "eeprom", (cmd_handler) stm32lx_cmd_eeprom, + "Manipulate EEPROM (NVM data) memory"}, + { 0 }, +}; + +enum { + STM32L0_DBGMCU_IDCODE_PHYS = 0x40015800, + STM32L1_DBGMCU_IDCODE_PHYS = 0xe0042000, +}; + +static const char stm32l0_driver_str[] = "STM32L0xx"; + +static const char stm32l0_xml_memory_map[] = "" +/* ""*/ + "" + /* Program flash; ranges up to 64KiB (0x10000). */ + " " + " 0x80" + " " + /* Data (EEPROM) NVRAM; ranges up to 2KiB (0x800). */ + " " + " 0x4" + " " + /* SRAM; ranges up to 8KiB (0x2000). */ + " " + ""; + +#if defined (CONFIG_STM32L1) +static const char stm32l1_driver_str[] = "STM32L1xx"; + +static const char stm32l1_xml_memory_map[] = "" +/* ""*/ + "" + /* Program flash; ranges from 32KiB to 512KiB (0x80000). */ + " " + " 0x100" + " " + /* Data (EEPROM) NVRAM; ranges from 2K to 16KiB (0x4000). */ + " " + " 0x4" + " " + /* SRAM; ranges from 4KiB to 80KiB (0x14000). */ + " " + ""; +#endif + +static const uint16_t stm32l0_nvm_prog_write_stub [] = { +#include "../flashstub/stm32l05x-nvm-prog-write.stub" +}; + +static const uint16_t stm32l0_nvm_prog_erase_stub [] = { +#include "../flashstub/stm32l05x-nvm-prog-erase.stub" +}; + +static uint32_t stm32lx_nvm_prog_page_size (struct target_s* target) +{ + switch (target->idcode) { + case 0x417: /* STM32L0xx */ + return STM32L0_NVM_PROG_PAGE_SIZE; + default: /* STM32L1xx */ + return STM32L1_NVM_PROG_PAGE_SIZE; + } +} + +static bool stm32lx_is_stm32l1 (struct target_s* target) +{ + switch (target->idcode) { + case 0x417: /* STM32L0xx */ + return false; + default: /* STM32L1xx */ + return true; + } +} + +static uint32_t stm32lx_nvm_eeprom_size (struct target_s* target) +{ + switch (target->idcode) { + case 0x417: /* STM32L0xx */ + return STM32L0_NVM_EEPROM_SIZE; + default: /* STM32L1xx */ + return STM32L1_NVM_EEPROM_SIZE; + } +} + +static uint32_t stm32lx_nvm_phys (struct target_s* target) +{ + switch (target->idcode) { + case 0x417: /* STM32L0xx */ + return STM32L0_NVM_PHYS; + default: /* STM32L1xx */ + return STM32L1_NVM_PHYS; + } +} + +static uint32_t stm32lx_nvm_data_page_size (struct target_s* target) +{ + switch (target->idcode) { + case 0x417: /* STM32L0xx */ + return STM32L0_NVM_DATA_PAGE_SIZE; + default: /* STM32L1xx */ + return STM32L1_NVM_DATA_PAGE_SIZE; + } +} + +static uint32_t stm32lx_nvm_option_size (struct target_s* target) +{ + switch (target->idcode) { + case 0x417: /* STM32L0xx */ + return STM32L0_NVM_OPT_SIZE; + default: /* STM32L1xx */ + return STM32L1_NVM_OPT_SIZE; + } +} + +/** Query MCU memory for an indication as to whether or not the + currently attached target is served by this module. We detect the + STM32L0xx parts as well as the STM32L1xx's. */ +bool stm32l0_probe (struct target_s* target) +{ + uint32_t idcode; + +#if defined (CONFIG_STM32L1) + + idcode = adiv5_ap_mem_read (adiv5_target_ap (target), + STM32L1_DBGMCU_IDCODE_PHYS) & 0xfff; + switch (idcode) { + case 0x416: /* CAT. 1 device */ + case 0x429: /* CAT. 2 device */ + case 0x427: /* CAT. 3 device */ + case 0x436: /* CAT. 4 device */ + case 0x437: /* CAT. 5 device */ + target->idcode = idcode; + target->driver = stm32l1_driver_str; + target->xml_mem_map = stm32l1_xml_memory_map; + target->flash_erase = stm32lx_nvm_erase; + target->flash_write = stm32lx_nvm_write; + target_add_commands (target, stm32lx_cmd_list, "STM32L1x"); + return true; + } +#endif + + idcode = adiv5_ap_mem_read (adiv5_target_ap (target), + STM32L0_DBGMCU_IDCODE_PHYS) & 0xfff; + switch (idcode) { + default: + break; + + case 0x417: /* STM32L0x[123] & probably others */ + target->idcode = idcode; + target->driver = stm32l0_driver_str; + target->xml_mem_map = stm32l0_xml_memory_map; + target->flash_erase = stm32lx_nvm_erase; + target->flash_write = stm32lx_nvm_write; + target_add_commands (target, stm32lx_cmd_list, "STM32L0x"); + return true; + } + + return false; +} + +/** Lock the NVM control registers preventing writes or erases. */ +static void stm32lx_nvm_lock (ADIv5_AP_t* ap, uint32_t nvm) +{ + adiv5_ap_mem_write (ap, STM32Lx_NVM_PECR(nvm), STM32Lx_NVM_PECR_PELOCK); +} + +/** Unlock the NVM control registers for modifying program or + data flash. Returns true if the unlock succeeds. */ +static bool stm32lx_nvm_prog_data_unlock (ADIv5_AP_t* ap, uint32_t nvm) +{ + /* Always lock first because that's the only way to know that the + unlock can succeed on the STM32L0's. */ + adiv5_ap_mem_write (ap, STM32Lx_NVM_PECR(nvm), STM32Lx_NVM_PECR_PELOCK); + adiv5_ap_mem_write (ap, STM32Lx_NVM_PEKEYR(nvm), STM32Lx_NVM_PEKEY1); + adiv5_ap_mem_write (ap, STM32Lx_NVM_PEKEYR(nvm), STM32Lx_NVM_PEKEY2); + adiv5_ap_mem_write (ap, STM32Lx_NVM_PRGKEYR(nvm), STM32Lx_NVM_PRGKEY1); + adiv5_ap_mem_write (ap, STM32Lx_NVM_PRGKEYR(nvm), STM32Lx_NVM_PRGKEY2); + + return !(adiv5_ap_mem_read (ap, STM32Lx_NVM_PECR(nvm)) + & STM32Lx_NVM_PECR_PRGLOCK); +} + + +/** Unlock the NVM control registers for modifying option bytes. + Returns true if the unlock succeeds. */ +static bool stm32lx_nvm_opt_unlock (ADIv5_AP_t* ap, uint32_t nvm) +{ + /* Always lock first because that's the only way to know that the + unlock can succeed on the STM32L0's. */ + adiv5_ap_mem_write (ap, STM32Lx_NVM_PECR(nvm), STM32Lx_NVM_PECR_PELOCK); + adiv5_ap_mem_write (ap, STM32Lx_NVM_PEKEYR(nvm), STM32Lx_NVM_PEKEY1); + adiv5_ap_mem_write (ap, STM32Lx_NVM_PEKEYR(nvm), STM32Lx_NVM_PEKEY2); + adiv5_ap_mem_write (ap, STM32Lx_NVM_OPTKEYR(nvm), STM32Lx_NVM_OPTKEY1); + adiv5_ap_mem_write (ap, STM32Lx_NVM_OPTKEYR(nvm), STM32Lx_NVM_OPTKEY2); + + return !(adiv5_ap_mem_read (ap, STM32Lx_NVM_PECR(nvm)) + & STM32Lx_NVM_PECR_OPTLOCK); +} + + +/** Erase a region of flash using a stub function. This only works + when the MCU hasn't entered a fault state (see NOTES). The flash + array is erased for all pages from addr to addr+len inclusive. */ +static int stm32lx_nvm_prog_erase_stubbed (struct target_s* target, + uint32_t addr, int size) +{ + struct stm32lx_nvm_stub_info info; + const uint32_t nvm = stm32lx_nvm_phys (target); + + info.nvm = nvm; + info.page_size = stm32lx_nvm_prog_page_size (target); + + /* Load the stub */ + target_mem_write_words (target, STM32Lx_STUB_PHYS, + (void*) &stm32l0_nvm_prog_erase_stub[0], + sizeof (stm32l0_nvm_prog_erase_stub)); + + /* Setup parameters */ + info.destination = addr; + info.size = size; + + /* Copy parameters */ + target_mem_write_words (target, STM32Lx_STUB_INFO_PHYS, + (void*) &info, sizeof (info)); + + /* Execute stub */ + target_pc_write (target, STM32Lx_STUB_PHYS); + if (target_check_error (target)) + return -1; + target_halt_resume (target, 0); + while (!target_halt_wait (target)) + ; + { + ADIv5_AP_t* ap = adiv5_target_ap(target); + if (adiv5_ap_mem_read (ap, STM32Lx_NVM_SR(nvm)) & STM32Lx_NVM_SR_ERR_M) + return -1; + } + + return 0; +} + + +/** Write to program flash using a stub function. This only works + when the MCU hasn't entered a fault state. Once the MCU faults, + this function will not succeed because the MCU will fault before + executing a single instruction in the stub. */ +static int stm32lx_nvm_prog_write_stubbed (struct target_s* target, + uint32_t destination, + const uint8_t* source, + int size) +{ + struct stm32lx_nvm_stub_info info; + const uint32_t nvm = stm32lx_nvm_phys (target); + const size_t page_size = stm32lx_nvm_prog_page_size (target); + + /* We can't handle unaligned destination or non-word writes. */ + /* *** FIXME: we should handle misaligned writes by padding with + *** zeros. Probably, the only real time we'd see something + *** misaligned would be on a write to a final half-word. Perhaps + *** this could be handled with the stub? In fact, aligning the + *** start is going to be mandatory. We will change the code to + *** cope with a trailing half-word. */ + if ((destination & 3) || (size & 3)) + return -1; + + info.nvm = nvm; + info.page_size = page_size; + + /* Load the stub */ + target_mem_write_words (target, STM32Lx_STUB_PHYS, + (void*) &stm32l0_nvm_prog_write_stub[0], + sizeof (stm32l0_nvm_prog_write_stub)); + + while (size > 0) { + + /* Max transfer size is adjusted in the event that the + destination isn't half-page aligned. This allows the + sub to write the first partial half-page and then + as many half-pages as will fit in the buffer. */ + size_t max = STM32Lx_STUB_DATA_MAX + - (destination - (destination & ~(info.page_size/2 - 1))); + size_t cb = size; + if (cb > max) + cb = max; + + /* Setup parameters */ + info.source = STM32Lx_STUB_DATA_PHYS; + info.destination = destination; + info.size = cb; + + /* Copy data to write to flash */ + target_mem_write_words (target, info.source, (void*) source, info.size); + + /* Move pointers early */ + destination += cb; + source += cb; + size -= cb; + + /* Copy parameters */ + target_mem_write_words (target, STM32Lx_STUB_INFO_PHYS, + (void*) &info, sizeof (info)); + + /* Execute stub */ + target_pc_write (target, STM32Lx_STUB_PHYS); + if (target_check_error (target)) + return -1; + target_halt_resume (target, 0); + while (!target_halt_wait (target)) + ; + + if (adiv5_ap_mem_read (adiv5_target_ap (target), STM32Lx_NVM_SR(nvm)) + & STM32Lx_NVM_SR_ERR_M) + return -1; + } + + return 0; +} + + +/** Erase a region of NVM for STM32Lx. This is the lead function and + it will invoke an implementation, stubbed or not depending on the + options and the range of addresses. */ +static int stm32lx_nvm_erase (struct target_s* target, uint32_t addr, int size) +{ + if (addr >= STM32Lx_NVM_EEPROM_PHYS) + return stm32lx_nvm_data_erase (target, addr, size); + + /* Use stub if not inhibited, the MCU is in a non-exceptonal state + and there is stub. */ + volatile uint32_t regs[20]; + target_regs_read (target, ®s); + if (inhibit_stubs || (regs[16] & 0xf)) + return stm32lx_nvm_prog_erase (target, addr, size); + + return stm32lx_nvm_prog_erase_stubbed (target, addr, size); +} + + +/** Write to a region on NVM for STM32L1xx. This is the lead function + and it will ibvoke an implementation, stubbed or not depending on + the options and the range of addresses. */ +static int stm32lx_nvm_write (struct target_s* target, + uint32_t destination, + const uint8_t* source, + int size) +{ + if (destination >= STM32Lx_NVM_EEPROM_PHYS) + return stm32lx_nvm_data_write (target, destination, source, size); + + /* Skip stub if the MCU is in a questionable state or if the user + asks us to avoid stubs. */ + volatile uint32_t regs[20]; + target_regs_read (target, ®s); + if (inhibit_stubs || (regs[16] & 0xf)) + return stm32lx_nvm_prog_write (target, destination, source, size); + + return stm32lx_nvm_prog_write_stubbed (target, destination, source, size); +} + + +/** Erase a region of program flash using operations through the debug + interface. This is slower than stubbed versions (see NOTES). The + flash array is erased for all pages from addr to addr+len + inclusive. NVM register file address chosen from target. */ +static int stm32lx_nvm_prog_erase (struct target_s* target, + uint32_t addr, int len) +{ + ADIv5_AP_t* ap = adiv5_target_ap (target); + const size_t page_size = stm32lx_nvm_prog_page_size (target); + const uint32_t nvm = stm32lx_nvm_phys (target); + + /* Word align */ + len += (addr & 3); + addr &= ~3; + + if (!stm32lx_nvm_prog_data_unlock (ap, nvm)) + return -1; + + /* Flash page erase instruction */ + adiv5_ap_mem_write (ap, STM32Lx_NVM_PECR(nvm), + STM32Lx_NVM_PECR_ERASE | STM32Lx_NVM_PECR_PROG); + + { + uint32_t pecr = adiv5_ap_mem_read (ap, STM32Lx_NVM_PECR (nvm)); + if ((pecr & (STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE)) + != (STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE)) + return -1; + } + + /* Clear errors. Note that this only works when we wait for the NVM + block to complete the last operation. */ + adiv5_ap_mem_write (ap, STM32Lx_NVM_SR (nvm), STM32Lx_NVM_SR_ERR_M); + + while (len > 0) { + /* Write first word of page to 0 */ + adiv5_ap_mem_write (ap, addr, 0); + + len -= page_size; + addr += page_size; + } + + /* Disable further programming by locking PECR */ + stm32lx_nvm_lock (ap, nvm); + + /* Wait for completion or an error */ + while (1) { + uint32_t sr = adiv5_ap_mem_read (ap, STM32Lx_NVM_SR(nvm)); + if (target_check_error (target)) + return -1; + if (sr & STM32Lx_NVM_SR_BSY) + continue; + if ((sr & STM32Lx_NVM_SR_ERR_M) || !(sr & STM32Lx_NVM_SR_EOP)) + return -1; + break; + } + + return 0; +} + + +/** Write to program flash using operations through the debug + interface. This is slower than the stubbed write (see NOTES). + NVM register file address chosen from target. */ +static int stm32lx_nvm_prog_write (struct target_s* target, + uint32_t destination, + const uint8_t* source_8, + int size) +{ + ADIv5_AP_t* ap = adiv5_target_ap (target); + const uint32_t nvm = stm32lx_nvm_phys (target); + const bool is_stm32l1 = stm32lx_is_stm32l1 (target); + + /* We can only handle word aligned writes and even word-multiple + ranges. The stm32l0 cannot perform anything smaller than a word + write due to the ECC bits. */ + if ((destination & 3) || (size & 3)) + return -1; + + if (!stm32lx_nvm_prog_data_unlock (ap, nvm)) + return -1; + + const size_t half_page_size = stm32lx_nvm_prog_page_size (target)/2; + uint32_t* source = (uint32_t*) source_8; + + while (size > 0) { + + /* Wait for BSY to clear because we cannot write the PECR until + the previous operation completes on STM32L1xx. */ + while (adiv5_ap_mem_read (ap, STM32Lx_NVM_SR(nvm)) & STM32Lx_NVM_SR_BSY) + if (target_check_error(target)) { + return -1; + } + + // Either we're not half-page aligned or we have less than a half + // page to write + if (size < half_page_size || (destination & (half_page_size - 1))) { + adiv5_ap_mem_write (ap, STM32Lx_NVM_PECR(nvm), + is_stm32l1 ? 0 : STM32Lx_NVM_PECR_PROG); + size_t c = half_page_size - (destination & (half_page_size - 1)); + + if (c > size) + c = size; + size -= c; + + target_mem_write_words (target, destination, source, c); + source += c/4; + destination += c; + } + // Or we are writing a half-page(s) + else { + adiv5_ap_mem_write (ap, STM32Lx_NVM_PECR (nvm), + STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_FPRG); + + size_t c = size & ~(half_page_size - 1); + size -= c; + target_mem_write_words (target, destination, source, c); + source += c/4; + destination += c; + } + } + + /* Disable further programming by locking PECR */ + stm32lx_nvm_lock (ap, nvm); + + /* Wait for completion or an error */ + while (1) { + uint32_t sr = adiv5_ap_mem_read (ap, STM32Lx_NVM_SR (nvm)); + if (target_check_error (target)) { + return -1; + } + if (sr & STM32Lx_NVM_SR_BSY) + continue; + if ((sr & STM32Lx_NVM_SR_ERR_M) || !(sr & STM32Lx_NVM_SR_EOP)) { + return -1; + } + break; + } + + return 0; +} + + +/** Erase a region of data flash using operations through the debug + interface . The flash is erased for all pages from addr to + addr+len, inclusive, on a word boundary. NVM register file + address chosen from target. */ +static int stm32lx_nvm_data_erase (struct target_s* target, + uint32_t addr, int len) +{ + ADIv5_AP_t* ap = adiv5_target_ap (target); + const size_t page_size = stm32lx_nvm_data_page_size (target); + const uint32_t nvm = stm32lx_nvm_phys (target); + + /* Word align */ + len += (addr & 3); + addr &= ~3; + + if (!stm32lx_nvm_prog_data_unlock (ap, nvm)) + return -1; + + /* Flash data erase instruction */ + adiv5_ap_mem_write (ap, STM32Lx_NVM_PECR(nvm), + STM32Lx_NVM_PECR_ERASE | STM32Lx_NVM_PECR_DATA); + + { + uint32_t pecr = adiv5_ap_mem_read (ap, STM32Lx_NVM_PECR(nvm)); + if ((pecr & (STM32Lx_NVM_PECR_ERASE | STM32Lx_NVM_PECR_DATA)) + != (STM32Lx_NVM_PECR_ERASE | STM32Lx_NVM_PECR_DATA)) + return -1; + } + + while (len > 0) { + /* Write first word of page to 0 */ + adiv5_ap_mem_write (ap, addr, 0); + + len -= page_size; + addr += page_size; + } + + /* Disable further programming by locking PECR */ + stm32lx_nvm_lock (ap, nvm); + + /* Wait for completion or an error */ + while (1) { + uint32_t sr = adiv5_ap_mem_read (ap, STM32Lx_NVM_SR (nvm)); + if (target_check_error (target)) + return -1; + if (sr & STM32Lx_NVM_SR_BSY) + continue; + if ((sr & STM32Lx_NVM_SR_ERR_M) || !(sr & STM32Lx_NVM_SR_EOP)) + return -1; + break; + } + + return 0; +} + + +/** Write to data flash using operations through the debug interface. + NVM register file address chosen from target. + + *** FIXME: need to make this work with writing a single byte as + well as words. */ +static int stm32lx_nvm_data_write (struct target_s* target, + uint32_t destination, + const uint8_t* source_8, + int size) +{ + ADIv5_AP_t* ap = adiv5_target_ap (target); + const uint32_t nvm = stm32lx_nvm_phys (target); + const bool is_stm32l1 = stm32lx_is_stm32l1 (target); + + /* *** FIXME: need to make this work with writing a single byte. */ + if ((destination & 3) || (size & 3)) + return -1; + + if (!stm32lx_nvm_prog_data_unlock (ap, nvm)) + return -1; + + uint32_t* source = (uint32_t*) source_8; + + adiv5_ap_mem_write (ap, STM32Lx_NVM_PECR(nvm), + is_stm32l1 ? 0 : STM32Lx_NVM_PECR_DATA); + + while (size) { + size -= 4; + uint32_t v = *source++; + adiv5_ap_mem_write (ap, destination, v); + destination += 4; + + if (target_check_error (target)) + return -1; + } + + /* Disable further programming by locking PECR */ + stm32lx_nvm_lock (ap, nvm); + + /* Wait for completion or an error */ + while (1) { + uint32_t sr = adiv5_ap_mem_read (ap, STM32Lx_NVM_SR(nvm)); + if (target_check_error (target)) + return -1; + if (sr & STM32Lx_NVM_SR_BSY) + continue; + if ((sr & STM32Lx_NVM_SR_ERR_M) || !(sr & STM32Lx_NVM_SR_EOP)) + return -1; + break; + } + + return 0; +} + + +/** Write one option word. The address is the physical address of the + word and the value is a complete word value. The caller is + responsible for making sure that the value satisfies the proper + format where the upper 16 bits are the 1s complement of the lower + 16 bits. The funtion returns when the operation is complete. + The return value is true if the write succeeded. */ +static bool stm32lx_option_write (target *t, uint32_t address, uint32_t value) +{ + ADIv5_AP_t* ap = adiv5_target_ap(t); + const uint32_t nvm = stm32lx_nvm_phys (t); + + /* Erase and program option in one go. */ + adiv5_ap_mem_write (ap, STM32Lx_NVM_PECR(nvm), STM32Lx_NVM_PECR_FIX); + adiv5_ap_mem_write (ap, address, value); + + uint32_t sr; + do { + sr = adiv5_ap_mem_read (ap, STM32Lx_NVM_SR(nvm)); + } while (sr & STM32Lx_NVM_SR_BSY); + + return !(sr & STM32Lx_NVM_SR_ERR_M); +} + + +/** Write one eeprom value. This version is more flexible than that + bulk version used for writing data from the executable file. The + address is the physical address of the word and the value is a + complete word value. The funtion returns when the operation is + complete. The return value is true if the write succeeded. + FWIW, byte writing isn't supported because the adiv5 layer + doesn't support byte-level operations. */ +static bool stm32lx_eeprom_write (target *t, uint32_t address, + size_t cb, uint32_t value) +{ + ADIv5_AP_t* ap = adiv5_target_ap(t); + const uint32_t nvm = stm32lx_nvm_phys (t); + const bool is_stm32l1 = stm32lx_is_stm32l1 (t); + + /* Clear errors. */ + adiv5_ap_mem_write (ap, STM32Lx_NVM_SR (nvm), STM32Lx_NVM_SR_ERR_M); + + /* Erase and program option in one go. */ + adiv5_ap_mem_write (ap, STM32Lx_NVM_PECR(nvm), + (is_stm32l1 ? 0 : STM32Lx_NVM_PECR_DATA) + | STM32Lx_NVM_PECR_FIX); + if (cb == 4) + adiv5_ap_mem_write (ap, address, value); + else if (cb == 2) + adiv5_ap_mem_write_halfword (ap, address, value); + else + return false; + + uint32_t sr; + do { + sr = adiv5_ap_mem_read (ap, STM32Lx_NVM_SR(nvm)); + } while (sr & STM32Lx_NVM_SR_BSY); + + return !(sr & STM32Lx_NVM_SR_ERR_M); +} + +static bool stm32lx_cmd_stubs (target* t, + int argc, char** argv) +{ + if (argc == 1) { + gdb_out ("usage: mon stubs [enable/disable]\n"); + } + else if (argc == 2) { + size_t cb = strlen (argv[1]); + if (!strncasecmp (argv[1], "enable", cb)) + inhibit_stubs = 0; + if (!strncasecmp (argv[1], "disable", cb)) + inhibit_stubs = 1; + } + gdb_outf ("stubs: %sabled\n", inhibit_stubs ? "dis" : "en"); + + return true; +} + +#if 0 +static bool stm32l0_cmd_erase_mass (target* t, int argc , char** argv) +{ + ADIv5_AP_t* ap = adiv5_target_ap (t); + + stm32lx_nvm_opt_unlock (ap); + + stm32l0_option_write (t, 0x1ff80000, 0xffff0000); + adiv5_ap_mem_write (ap, STM32L0_NVM_PECR, STM32L0_NVM_PECR_OBL_LAUNCH); + stm32l0_option_write (t, 0x1ff80000, 0xff5500aa); + adiv5_ap_mem_write (ap, STM32L0_NVM_PECR, STM32L0_NVM_PECR_OBL_LAUNCH); + + uint32_t sr; + do { + sr = adiv5_ap_mem_read (ap, STM32L0_NVM_SR); + } while (sr & STM32L0_NVM_SR_BSY); + + stm32l0_nvm_lock (ap); + return true; +} +#endif + +#if 0 +static bool stm32l0_cmd_reset (target* t, int argc, char** argv) +{ + gdb_out ("Resetting target\n"); + target_reset (t); + + return true; +} +#endif + +static bool stm32lx_cmd_option (target* t, int argc, char** argv) +{ + ADIv5_AP_t* ap = adiv5_target_ap (t); + const uint32_t nvm = stm32lx_nvm_phys (t); + const size_t opt_size = stm32lx_nvm_option_size (t); + + if (!stm32lx_nvm_opt_unlock (ap, nvm)) { + gdb_out ("unable to unlock NVM option bytes\n"); + return true; + } + + size_t cb = strlen (argv[1]); + + if (argc == 2 && !strncasecmp (argv[1], "obl_launch", cb)) { + adiv5_ap_mem_write (ap, STM32Lx_NVM_PECR(nvm), STM32Lx_NVM_PECR_OBL_LAUNCH); + } + else if (argc == 4 && !strncasecmp (argv[1], "raw", cb)) { + uint32_t addr = strtoul (argv[2], NULL, 0); + uint32_t val = strtoul (argv[3], NULL, 0); + gdb_outf ("raw %08x <- %08x\n", addr, val); + if ( addr < STM32Lx_NVM_OPT_PHYS + || addr >= STM32Lx_NVM_OPT_PHYS + opt_size + || (addr & 3)) + goto usage; + if (!stm32lx_option_write (t, addr, val)) + gdb_out ("option write failed\n"); + } + else if (argc == 4 && !strncasecmp (argv[1], "write", cb)) { + uint32_t addr = strtoul (argv[2], NULL, 0); + uint32_t val = strtoul (argv[3], NULL, 0); + val = (val & 0xffff) | ((~val & 0xffff) << 16); + gdb_outf ("write %08x <- %08x\n", addr, val); + if ( addr < STM32Lx_NVM_OPT_PHYS + || addr >= STM32Lx_NVM_OPT_PHYS + opt_size + || (addr & 3)) + goto usage; + if (!stm32lx_option_write (t, addr, val)) + gdb_out ("option write failed\n"); + } + else if (argc == 2 && !strncasecmp (argv[1], "show", cb)) + ; + else + goto usage; + + /* Report the current option values */ + for (int i = 0; i < opt_size; i += sizeof (uint32_t)) { + uint32_t addr = STM32Lx_NVM_OPT_PHYS + i; + uint32_t val = adiv5_ap_mem_read (ap, addr); + gdb_outf ("0x%08x: 0x%04x 0x%04x %s\n", + addr, val & 0xffff, (val >> 16) & 0xffff, + ((val & 0xffff) == ((~val >> 16) & 0xffff)) ? "OK" : "ERR"); + } + + if (stm32lx_is_stm32l1 (t)) { + uint32_t optr = adiv5_ap_mem_read (ap, STM32Lx_NVM_OPTR(nvm)); + uint8_t rdprot = (optr >> STM32L1_NVM_OPTR_RDPROT_S) + & STM32L1_NVM_OPTR_RDPROT_M; + if (rdprot == STM32L1_NVM_OPTR_RDPROT_0) + rdprot = 0; + else if (rdprot == STM32L1_NVM_OPTR_RDPROT_2) + rdprot = 2; + else + rdprot = 1; + gdb_outf ("OPTR: 0x%08x, RDPRT %d, SPRMD %d, " + "BOR %d, WDG_SW %d, nRST_STP %d, nRST_STBY %d, nBFB2 %d\n", + optr, rdprot, + (optr & STM32L1_NVM_OPTR_SPRMOD) ? 1 : 0, + (optr >> STM32L1_NVM_OPTR_BOR_LEV_S) & STM32L1_NVM_OPTR_BOR_LEV_M, + (optr & STM32L1_NVM_OPTR_WDG_SW) ? 1 : 0, + (optr & STM32L1_NVM_OPTR_nRST_STOP) ? 1 : 0, + (optr & STM32L1_NVM_OPTR_nRST_STDBY) ? 1 : 0, + (optr & STM32L1_NVM_OPTR_nBFB2) ? 1 : 0); + } + else { + uint32_t optr = adiv5_ap_mem_read (ap, STM32Lx_NVM_OPTR(nvm)); + uint8_t rdprot = (optr >> STM32L0_NVM_OPTR_RDPROT_S) + & STM32L0_NVM_OPTR_RDPROT_M; + if (rdprot == STM32L0_NVM_OPTR_RDPROT_0) + rdprot = 0; + else if (rdprot == STM32L0_NVM_OPTR_RDPROT_2) + rdprot = 2; + else + rdprot = 1; + gdb_outf ("OPTR: 0x%08x, RDPROT %d, WPRMOD %d, WDG_SW %d, BOOT1 %d\n", + optr, rdprot, + (optr & STM32L0_NVM_OPTR_WPRMOD) ? 1 : 0, + (optr & STM32L0_NVM_OPTR_WDG_SW) ? 1 : 0, + (optr & STM32L0_NVM_OPTR_BOOT1) ? 1 : 0); + } + + goto done; + + usage: + gdb_out ("usage: monitor option [ARGS]\n"); + gdb_out (" show - Show options in NVM and as loaded\n"); + gdb_out (" obl_launch - Reload options from NVM\n"); + gdb_out (" write - Set option half-word; " + "complement computed\n"); + gdb_out (" raw - Set option word\n"); + gdb_outf ("The value of must be word aligned and from 0x%08x " + "to +0x%x\n", + STM32Lx_NVM_OPT_PHYS, + STM32Lx_NVM_OPT_PHYS + opt_size - sizeof (uint32_t)); + + done: + stm32lx_nvm_lock (ap, nvm); + return true; +} + + +static bool stm32lx_cmd_eeprom (target* t, int argc, char** argv) +{ + ADIv5_AP_t* ap = adiv5_target_ap (t); + const uint32_t nvm = stm32lx_nvm_phys (t); + + if (!stm32lx_nvm_prog_data_unlock (ap, nvm)) { + gdb_out ("unable to unlock EEPROM\n"); + return true; + } + + size_t cb = strlen (argv[1]); + + if (argc == 4) { + uint32_t addr = strtoul (argv[2], NULL, 0); + uint32_t val = strtoul (argv[3], NULL, 0); + + if ( addr < STM32Lx_NVM_EEPROM_PHYS + || addr >= STM32Lx_NVM_EEPROM_PHYS + stm32lx_nvm_eeprom_size (t)) + goto usage; + +#if 0 + if (!strncasecmp (argv[1], "byte", cb)) { + gdb_outf ("write byte 0x%08x <- 0x%08x\n", addr, val); + if (!stm32l0_eeprom_write (t, addr, 1, val)) + gdb_out ("eeprom write failed\n"); + } else +#endif + if (!strncasecmp (argv[1], "halfword", cb)) { + val &= 0xffff; + gdb_outf ("write halfword 0x%08x <- 0x%04x\n", addr, val); + if (addr & 1) + goto usage; + if (!stm32lx_eeprom_write (t, addr, 2, val)) + gdb_out ("eeprom write failed\n"); + } else if (!strncasecmp (argv[1], "word", cb)) { + gdb_outf ("write word 0x%08x <- 0x%08x\n", addr, val); + if (addr & 3) + goto usage; + if (!stm32lx_eeprom_write (t, addr, 4, val)) + gdb_out ("eeprom write failed\n"); + } + else + goto usage; + } + else + goto usage; + + goto done; + + usage: + gdb_out ("usage: monitor eeprom [ARGS]\n"); +// gdb_out (" byte - Write a byte\n"); + gdb_out (" halfword - Write a half-word\n"); + gdb_out (" word - Write a word\n"); + gdb_outf ("The value of must in the interval [0x%08x, 0x%x)\n", + STM32Lx_NVM_EEPROM_PHYS, + STM32Lx_NVM_EEPROM_PHYS + + stm32lx_nvm_eeprom_size (t)); + + done: + stm32lx_nvm_lock (ap, nvm); + return true; +} -- cgit v1.2.3 From bf1cb71eb7a3a679a6acf944283cd0f0ef53c077 Mon Sep 17 00:00:00 2001 From: Marc Singer Date: Sat, 24 Jan 2015 13:50:59 -0800 Subject: Revisions on Gareth's comments. o Implemented byte writes to EEPROM now that the emulator has a byte-wide target write. o Added comment describing the reason that mass erase doesn't work. o Removed all unused code. o Changed to Linux kernel indent style. o Changed to Linux kernel function to parenthesis style. o Stub generation doesn't use Perl, switched to sed. Also, only including the instructions instead of the source and the instructions. o Handling unaligned destination writes. --- flashstub/README | 6 + flashstub/code-to-array.pl | 24 - flashstub/dump-to-array.sh | 11 + flashstub/stm32l05x-nvm-prog-erase.cc | 80 +- flashstub/stm32l05x-nvm-prog-erase.stub | 226 ++--- flashstub/stm32l05x-nvm-prog-write.cc | 105 +- flashstub/stm32l05x-nvm-prog-write.stub | 300 ++---- src/include/stm32lx-nvm.h | 246 ++--- src/stm32l0.c | 1624 +++++++++++++++---------------- 9 files changed, 1209 insertions(+), 1413 deletions(-) delete mode 100755 flashstub/code-to-array.pl create mode 100755 flashstub/dump-to-array.sh (limited to 'src') diff --git a/flashstub/README b/flashstub/README index 155c8d9..90d164c 100644 --- a/flashstub/README +++ b/flashstub/README @@ -11,3 +11,9 @@ of half-words for inclusion in the target driver. The use of a higher level language allows more detailed code and for easy revisions. These stubs communicate with the driver through a structure defined in the src/include/stm32l0-nvm.h header. + +The dump-to-array.sh helper script uses sed to transform the output of +'objdump -d' into a half-word array of the instructions that may be +included in C code to declare the stub. FWIW, objcopy doesn't produce +the same output as objdump. It omits some of the instructions, +probably because the object file isn't linked. diff --git a/flashstub/code-to-array.pl b/flashstub/code-to-array.pl deleted file mode 100755 index 5333e31..0000000 --- a/flashstub/code-to-array.pl +++ /dev/null @@ -1,24 +0,0 @@ -#!/usr/bin/perl -# -# Convert the output of objdump to an array of bytes are can include -# into our program. - -while (<>) { - if (m/^\s*([0-9a-fA-F]+):\s*([0-9a-fA-F]+)(.*)/) { - my $addr = "0x$1"; - my $value = $2; - if (length ($value) == 4) { - print " [$addr/2] = 0x$value, // $_"; - } - else { - my $lsb = substr ($value, 4, 4); - my $msb = substr ($value, 0, 4); - print " [$addr/2] = 0x$lsb, // $_"; - print " [$addr/2 + 1] = 0x$msb,\n"; - } - } - else { - print "// ", $_; - } -} - diff --git a/flashstub/dump-to-array.sh b/flashstub/dump-to-array.sh new file mode 100755 index 0000000..78584d0 --- /dev/null +++ b/flashstub/dump-to-array.sh @@ -0,0 +1,11 @@ +#!/bin/sh +# +# Convert the output of objdump to an array of half-words that can be +# included into C code to represent the stub. +# +# Invoke with something like this: +# +# objdump -z -d FILE.o | dump-to-array.sh > FILE.stub +# + +sed -E "/^[ ][ ]*[0-9a-fA-F]+:/!d; s/([0-9a-fA-F]+):[ \t]+([0-9a-fA-F]+).*/[0x\1\/2] = 0x\2,/ ; s/0x(....)(....),/0x\2, 0x\1,/" diff --git a/flashstub/stm32l05x-nvm-prog-erase.cc b/flashstub/stm32l05x-nvm-prog-erase.cc index 28c11a3..58030e3 100644 --- a/flashstub/stm32l05x-nvm-prog-erase.cc +++ b/flashstub/stm32l05x-nvm-prog-erase.cc @@ -42,52 +42,52 @@ /* Erase a region of flash. In the event that the erase is misaligned with respect to pages, it will erase the pages that contain the requested range of bytes. */ -extern "C" void __attribute((naked)) stm32l05x_nvm_prog_erase () { - // Leave room for INFO at second word of routine - __asm volatile ("b 0f\n\t" - ".align 2\n\t" - ".word 0\n\t" - ".word 0\n\t" - ".word 0\n\t" - ".word 0\n\t" - ".word 0\n\t" - "0:"); - - auto& nvm = Nvm (Info.nvm); - - // Align to the start of the first page so that we make sure to erase - // all of the target pages. - auto remainder = reinterpret_cast (Info.destination) - & (Info.page_size - 1); - Info.size += remainder; - Info.destination -= remainder/sizeof (*Info.destination); - - if (!unlock (nvm)) - goto quit; - - nvm.sr = STM32Lx_NVM_SR_ERR_M; // Clear errors - - // Enable erasing - nvm.pecr = STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE; - if ((nvm.pecr & (STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE)) - != (STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE)) - goto quit; - - while (Info.size > 0) { - *Info.destination = 0; // Initiate erase - - Info.destination += Info.page_size/sizeof (*Info.destination); - Info.size -= Info.page_size; - } +extern "C" void __attribute((naked)) stm32l05x_nvm_prog_erase() { + // Leave room for INFO at second word of routine + __asm volatile ("b 0f\n\t" + ".align 2\n\t" + ".word 0\n\t" + ".word 0\n\t" + ".word 0\n\t" + ".word 0\n\t" + ".word 0\n\t" + "0:"); + + auto& nvm = Nvm (Info.nvm); + + // Align to the start of the first page so that we make sure to erase + // all of the target pages. + auto remainder = reinterpret_cast (Info.destination) + & (Info.page_size - 1); + Info.size += remainder; + Info.destination -= remainder/sizeof (*Info.destination); + + if (!unlock(nvm)) + goto quit; + + nvm.sr = STM32Lx_NVM_SR_ERR_M; // Clear errors + + // Enable erasing + nvm.pecr = STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE; + if ((nvm.pecr & (STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE)) + != (STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE)) + goto quit; + + while (Info.size > 0) { + *Info.destination = 0; // Initiate erase + + Info.destination += Info.page_size/sizeof (*Info.destination); + Info.size -= Info.page_size; + } quit: - lock (nvm); - __asm volatile ("bkpt"); + lock(nvm); + __asm volatile ("bkpt"); } /* Local Variables: - compile-command: "/opt/arm/arm-none-eabi-g++ -mcpu=cortex-m0plus -g -c -std=c++11 -mthumb -o stm32l05x-nvm-prog-erase.o -Os -Wa,-ahndl=stm32l05x-nvm-prog-erase.lst stm32l05x-nvm-prog-erase.cc ; /opt/arm/arm-none-eabi-objdump -S stm32l05x-nvm-prog-erase.o | ./code-to-array.pl > stm32l05x-nvm-prog-erase.stub" + compile-command: "/opt/arm/arm-none-eabi-g++ -mcpu=cortex-m0plus -g -c -std=c++11 -mthumb -o stm32l05x-nvm-prog-erase.o -Os -Wa,-ahndl=stm32l05x-nvm-prog-erase.lst stm32l05x-nvm-prog-erase.cc ; /opt/arm/arm-none-eabi-objdump -d -z stm32l05x-nvm-prog-erase.o | ./dump-to-array.sh > stm32l05x-nvm-prog-erase.stub" End: */ diff --git a/flashstub/stm32l05x-nvm-prog-erase.stub b/flashstub/stm32l05x-nvm-prog-erase.stub index ebb6fbb..e0fea34 100644 --- a/flashstub/stm32l05x-nvm-prog-erase.stub +++ b/flashstub/stm32l05x-nvm-prog-erase.stub @@ -1,159 +1,67 @@ -// -// stm32l05x-nvm-prog-erase.o: file format elf32-littlearm -// -// -// Disassembly of section .text: -// -// 00000000 : -// ".word 0\n\t" -// ".word 0\n\t" -// ".word 0\n\t" -// ".word 0\n\t" -// ".word 0\n\t" -// "0:"); - [0x0/2] = 0xe00a, // 0: e00a b.n 18 - [0x2/2] = 0x46c0, // 2: 46c0 nop ; (mov r8, r8) -// ... -// -// auto& nvm = Nvm (Info.nvm); - [0x18/2] = 0x491a, // 18: 491a ldr r1, [pc, #104] ; (84 ) -// -// // Align to the start of the first page so that we make sure to erase -// // all of the target pages. -// auto remainder = reinterpret_cast (Info.destination) -// & (Info.page_size - 1); - [0x1a/2] = 0x8a08, // 1a: 8a08 ldrh r0, [r1, #16] - [0x1c/2] = 0x680c, // 1c: 680c ldr r4, [r1, #0] -// Info.size += remainder; - [0x1e/2] = 0x684d, // 1e: 684d ldr r5, [r1, #4] -// auto& nvm = Nvm (Info.nvm); -// -// // Align to the start of the first page so that we make sure to erase -// // all of the target pages. -// auto remainder = reinterpret_cast (Info.destination) -// & (Info.page_size - 1); - [0x20/2] = 0x1e42, // 20: 1e42 subs r2, r0, #1 - [0x22/2] = 0x4022, // 22: 4022 ands r2, r4 -// Info.size += remainder; - [0x24/2] = 0x1955, // 24: 1955 adds r5, r2, r5 -// Info.destination -= remainder/sizeof (*Info.destination); - [0x26/2] = 0x0892, // 26: 0892 lsrs r2, r2, #2 - [0x28/2] = 0x0092, // 28: 0092 lsls r2, r2, #2 - [0x2a/2] = 0x1aa2, // 2a: 1aa2 subs r2, r4, r2 - [0x2c/2] = 0x600a, // 2c: 600a str r2, [r1, #0] -// #define Nvm(nvm) (*reinterpret_cast(nvm)) -// #define Info (*reinterpret_cast(STM32Lx_STUB_INFO_PHYS)) -// -// namespace { -// inline __attribute((always_inline)) bool unlock (STM32::NVM& nvm) { -// nvm.pecr = STM32Lx_NVM_PECR_PELOCK; // Lock to guarantee unlock - [0x2e/2] = 0x2201, // 2e: 2201 movs r2, #1 -// ".word 0\n\t" -// ".word 0\n\t" -// ".word 0\n\t" -// "0:"); -// -// auto& nvm = Nvm (Info.nvm); - [0x30/2] = 0x68cb, // 30: 68cb ldr r3, [r1, #12] -// -// // Align to the start of the first page so that we make sure to erase -// // all of the target pages. -// auto remainder = reinterpret_cast (Info.destination) -// & (Info.page_size - 1); -// Info.size += remainder; - [0x32/2] = 0x604d, // 32: 604d str r5, [r1, #4] - [0x34/2] = 0x605a, // 34: 605a str r2, [r3, #4] -// nvm.pkeyr = STM32::NVM::PKEY1; - [0x36/2] = 0x4a14, // 36: 4a14 ldr r2, [pc, #80] ; (88 ) - [0x38/2] = 0x60da, // 38: 60da str r2, [r3, #12] -// nvm.pkeyr = STM32::NVM::PKEY2; - [0x3a/2] = 0x4a14, // 3a: 4a14 ldr r2, [pc, #80] ; (8c ) - [0x3c/2] = 0x60da, // 3c: 60da str r2, [r3, #12] -// nvm.prgkeyr = STM32::NVM::PRGKEY1; - [0x3e/2] = 0x4a14, // 3e: 4a14 ldr r2, [pc, #80] ; (90 ) - [0x40/2] = 0x611a, // 40: 611a str r2, [r3, #16] -// nvm.prgkeyr = STM32::NVM::PRGKEY2; - [0x42/2] = 0x4a14, // 42: 4a14 ldr r2, [pc, #80] ; (94 ) - [0x44/2] = 0x611a, // 44: 611a str r2, [r3, #16] -// return !(nvm.pecr & STM32Lx_NVM_PECR_PRGLOCK); - [0x46/2] = 0x685a, // 46: 685a ldr r2, [r3, #4] -// Info.destination -= remainder/sizeof (*Info.destination); -// -// if (!unlock (nvm)) - [0x48/2] = 0x0792, // 48: 0792 lsls r2, r2, #30 - [0x4a/2] = 0xd502, // 4a: d502 bpl.n 52 -// } -// inline __attribute((always_inline)) void lock (STM32::NVM& nvm) { -// nvm.pecr = STM32Lx_NVM_PECR_PELOCK; } - [0x4c/2] = 0x2201, // 4c: 2201 movs r2, #1 - [0x4e/2] = 0x605a, // 4e: 605a str r2, [r3, #4] -// Info.size -= Info.page_size; -// } -// -// quit: -// lock (nvm); -// __asm volatile ("bkpt"); - [0x50/2] = 0xbe00, // 50: be00 bkpt 0x0000 -// Info.destination -= remainder/sizeof (*Info.destination); -// -// if (!unlock (nvm)) -// goto quit; -// -// nvm.sr = STM32Lx_NVM_SR_ERR_M; // Clear errors - [0x52/2] = 0x4a11, // 52: 4a11 ldr r2, [pc, #68] ; (98 ) - [0x54/2] = 0x619a, // 54: 619a str r2, [r3, #24] -// -// // Enable erasing -// nvm.pecr = STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE; - [0x56/2] = 0x2282, // 56: 2282 movs r2, #130 ; 0x82 - [0x58/2] = 0x0092, // 58: 0092 lsls r2, r2, #2 - [0x5a/2] = 0x605a, // 5a: 605a str r2, [r3, #4] -// if ((nvm.pecr & (STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE)) - [0x5c/2] = 0x685c, // 5c: 685c ldr r4, [r3, #4] - [0x5e/2] = 0x4014, // 5e: 4014 ands r4, r2 - [0x60/2] = 0x4294, // 60: 4294 cmp r4, r2 - [0x62/2] = 0xd1f3, // 62: d1f3 bne.n 4c -// goto quit; -// -// while (Info.size > 0) { -// *Info.destination = 0; // Initiate erase -// -// Info.destination += Info.page_size/sizeof (*Info.destination); - [0x64/2] = 0x0884, // 64: 0884 lsrs r4, r0, #2 - [0x66/2] = 0x00a4, // 66: 00a4 lsls r4, r4, #2 -// nvm.pecr = STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE; -// if ((nvm.pecr & (STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE)) -// != (STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE)) -// goto quit; -// -// while (Info.size > 0) { - [0x68/2] = 0x684d, // 68: 684d ldr r5, [r1, #4] - [0x6a/2] = 0x4a06, // 6a: 4a06 ldr r2, [pc, #24] ; (84 ) - [0x6c/2] = 0x2d00, // 6c: 2d00 cmp r5, #0 - [0x6e/2] = 0xdded, // 6e: dded ble.n 4c -// *Info.destination = 0; // Initiate erase - [0x70/2] = 0x2600, // 70: 2600 movs r6, #0 - [0x72/2] = 0x6815, // 72: 6815 ldr r5, [r2, #0] - [0x74/2] = 0x602e, // 74: 602e str r6, [r5, #0] -// -// Info.destination += Info.page_size/sizeof (*Info.destination); - [0x76/2] = 0x6815, // 76: 6815 ldr r5, [r2, #0] - [0x78/2] = 0x192d, // 78: 192d adds r5, r5, r4 - [0x7a/2] = 0x6015, // 7a: 6015 str r5, [r2, #0] -// Info.size -= Info.page_size; - [0x7c/2] = 0x6855, // 7c: 6855 ldr r5, [r2, #4] - [0x7e/2] = 0x1a2d, // 7e: 1a2d subs r5, r5, r0 - [0x80/2] = 0x6055, // 80: 6055 str r5, [r2, #4] - [0x82/2] = 0xe7f1, // 82: e7f1 b.n 68 - [0x84/2] = 0x0004, // 84: 20000004 .word 0x20000004 - [0x84/2 + 1] = 0x2000, - [0x88/2] = 0xcdef, // 88: 89abcdef .word 0x89abcdef - [0x88/2 + 1] = 0x89ab, - [0x8c/2] = 0x0405, // 8c: 02030405 .word 0x02030405 - [0x8c/2 + 1] = 0x0203, - [0x90/2] = 0xaebf, // 90: 8c9daebf .word 0x8c9daebf - [0x90/2 + 1] = 0x8c9d, - [0x94/2] = 0x1516, // 94: 13141516 .word 0x13141516 - [0x94/2 + 1] = 0x1314, - [0x98/2] = 0x0700, // 98: 00010700 .word 0x00010700 - [0x98/2 + 1] = 0x0001, + [0x0/2] = 0xe00a, + [0x2/2] = 0x46c0, + [0x4/2] = 0x0000, 0x0000, + [0x8/2] = 0x0000, 0x0000, + [0xc/2] = 0x0000, 0x0000, + [0x10/2] = 0x0000, 0x0000, + [0x14/2] = 0x0000, 0x0000, + [0x18/2] = 0x491a, + [0x1a/2] = 0x8a08, + [0x1c/2] = 0x680c, + [0x1e/2] = 0x684d, + [0x20/2] = 0x1e42, + [0x22/2] = 0x4022, + [0x24/2] = 0x1955, + [0x26/2] = 0x0892, + [0x28/2] = 0x0092, + [0x2a/2] = 0x1aa2, + [0x2c/2] = 0x600a, + [0x2e/2] = 0x2201, + [0x30/2] = 0x68cb, + [0x32/2] = 0x604d, + [0x34/2] = 0x605a, + [0x36/2] = 0x4a14, + [0x38/2] = 0x60da, + [0x3a/2] = 0x4a14, + [0x3c/2] = 0x60da, + [0x3e/2] = 0x4a14, + [0x40/2] = 0x611a, + [0x42/2] = 0x4a14, + [0x44/2] = 0x611a, + [0x46/2] = 0x685a, + [0x48/2] = 0x0792, + [0x4a/2] = 0xd502, + [0x4c/2] = 0x2201, + [0x4e/2] = 0x605a, + [0x50/2] = 0xbe00, + [0x52/2] = 0x4a11, + [0x54/2] = 0x619a, + [0x56/2] = 0x2282, + [0x58/2] = 0x0092, + [0x5a/2] = 0x605a, + [0x5c/2] = 0x685c, + [0x5e/2] = 0x4014, + [0x60/2] = 0x4294, + [0x62/2] = 0xd1f3, + [0x64/2] = 0x0884, + [0x66/2] = 0x00a4, + [0x68/2] = 0x684d, + [0x6a/2] = 0x4a06, + [0x6c/2] = 0x2d00, + [0x6e/2] = 0xdded, + [0x70/2] = 0x2600, + [0x72/2] = 0x6815, + [0x74/2] = 0x602e, + [0x76/2] = 0x6815, + [0x78/2] = 0x192d, + [0x7a/2] = 0x6015, + [0x7c/2] = 0x6855, + [0x7e/2] = 0x1a2d, + [0x80/2] = 0x6055, + [0x82/2] = 0xe7f1, + [0x84/2] = 0x0004, 0x2000, + [0x88/2] = 0xcdef, 0x89ab, + [0x8c/2] = 0x0405, 0x0203, + [0x90/2] = 0xaebf, 0x8c9d, + [0x94/2] = 0x1516, 0x1314, + [0x98/2] = 0x0700, 0x0001, diff --git a/flashstub/stm32l05x-nvm-prog-write.cc b/flashstub/stm32l05x-nvm-prog-write.cc index 78799d9..e90401e 100644 --- a/flashstub/stm32l05x-nvm-prog-write.cc +++ b/flashstub/stm32l05x-nvm-prog-write.cc @@ -43,70 +43,71 @@ /* Write a block of bytes to flash. The called is responsible for making sure that the address are aligned and that the count is an even multiple of words. */ -extern "C" void __attribute((naked)) stm32l05x_nvm_prog_write () { +extern "C" void __attribute((naked)) stm32l05x_nvm_prog_write() { // Leave room for INFO at second word of routine - __asm volatile ("b 0f\n\t" - ".align 2\n\t" - ".word 0\n\t" - ".word 0\n\t" - ".word 0\n\t" - ".word 0\n\t" - ".word 0\n\t" - "0:"); + __asm volatile ("b 0f\n\t" + ".align 2\n\t" + ".word 0\n\t" + ".word 0\n\t" + ".word 0\n\t" + ".word 0\n\t" + ".word 0\n\t" + "0:"); - auto& nvm = Nvm (Info.nvm); + auto& nvm = Nvm (Info.nvm); - if (!unlock (nvm)) - goto quit; + if (!unlock(nvm)) + goto quit; - nvm.sr = STM32Lx_NVM_SR_ERR_M; // Clear errors + nvm.sr = STM32Lx_NVM_SR_ERR_M; // Clear errors - while (Info.size > 0) { + while (Info.size > 0) { - // Either we're not half-page aligned or we have less than a half - // page to write - if (Info.size < Info.page_size/2 - || (reinterpret_cast (Info.destination) - & (Info.page_size/2 - 1))) { - nvm.pecr = (Info.options & OPT_STM32L1) ? 0 - : STM32Lx_NVM_PECR_PROG; // Word programming - size_t c = Info.page_size/2 - - (reinterpret_cast (Info.destination) - & (Info.page_size/2 - 1)); - if (c > Info.size) - c = Info.size; - Info.size -= c; - c /= 4; - while (c--) { - uint32_t v = *Info.source++; - *Info.destination++ = v; - if (nvm.sr & STM32Lx_NVM_SR_ERR_M) - goto quit; - } - } - // Or we are writing a half-page(s) - else { - nvm.pecr = STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_FPRG; // Half-page prg - size_t c = Info.size & ~(Info.page_size/2 - 1); - Info.size -= c; - c /= 4; - while (c--) { - uint32_t v = *Info.source++; - *Info.destination++ = v; - } - if (nvm.sr & STM32Lx_NVM_SR_ERR_M) - goto quit; - } - } + // Either we're not half-page aligned or we have less + // than a half page to write + if (Info.size < Info.page_size/2 + || (reinterpret_cast (Info.destination) + & (Info.page_size/2 - 1))) { + nvm.pecr = (Info.options & OPT_STM32L1) ? 0 + : STM32Lx_NVM_PECR_PROG; // Word programming + size_t c = Info.page_size/2 + - (reinterpret_cast (Info.destination) + & (Info.page_size/2 - 1)); + if (c > Info.size) + c = Info.size; + Info.size -= c; + c /= 4; + while (c--) { + uint32_t v = *Info.source++; + *Info.destination++ = v; + if (nvm.sr & STM32Lx_NVM_SR_ERR_M) + goto quit; + } + } + // Or we are writing a half-page(s) + else { + nvm.pecr = STM32Lx_NVM_PECR_PROG + | STM32Lx_NVM_PECR_FPRG; // Half-page prg + size_t c = Info.size & ~(Info.page_size/2 - 1); + Info.size -= c; + c /= 4; + while (c--) { + uint32_t v = *Info.source++; + *Info.destination++ = v; + } + if (nvm.sr & STM32Lx_NVM_SR_ERR_M) + goto quit; + } + } quit: - lock (nvm); - __asm volatile ("bkpt"); + lock(nvm); + __asm volatile ("bkpt"); } /* Local Variables: - compile-command: "/opt/arm/arm-none-eabi-g++ -mcpu=cortex-m0plus -g -c -std=c++11 -mthumb -o stm32l05x-nvm-prog-write.o -Os -Wa,-ahndl=stm32l05x-nvm-prog-write.lst stm32l05x-nvm-prog-write.cc ; /opt/arm/arm-none-eabi-objdump -S stm32l05x-nvm-prog-write.o | ./code-to-array.pl > stm32l05x-nvm-prog-write.stub" + compile-command: "/opt/arm/arm-none-eabi-g++ -mcpu=cortex-m0plus -g -c -std=c++11 -mthumb -o stm32l05x-nvm-prog-write.o -Os -Wa,-ahndl=stm32l05x-nvm-prog-write.lst stm32l05x-nvm-prog-write.cc ; /opt/arm/arm-none-eabi-objdump -d -z stm32l05x-nvm-prog-write.o | ./dump-to-array.sh > stm32l05x-nvm-prog-write.stub" End: */ diff --git a/flashstub/stm32l05x-nvm-prog-write.stub b/flashstub/stm32l05x-nvm-prog-write.stub index 6fd661f..7ddbc81 100644 --- a/flashstub/stm32l05x-nvm-prog-write.stub +++ b/flashstub/stm32l05x-nvm-prog-write.stub @@ -1,201 +1,99 @@ -// -// stm32l05x-nvm-prog-write.o: file format elf32-littlearm -// -// -// Disassembly of section .text: -// -// 00000000 : -// ".word 0\n\t" -// ".word 0\n\t" -// ".word 0\n\t" -// ".word 0\n\t" -// ".word 0\n\t" -// "0:"); - [0x0/2] = 0xe00a, // 0: e00a b.n 18 - [0x2/2] = 0x46c0, // 2: 46c0 nop ; (mov r8, r8) -// ... -// #define Nvm(nvm) (*reinterpret_cast(nvm)) -// #define Info (*reinterpret_cast(STM32Lx_STUB_INFO_PHYS)) -// -// namespace { -// inline __attribute((always_inline)) bool unlock (STM32::NVM& nvm) { -// nvm.pecr = STM32Lx_NVM_PECR_PELOCK; // Lock to guarantee unlock - [0x18/2] = 0x2201, // 18: 2201 movs r2, #1 -// -// auto& nvm = Nvm (Info.nvm); - [0x1a/2] = 0x4b2a, // 1a: 4b2a ldr r3, [pc, #168] ; (c4 ) - [0x1c/2] = 0x68d9, // 1c: 68d9 ldr r1, [r3, #12] - [0x1e/2] = 0x604a, // 1e: 604a str r2, [r1, #4] -// nvm.pkeyr = STM32::NVM::PKEY1; - [0x20/2] = 0x4a29, // 20: 4a29 ldr r2, [pc, #164] ; (c8 ) - [0x22/2] = 0x60ca, // 22: 60ca str r2, [r1, #12] -// nvm.pkeyr = STM32::NVM::PKEY2; - [0x24/2] = 0x4a29, // 24: 4a29 ldr r2, [pc, #164] ; (cc ) - [0x26/2] = 0x60ca, // 26: 60ca str r2, [r1, #12] -// nvm.prgkeyr = STM32::NVM::PRGKEY1; - [0x28/2] = 0x4a29, // 28: 4a29 ldr r2, [pc, #164] ; (d0 ) - [0x2a/2] = 0x610a, // 2a: 610a str r2, [r1, #16] -// nvm.prgkeyr = STM32::NVM::PRGKEY2; - [0x2c/2] = 0x4a29, // 2c: 4a29 ldr r2, [pc, #164] ; (d4 ) - [0x2e/2] = 0x610a, // 2e: 610a str r2, [r1, #16] -// return !(nvm.pecr & STM32Lx_NVM_PECR_PRGLOCK); - [0x30/2] = 0x684a, // 30: 684a ldr r2, [r1, #4] -// -// if (!unlock (nvm)) - [0x32/2] = 0x0792, // 32: 0792 lsls r2, r2, #30 - [0x34/2] = 0xd502, // 34: d502 bpl.n 3c -// } -// inline __attribute((always_inline)) void lock (STM32::NVM& nvm) { -// nvm.pecr = STM32Lx_NVM_PECR_PELOCK; } - [0x36/2] = 0x2301, // 36: 2301 movs r3, #1 - [0x38/2] = 0x604b, // 38: 604b str r3, [r1, #4] -// } -// } -// -// quit: -// lock (nvm); -// __asm volatile ("bkpt"); - [0x3a/2] = 0xbe00, // 3a: be00 bkpt 0x0000 -// auto& nvm = Nvm (Info.nvm); -// -// if (!unlock (nvm)) -// goto quit; -// -// nvm.sr = STM32Lx_NVM_SR_ERR_M; // Clear errors - [0x3c/2] = 0x4826, // 3c: 4826 ldr r0, [pc, #152] ; (d8 ) - [0x3e/2] = 0x6188, // 3e: 6188 str r0, [r1, #24] -// -// while (Info.size > 0) { - [0x40/2] = 0x685d, // 40: 685d ldr r5, [r3, #4] - [0x42/2] = 0x4e20, // 42: 4e20 ldr r6, [pc, #128] ; (c4 ) - [0x44/2] = 0x2d00, // 44: 2d00 cmp r5, #0 - [0x46/2] = 0xddf6, // 46: ddf6 ble.n 36 -// -// // Either we're not half-page aligned or we have less than a half -// // page to write -// if (Info.size < Info.page_size/2 - [0x48/2] = 0x8a32, // 48: 8a32 ldrh r2, [r6, #16] - [0x4a/2] = 0x0852, // 4a: 0852 lsrs r2, r2, #1 - [0x4c/2] = 0x1e54, // 4c: 1e54 subs r4, r2, #1 - [0x4e/2] = 0x4295, // 4e: 4295 cmp r5, r2 - [0x50/2] = 0xdb02, // 50: db02 blt.n 58 -// || (reinterpret_cast (Info.destination) - [0x52/2] = 0x6837, // 52: 6837 ldr r7, [r6, #0] - [0x54/2] = 0x4227, // 54: 4227 tst r7, r4 - [0x56/2] = 0xd01d, // 56: d01d beq.n 94 -// & (Info.page_size/2 - 1))) { -// nvm.pecr = (Info.options & OPT_STM32L1) ? 0 -// : STM32Lx_NVM_PECR_PROG; // Word programming - [0x58/2] = 0x2602, // 58: 2602 movs r6, #2 -// // Either we're not half-page aligned or we have less than a half -// // page to write -// if (Info.size < Info.page_size/2 -// || (reinterpret_cast (Info.destination) -// & (Info.page_size/2 - 1))) { -// nvm.pecr = (Info.options & OPT_STM32L1) ? 0 - [0x5a/2] = 0x8a5f, // 5a: 8a5f ldrh r7, [r3, #18] -// : STM32Lx_NVM_PECR_PROG; // Word programming - [0x5c/2] = 0x4037, // 5c: 4037 ands r7, r6 - [0x5e/2] = 0x427e, // 5e: 427e negs r6, r7 - [0x60/2] = 0x417e, // 60: 417e adcs r6, r7 - [0x62/2] = 0x00f6, // 62: 00f6 lsls r6, r6, #3 - [0x64/2] = 0x604e, // 64: 604e str r6, [r1, #4] -// size_t c = Info.page_size/2 -// - (reinterpret_cast (Info.destination) -// & (Info.page_size/2 - 1)); - [0x66/2] = 0x681e, // 66: 681e ldr r6, [r3, #0] - [0x68/2] = 0x4034, // 68: 4034 ands r4, r6 - [0x6a/2] = 0x1b12, // 6a: 1b12 subs r2, r2, r4 - [0x6c/2] = 0x42aa, // 6c: 42aa cmp r2, r5 - [0x6e/2] = 0xd900, // 6e: d900 bls.n 72 - [0x70/2] = 0x1c2a, // 70: 1c2a adds r2, r5, #0 -// if (c > Info.size) -// c = Info.size; -// Info.size -= c; - [0x72/2] = 0x1aad, // 72: 1aad subs r5, r5, r2 - [0x74/2] = 0x605d, // 74: 605d str r5, [r3, #4] -// c /= 4; - [0x76/2] = 0x0892, // 76: 0892 lsrs r2, r2, #2 -// while (c--) { - [0x78/2] = 0x3a01, // 78: 3a01 subs r2, #1 - [0x7a/2] = 0xd3e1, // 7a: d3e1 bcc.n 40 -// uint32_t v = *Info.source++; - [0x7c/2] = 0x689c, // 7c: 689c ldr r4, [r3, #8] - [0x7e/2] = 0x1d25, // 7e: 1d25 adds r5, r4, #4 - [0x80/2] = 0x609d, // 80: 609d str r5, [r3, #8] - [0x82/2] = 0x6825, // 82: 6825 ldr r5, [r4, #0] -// *Info.destination++ = v; - [0x84/2] = 0x681c, // 84: 681c ldr r4, [r3, #0] - [0x86/2] = 0x1d26, // 86: 1d26 adds r6, r4, #4 - [0x88/2] = 0x601e, // 88: 601e str r6, [r3, #0] - [0x8a/2] = 0x6025, // 8a: 6025 str r5, [r4, #0] -// if (nvm.sr & STM32Lx_NVM_SR_ERR_M) - [0x8c/2] = 0x698c, // 8c: 698c ldr r4, [r1, #24] - [0x8e/2] = 0x4204, // 8e: 4204 tst r4, r0 - [0x90/2] = 0xd0f2, // 90: d0f2 beq.n 78 - [0x92/2] = 0xe7d0, // 92: e7d0 b.n 36 -// goto quit; -// } -// } -// // Or we are writing a half-page(s) -// else { -// nvm.pecr = STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_FPRG; // Half-page prg - [0x94/2] = 0x2481, // 94: 2481 movs r4, #129 ; 0x81 -// size_t c = Info.size & ~(Info.page_size/2 - 1); - [0x96/2] = 0x4252, // 96: 4252 negs r2, r2 - [0x98/2] = 0x402a, // 98: 402a ands r2, r5 -// Info.size -= c; - [0x9a/2] = 0x1aad, // 9a: 1aad subs r5, r5, r2 -// goto quit; -// } -// } -// // Or we are writing a half-page(s) -// else { -// nvm.pecr = STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_FPRG; // Half-page prg - [0x9c/2] = 0x00e4, // 9c: 00e4 lsls r4, r4, #3 - [0x9e/2] = 0x604c, // 9e: 604c str r4, [r1, #4] -// size_t c = Info.size & ~(Info.page_size/2 - 1); -// Info.size -= c; -// c /= 4; - [0xa0/2] = 0x0892, // a0: 0892 lsrs r2, r2, #2 -// } -// // Or we are writing a half-page(s) -// else { -// nvm.pecr = STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_FPRG; // Half-page prg -// size_t c = Info.size & ~(Info.page_size/2 - 1); -// Info.size -= c; - [0xa2/2] = 0x6075, // a2: 6075 str r5, [r6, #4] -// c /= 4; -// while (c--) { - [0xa4/2] = 0x3a01, // a4: 3a01 subs r2, #1 - [0xa6/2] = 0xd308, // a6: d308 bcc.n ba -// uint32_t v = *Info.source++; - [0xa8/2] = 0x689c, // a8: 689c ldr r4, [r3, #8] - [0xaa/2] = 0x1d25, // aa: 1d25 adds r5, r4, #4 - [0xac/2] = 0x609d, // ac: 609d str r5, [r3, #8] - [0xae/2] = 0x6825, // ae: 6825 ldr r5, [r4, #0] -// *Info.destination++ = v; - [0xb0/2] = 0x681c, // b0: 681c ldr r4, [r3, #0] - [0xb2/2] = 0x1d26, // b2: 1d26 adds r6, r4, #4 - [0xb4/2] = 0x601e, // b4: 601e str r6, [r3, #0] - [0xb6/2] = 0x6025, // b6: 6025 str r5, [r4, #0] - [0xb8/2] = 0xe7f4, // b8: e7f4 b.n a4 -// } -// if (nvm.sr & STM32Lx_NVM_SR_ERR_M) - [0xba/2] = 0x698a, // ba: 698a ldr r2, [r1, #24] - [0xbc/2] = 0x4202, // bc: 4202 tst r2, r0 - [0xbe/2] = 0xd0bf, // be: d0bf beq.n 40 - [0xc0/2] = 0xe7b9, // c0: e7b9 b.n 36 - [0xc2/2] = 0x46c0, // c2: 46c0 nop ; (mov r8, r8) - [0xc4/2] = 0x0004, // c4: 20000004 .word 0x20000004 - [0xc4/2 + 1] = 0x2000, - [0xc8/2] = 0xcdef, // c8: 89abcdef .word 0x89abcdef - [0xc8/2 + 1] = 0x89ab, - [0xcc/2] = 0x0405, // cc: 02030405 .word 0x02030405 - [0xcc/2 + 1] = 0x0203, - [0xd0/2] = 0xaebf, // d0: 8c9daebf .word 0x8c9daebf - [0xd0/2 + 1] = 0x8c9d, - [0xd4/2] = 0x1516, // d4: 13141516 .word 0x13141516 - [0xd4/2 + 1] = 0x1314, - [0xd8/2] = 0x0700, // d8: 00010700 .word 0x00010700 - [0xd8/2 + 1] = 0x0001, + [0x0/2] = 0xe00a, + [0x2/2] = 0x46c0, + [0x4/2] = 0x0000, 0x0000, + [0x8/2] = 0x0000, 0x0000, + [0xc/2] = 0x0000, 0x0000, + [0x10/2] = 0x0000, 0x0000, + [0x14/2] = 0x0000, 0x0000, + [0x18/2] = 0x2201, + [0x1a/2] = 0x4b2a, + [0x1c/2] = 0x68d9, + [0x1e/2] = 0x604a, + [0x20/2] = 0x4a29, + [0x22/2] = 0x60ca, + [0x24/2] = 0x4a29, + [0x26/2] = 0x60ca, + [0x28/2] = 0x4a29, + [0x2a/2] = 0x610a, + [0x2c/2] = 0x4a29, + [0x2e/2] = 0x610a, + [0x30/2] = 0x684a, + [0x32/2] = 0x0792, + [0x34/2] = 0xd502, + [0x36/2] = 0x2301, + [0x38/2] = 0x604b, + [0x3a/2] = 0xbe00, + [0x3c/2] = 0x4826, + [0x3e/2] = 0x6188, + [0x40/2] = 0x685d, + [0x42/2] = 0x4e20, + [0x44/2] = 0x2d00, + [0x46/2] = 0xddf6, + [0x48/2] = 0x8a32, + [0x4a/2] = 0x0852, + [0x4c/2] = 0x1e54, + [0x4e/2] = 0x4295, + [0x50/2] = 0xdb02, + [0x52/2] = 0x6837, + [0x54/2] = 0x4227, + [0x56/2] = 0xd01d, + [0x58/2] = 0x2602, + [0x5a/2] = 0x8a5f, + [0x5c/2] = 0x4037, + [0x5e/2] = 0x427e, + [0x60/2] = 0x417e, + [0x62/2] = 0x00f6, + [0x64/2] = 0x604e, + [0x66/2] = 0x681e, + [0x68/2] = 0x4034, + [0x6a/2] = 0x1b12, + [0x6c/2] = 0x42aa, + [0x6e/2] = 0xd900, + [0x70/2] = 0x1c2a, + [0x72/2] = 0x1aad, + [0x74/2] = 0x605d, + [0x76/2] = 0x0892, + [0x78/2] = 0x3a01, + [0x7a/2] = 0xd3e1, + [0x7c/2] = 0x689c, + [0x7e/2] = 0x1d25, + [0x80/2] = 0x609d, + [0x82/2] = 0x6825, + [0x84/2] = 0x681c, + [0x86/2] = 0x1d26, + [0x88/2] = 0x601e, + [0x8a/2] = 0x6025, + [0x8c/2] = 0x698c, + [0x8e/2] = 0x4204, + [0x90/2] = 0xd0f2, + [0x92/2] = 0xe7d0, + [0x94/2] = 0x2481, + [0x96/2] = 0x4252, + [0x98/2] = 0x402a, + [0x9a/2] = 0x1aad, + [0x9c/2] = 0x00e4, + [0x9e/2] = 0x604c, + [0xa0/2] = 0x0892, + [0xa2/2] = 0x6075, + [0xa4/2] = 0x3a01, + [0xa6/2] = 0xd308, + [0xa8/2] = 0x689c, + [0xaa/2] = 0x1d25, + [0xac/2] = 0x609d, + [0xae/2] = 0x6825, + [0xb0/2] = 0x681c, + [0xb2/2] = 0x1d26, + [0xb4/2] = 0x601e, + [0xb6/2] = 0x6025, + [0xb8/2] = 0xe7f4, + [0xba/2] = 0x698a, + [0xbc/2] = 0x4202, + [0xbe/2] = 0xd0bf, + [0xc0/2] = 0xe7b9, + [0xc2/2] = 0x46c0, + [0xc4/2] = 0x0004, 0x2000, + [0xc8/2] = 0xcdef, 0x89ab, + [0xcc/2] = 0x0405, 0x0203, + [0xd0/2] = 0xaebf, 0x8c9d, + [0xd4/2] = 0x1516, 0x1314, + [0xd8/2] = 0x0700, 0x0001, diff --git a/src/include/stm32lx-nvm.h b/src/include/stm32lx-nvm.h index 126f2ab..190a8ab 100644 --- a/src/include/stm32lx-nvm.h +++ b/src/include/stm32lx-nvm.h @@ -31,108 +31,108 @@ /* ----- Types */ enum { - STM32Lx_STUB_PHYS = 0x20000000ul, - STM32Lx_STUB_INFO_PHYS = 0x20000004ul, - STM32Lx_STUB_DATA_PHYS = (0x20000000ul + 1024), - STM32Lx_STUB_DATA_MAX = 2048, - - STM32Lx_NVM_OPT_PHYS = 0x1ff80000ul, - STM32Lx_NVM_EEPROM_PHYS = 0x08080000ul, - - STM32L0_NVM_PHYS = 0x40022000ul, - STM32L0_NVM_PROG_PAGE_SIZE = 128, - STM32L0_NVM_DATA_PAGE_SIZE = 4, - STM32L0_NVM_OPT_SIZE = 12, - STM32L0_NVM_EEPROM_SIZE = 2*1024, - - STM32L1_NVM_PHYS = 0x40023c00ul, - STM32L1_NVM_PROG_PAGE_SIZE = 256, - STM32L1_NVM_DATA_PAGE_SIZE = 4, - STM32L1_NVM_OPT_SIZE = 32, - STM32L1_NVM_EEPROM_SIZE = 16*1024, - - STM32Lx_NVM_PEKEY1 = 0x89abcdeful, - STM32Lx_NVM_PEKEY2 = 0x02030405ul, - STM32Lx_NVM_PRGKEY1 = 0x8c9daebful, - STM32Lx_NVM_PRGKEY2 = 0x13141516ul, - STM32Lx_NVM_OPTKEY1 = 0xfbead9c8ul, - STM32Lx_NVM_OPTKEY2 = 0x24252627ul, - - STM32Lx_NVM_PECR_OBL_LAUNCH = (1<<18), - STM32Lx_NVM_PECR_ERRIE = (1<<17), - STM32Lx_NVM_PECR_EOPIE = (1<<16), - STM32Lx_NVM_PECR_FPRG = (1<<10), - STM32Lx_NVM_PECR_ERASE = (1<< 9), - STM32Lx_NVM_PECR_FIX = (1<< 8), /* FTDW */ - STM32Lx_NVM_PECR_DATA = (1<< 4), - STM32Lx_NVM_PECR_PROG = (1<< 3), - STM32Lx_NVM_PECR_OPTLOCK = (1<< 2), - STM32Lx_NVM_PECR_PRGLOCK = (1<< 1), - STM32Lx_NVM_PECR_PELOCK = (1<< 0), - - STM32Lx_NVM_SR_FWWERR = (1<<17), - STM32Lx_NVM_SR_NOTZEROERR = (1<<16), - STM32Lx_NVM_SR_RDERR = (1<<13), - STM32Lx_NVM_SR_OPTVER = (1<<11), - STM32Lx_NVM_SR_SIZERR = (1<<10), - STM32Lx_NVM_SR_PGAERR = (1<<9), - STM32Lx_NVM_SR_WRPERR = (1<<8), - STM32Lx_NVM_SR_READY = (1<<3), - STM32Lx_NVM_SR_HWOFF = (1<<2), - STM32Lx_NVM_SR_EOP = (1<<1), - STM32Lx_NVM_SR_BSY = (1<<0), - STM32Lx_NVM_SR_ERR_M = ( STM32Lx_NVM_SR_WRPERR - | STM32Lx_NVM_SR_PGAERR - | STM32Lx_NVM_SR_SIZERR - | STM32Lx_NVM_SR_NOTZEROERR), - - STM32L0_NVM_OPTR_BOOT1 = (1<<31), - STM32L0_NVM_OPTR_WDG_SW = (1<<20), - STM32L0_NVM_OPTR_WPRMOD = (1<<8), - STM32L0_NVM_OPTR_RDPROT_S = (0), - STM32L0_NVM_OPTR_RDPROT_M = (0xff), - STM32L0_NVM_OPTR_RDPROT_0 = (0xaa), - STM32L0_NVM_OPTR_RDPROT_2 = (0xcc), - - STM32L1_NVM_OPTR_nBFB2 = (1<<23), - STM32L1_NVM_OPTR_nRST_STDBY = (1<<22), - STM32L1_NVM_OPTR_nRST_STOP = (1<<21), - STM32L1_NVM_OPTR_WDG_SW = (1<<20), - STM32L1_NVM_OPTR_BOR_LEV_S = (16), - STM32L1_NVM_OPTR_BOR_LEV_M = (0xf), - STM32L1_NVM_OPTR_SPRMOD = (1<<8), - STM32L1_NVM_OPTR_RDPROT_S = (0), - STM32L1_NVM_OPTR_RDPROT_M = (0xff), - STM32L1_NVM_OPTR_RDPROT_0 = (0xaa), - STM32L1_NVM_OPTR_RDPROT_2 = (0xcc), + STM32Lx_STUB_PHYS = 0x20000000ul, + STM32Lx_STUB_INFO_PHYS = 0x20000004ul, + STM32Lx_STUB_DATA_PHYS = (0x20000000ul + 1024), + STM32Lx_STUB_DATA_MAX = 2048, + + STM32Lx_NVM_OPT_PHYS = 0x1ff80000ul, + STM32Lx_NVM_EEPROM_PHYS = 0x08080000ul, + + STM32L0_NVM_PHYS = 0x40022000ul, + STM32L0_NVM_PROG_PAGE_SIZE = 128, + STM32L0_NVM_DATA_PAGE_SIZE = 4, + STM32L0_NVM_OPT_SIZE = 12, + STM32L0_NVM_EEPROM_SIZE = 2*1024, + + STM32L1_NVM_PHYS = 0x40023c00ul, + STM32L1_NVM_PROG_PAGE_SIZE = 256, + STM32L1_NVM_DATA_PAGE_SIZE = 4, + STM32L1_NVM_OPT_SIZE = 32, + STM32L1_NVM_EEPROM_SIZE = 16*1024, + + STM32Lx_NVM_PEKEY1 = 0x89abcdeful, + STM32Lx_NVM_PEKEY2 = 0x02030405ul, + STM32Lx_NVM_PRGKEY1 = 0x8c9daebful, + STM32Lx_NVM_PRGKEY2 = 0x13141516ul, + STM32Lx_NVM_OPTKEY1 = 0xfbead9c8ul, + STM32Lx_NVM_OPTKEY2 = 0x24252627ul, + + STM32Lx_NVM_PECR_OBL_LAUNCH = (1<<18), + STM32Lx_NVM_PECR_ERRIE = (1<<17), + STM32Lx_NVM_PECR_EOPIE = (1<<16), + STM32Lx_NVM_PECR_FPRG = (1<<10), + STM32Lx_NVM_PECR_ERASE = (1<< 9), + STM32Lx_NVM_PECR_FIX = (1<< 8), /* FTDW */ + STM32Lx_NVM_PECR_DATA = (1<< 4), + STM32Lx_NVM_PECR_PROG = (1<< 3), + STM32Lx_NVM_PECR_OPTLOCK = (1<< 2), + STM32Lx_NVM_PECR_PRGLOCK = (1<< 1), + STM32Lx_NVM_PECR_PELOCK = (1<< 0), + + STM32Lx_NVM_SR_FWWERR = (1<<17), + STM32Lx_NVM_SR_NOTZEROERR = (1<<16), + STM32Lx_NVM_SR_RDERR = (1<<13), + STM32Lx_NVM_SR_OPTVER = (1<<11), + STM32Lx_NVM_SR_SIZERR = (1<<10), + STM32Lx_NVM_SR_PGAERR = (1<<9), + STM32Lx_NVM_SR_WRPERR = (1<<8), + STM32Lx_NVM_SR_READY = (1<<3), + STM32Lx_NVM_SR_HWOFF = (1<<2), + STM32Lx_NVM_SR_EOP = (1<<1), + STM32Lx_NVM_SR_BSY = (1<<0), + STM32Lx_NVM_SR_ERR_M = ( STM32Lx_NVM_SR_WRPERR + | STM32Lx_NVM_SR_PGAERR + | STM32Lx_NVM_SR_SIZERR + | STM32Lx_NVM_SR_NOTZEROERR), + + STM32L0_NVM_OPTR_BOOT1 = (1<<31), + STM32L0_NVM_OPTR_WDG_SW = (1<<20), + STM32L0_NVM_OPTR_WPRMOD = (1<<8), + STM32L0_NVM_OPTR_RDPROT_S = (0), + STM32L0_NVM_OPTR_RDPROT_M = (0xff), + STM32L0_NVM_OPTR_RDPROT_0 = (0xaa), + STM32L0_NVM_OPTR_RDPROT_2 = (0xcc), + + STM32L1_NVM_OPTR_nBFB2 = (1<<23), + STM32L1_NVM_OPTR_nRST_STDBY = (1<<22), + STM32L1_NVM_OPTR_nRST_STOP = (1<<21), + STM32L1_NVM_OPTR_WDG_SW = (1<<20), + STM32L1_NVM_OPTR_BOR_LEV_S = (16), + STM32L1_NVM_OPTR_BOR_LEV_M = (0xf), + STM32L1_NVM_OPTR_SPRMOD = (1<<8), + STM32L1_NVM_OPTR_RDPROT_S = (0), + STM32L1_NVM_OPTR_RDPROT_M = (0xff), + STM32L1_NVM_OPTR_RDPROT_0 = (0xaa), + STM32L1_NVM_OPTR_RDPROT_2 = (0xcc), }; #if defined (__cplusplus) namespace STM32 { - struct NVM { - volatile uint32_t acr; - volatile uint32_t pecr; - volatile uint32_t pdkeyr; - volatile uint32_t pkeyr; - volatile uint32_t prgkeyr; - volatile uint32_t optkeyr; - volatile uint32_t sr; - volatile uint32_t optr; - volatile uint32_t wrprot; - - static constexpr uint32_t PKEY1 = 0x89abcdef; - static constexpr uint32_t PKEY2 = 0x02030405; - static constexpr uint32_t PRGKEY1 = 0x8c9daebf; - static constexpr uint32_t PRGKEY2 = 0x13141516; - static constexpr uint32_t OPTKEY1 = 0xfbead9c8; - static constexpr uint32_t OPTKEY2 = 0x24252627; - static constexpr uint32_t PDKEY1 = 0x04152637; - static constexpr uint32_t PDKEY2 = 0xfafbfcfd; - }; - - static_assert(sizeof (NVM) == 9*4, "NVM size error"); + struct NVM { + volatile uint32_t acr; + volatile uint32_t pecr; + volatile uint32_t pdkeyr; + volatile uint32_t pkeyr; + volatile uint32_t prgkeyr; + volatile uint32_t optkeyr; + volatile uint32_t sr; + volatile uint32_t optr; + volatile uint32_t wrprot; + + static constexpr uint32_t PKEY1 = 0x89abcdef; + static constexpr uint32_t PKEY2 = 0x02030405; + static constexpr uint32_t PRGKEY1 = 0x8c9daebf; + static constexpr uint32_t PRGKEY2 = 0x13141516; + static constexpr uint32_t OPTKEY1 = 0xfbead9c8; + static constexpr uint32_t OPTKEY2 = 0x24252627; + static constexpr uint32_t PDKEY1 = 0x04152637; + static constexpr uint32_t PDKEY2 = 0xfafbfcfd; + }; + + static_assert(sizeof (NVM) == 9*4, "NVM size error"); } using stm32lx_stub_pointer_t = uint32_t*; @@ -140,16 +140,18 @@ using stm32lx_stub_pointer_t = uint32_t*; #define Info (*reinterpret_cast(STM32Lx_STUB_INFO_PHYS)) namespace { - inline __attribute((always_inline)) bool unlock (STM32::NVM& nvm) { - nvm.pecr = STM32Lx_NVM_PECR_PELOCK; // Lock to guarantee unlock - nvm.pkeyr = STM32::NVM::PKEY1; - nvm.pkeyr = STM32::NVM::PKEY2; - nvm.prgkeyr = STM32::NVM::PRGKEY1; - nvm.prgkeyr = STM32::NVM::PRGKEY2; - return !(nvm.pecr & STM32Lx_NVM_PECR_PRGLOCK); - } - inline __attribute((always_inline)) void lock (STM32::NVM& nvm) { - nvm.pecr = STM32Lx_NVM_PECR_PELOCK; } + inline __attribute((always_inline)) bool unlock (STM32::NVM& nvm) { + // Lock guarantees unlock + nvm.pecr = STM32Lx_NVM_PECR_PELOCK; + + nvm.pkeyr = STM32::NVM::PKEY1; + nvm.pkeyr = STM32::NVM::PKEY2; + nvm.prgkeyr = STM32::NVM::PRGKEY1; + nvm.prgkeyr = STM32::NVM::PRGKEY2; + return !(nvm.pecr & STM32Lx_NVM_PECR_PRGLOCK); + } + inline __attribute((always_inline)) void lock (STM32::NVM& nvm) { + nvm.pecr = STM32Lx_NVM_PECR_PELOCK; } } @@ -158,15 +160,15 @@ namespace { typedef uint32_t stm32lx_stub_pointer_t; struct stm32lx_nvm { - volatile uint32_t acr; - volatile uint32_t pecr; - volatile uint32_t pdkeyr; - volatile uint32_t pekeyr; - volatile uint32_t prgkeyr; - volatile uint32_t optkeyr; - volatile uint32_t sr; - volatile uint32_t optr; /* or obr */ - volatile uint32_t wrprot; /* or wprot1 */ + volatile uint32_t acr; + volatile uint32_t pecr; + volatile uint32_t pdkeyr; + volatile uint32_t pekeyr; + volatile uint32_t prgkeyr; + volatile uint32_t optkeyr; + volatile uint32_t sr; + volatile uint32_t optr; /* or obr */ + volatile uint32_t wrprot; /* or wprot1 */ }; #define STM32Lx_NVM(p) (*(struct stm32lx_nvm*) (p)) @@ -180,16 +182,16 @@ struct stm32lx_nvm { #endif enum { - OPT_STM32L1 = 1<<1, + OPT_STM32L1 = 1<<1, }; struct stm32lx_nvm_stub_info { - stm32lx_stub_pointer_t destination; - int32_t size; - stm32lx_stub_pointer_t source; - uint32_t nvm; - uint16_t page_size; - uint16_t options; + stm32lx_stub_pointer_t destination; + int32_t size; + stm32lx_stub_pointer_t source; + uint32_t nvm; + uint16_t page_size; + uint16_t options; } __attribute__((packed)); /* ----- Globals */ diff --git a/src/stm32l0.c b/src/stm32l0.c index 0f6dcdb..954a277 100644 --- a/src/stm32l0.c +++ b/src/stm32l0.c @@ -52,18 +52,34 @@ the best circumstances, the NVM operation functions will check the MCU state and either execute the stub or non-stub version accordingly. The user can override stubs as well with a command - in case the detection feature fails. + in case the detection feature fails...which it seems to do in + most cases. o Erase would be more efficient if we checked for non-blank-ness before initiating an erase. This would have to be done in a stub for efficiency. - o Mass erase broken. The method for performing a mass erase is to - set the options for read protection, reload the option bytes, set - options for no protection, and then reload the option bytes - again. The command fails because we lose contact with the target - when we perform the option byte reload. For the time being, the - command is disabled. + o Mass erase unimplemented. The method for performing a mass erase + is to set the options for read protection, reload the option + bytes, set options for no protection, and then reload the option + bytes again. The command fails because we lose contact with the + target when we perform the option byte reload. For the time + being, the command is disabled. + + The body of the function was the following. It is left here for + reference in case someone either discovers what is wrong with + these lines, or a change is made to the emulator that allows it + to regain control of the target after the option byte reload. + + stm32l0_option_write(t, 0x1ff80000, 0xffff0000); + adiv5_ap_mem_write(ap, STM32L0_NVM_PECR, STM32L0_NVM_PECR_OBL_LAUNCH); + stm32l0_option_write(t, 0x1ff80000, 0xff5500aa); + adiv5_ap_mem_write(ap, STM32L0_NVM_PECR, STM32L0_NVM_PECR_OBL_LAUNCH); + + uint32_t sr; + do { + sr = adiv5_ap_mem_read(ap, STM32L0_NVM_SR); + } while (sr & STM32L0_NVM_SR_BSY); o Errors. We probably should clear SR errors immediately after detecting them. If we don't then we always must wait for the NVM @@ -72,48 +88,27 @@ o There are minor inconsistencies between the stm32l0 and the stm32l1 in when handling NVM operations. - o When we erase or write individual words (not half-pages) on the - stm32l0, we set the PROG bit. On the stm32l1 the PROG bit is - only set when erasing. This is not documented in the register - summaries, but in the functional quick reference. - - o On the STM32L1xx, PECR can only be changed when the NVM - hardware is idle. The STM32L0xx allows the PECR to be updated - while an operation is in progress. - - o Performance. The throughput for writing is not high. We suspect - it may be possible to improve throughput significantly by increasing - the MCU clock. The code, as is, offers a simplicity without - undue knowledge of the inner workings of the MCUs. Increasing - clock frequencies would require substantial knowledge of the - clock tree. - - 0x1ff80000: 0x00aa 0xff55 OK - 0x1ff80004: 0x8070 0x7f8f OK - 0x1ff80008: 0x0000 0xffff OK - OPTR: 0x807000aa, RDPROT 0, WPRMOD 0, WDG_SW 1, BOOT1 1 - - - Options code -p *(int*)0x40022004 = 1 -p *(int*)0x4002200c = 0x89abcdef -p *(int*)0x4002200c = 0x02030405 -p *(int*)0x40022014 = 0xfbead9c8 -p *(int*)0x40022014 = 0x24252627 -p *(int*)0x40022004 = 0x10 -x/4wx 0x40022000 -p *(int*)0x1ff80000 = 0xff5500aa - - l1 program -p *(int*)0x40023c04 = 1 -p *(int*)0x40023c0c = 0x89abcdef -p *(int*)0x40023c0c = 0x02030405 -p *(int*)0x40023c10 = 0x8c9daebf -p *(int*)0x40023c10 = 0x13141516 - - -p *(int*)0x40023c14 = 0xfbead9c8 -p *(int*)0x40023c14 = 0x24252627 + o When we erase or write individual words (not half-pages) on the + stm32l0, we set the PROG bit. On the stm32l1 the PROG bit is + only set when erasing. This is not documented in the register + summaries, but in the functional quick reference. Argh. + + o On the STM32L1xx, PECR can only be changed when the NVM + hardware is idle. The STM32L0xx allows the PECR to be updated + while an operation is in progress. + + o Performance. The throughput for writing is not high. We + suspected it may be possible to improve throughput significantly + by increasing the MCU clock. The code, as is, offers a + simplicity without undue knowledge of the inner workings of the + MCUs. Increasing clock frequencies would require substantial + knowledge of the clock tree. + + FWIW, this was tried. We verified that the system clocks were + changed, but the flash write was no faster. It looks like this + is due to the fact that the emulator performs a target reset + before executing the flash operations, bringing the system back + to the reset state clocking. */ @@ -130,58 +125,53 @@ p *(int*)0x40023c14 = 0x24252627 #include "stm32lx-nvm.h" -static int inhibit_stubs; - -static int stm32lx_nvm_erase (struct target_s* target, - uint32_t addr, int len); -static int stm32lx_nvm_write (struct target_s* target, - uint32_t destination, - const uint8_t* source, - int size); - -static int stm32lx_nvm_prog_erase (struct target_s* target, - uint32_t addr, int len); -static int stm32lx_nvm_prog_write (struct target_s* target, - uint32_t destination, - const uint8_t* source, - int size); - -static int stm32lx_nvm_prog_erase_stubbed (struct target_s* target, - uint32_t addr, int len); -static int stm32lx_nvm_prog_write_stubbed (struct target_s* target, - uint32_t destination, - const uint8_t* source, - int size); - -static int stm32lx_nvm_data_erase (struct target_s* target, - uint32_t addr, int len); -static int stm32lx_nvm_data_write (struct target_s* target, - uint32_t destination, - const uint8_t* source, - int size); - -//static bool stm32l0_cmd_erase_mass (target* t, int argc, char** argv); +static int inhibit_stubs; /* Local option to force non-stub flash IO */ + +static int stm32lx_nvm_erase(struct target_s* target, + uint32_t addr, int len); +static int stm32lx_nvm_write(struct target_s* target, + uint32_t destination, + const uint8_t* source, + int size); + +static int stm32lx_nvm_prog_erase(struct target_s* target, + uint32_t addr, int len); +static int stm32lx_nvm_prog_write(struct target_s* target, + uint32_t destination, + const uint8_t* source, + int size); + +static int stm32lx_nvm_prog_erase_stubbed(struct target_s* target, + uint32_t addr, int len); +static int stm32lx_nvm_prog_write_stubbed(struct target_s* target, + uint32_t destination, + const uint8_t* source, + int size); + +static int stm32lx_nvm_data_erase(struct target_s* target, + uint32_t addr, int len); +static int stm32lx_nvm_data_write(struct target_s* target, + uint32_t destination, + const uint8_t* source, + int size); + static bool stm32lx_cmd_option (target* t, int argc, char** argv); static bool stm32lx_cmd_eeprom (target* t, int argc, char** argv); -//static bool stm32l0_cmd_reset (target* t, int argc, char** argv); static bool stm32lx_cmd_stubs (target* t, int argc, char** argv); static const struct command_s stm32lx_cmd_list[] = { - { "stubs", (cmd_handler) stm32lx_cmd_stubs, - "Enable/disable NVM operation stubs" }, -// { "erase_mass", (cmd_handler) stm32l0_cmd_erase_mass, -// "Erase NVM flash and data" }, -// { "reset", (cmd_handler) stm32l0_cmd_reset, "Reset target" }, - { "option", (cmd_handler) stm32lx_cmd_option, - "Manipulate option bytes"}, - { "eeprom", (cmd_handler) stm32lx_cmd_eeprom, - "Manipulate EEPROM (NVM data) memory"}, - { 0 }, + { "stubs", (cmd_handler) stm32lx_cmd_stubs, + "Enable/disable NVM operation stubs" }, + { "option", (cmd_handler) stm32lx_cmd_option, + "Manipulate option bytes"}, + { "eeprom", (cmd_handler) stm32lx_cmd_eeprom, + "Manipulate EEPROM(NVM data) memory"}, + { 0 }, }; enum { - STM32L0_DBGMCU_IDCODE_PHYS = 0x40015800, - STM32L1_DBGMCU_IDCODE_PHYS = 0xe0042000, + STM32L0_DBGMCU_IDCODE_PHYS = 0x40015800, + STM32L1_DBGMCU_IDCODE_PHYS = 0xe0042000, }; static const char stm32l0_driver_str[] = "STM32L0xx"; @@ -191,19 +181,19 @@ static const char stm32l0_xml_memory_map[] = "" " PUBLIC \"+//IDN gnu.org//DTD GDB Memory Map V1.0//EN\"" " \"http://sourceware.org/gdb/gdb-memory-map.dtd\">"*/ "" - /* Program flash; ranges up to 64KiB (0x10000). */ + /* Program flash; ranges up to 64KiB(0x10000). */ " " " 0x80" " " - /* Data (EEPROM) NVRAM; ranges up to 2KiB (0x800). */ + /* Data(EEPROM) NVRAM; ranges up to 2KiB(0x800). */ " " " 0x4" " " - /* SRAM; ranges up to 8KiB (0x2000). */ + /* SRAM; ranges up to 8KiB(0x2000). */ " " ""; -#if defined (CONFIG_STM32L1) +#if defined(CONFIG_STM32L1) static const char stm32l1_driver_str[] = "STM32L1xx"; static const char stm32l1_xml_memory_map[] = "" @@ -211,15 +201,15 @@ static const char stm32l1_xml_memory_map[] = "" " PUBLIC \"+//IDN gnu.org//DTD GDB Memory Map V1.0//EN\"" " \"http://sourceware.org/gdb/gdb-memory-map.dtd\">"*/ "" - /* Program flash; ranges from 32KiB to 512KiB (0x80000). */ + /* Program flash; ranges from 32KiB to 512KiB(0x80000). */ " " " 0x100" " " - /* Data (EEPROM) NVRAM; ranges from 2K to 16KiB (0x4000). */ + /* Data(EEPROM) NVRAM; ranges from 2K to 16KiB(0x4000). */ " " " 0x4" " " - /* SRAM; ranges from 4KiB to 80KiB (0x14000). */ + /* SRAM; ranges from 4KiB to 80KiB(0x14000). */ " " ""; #endif @@ -232,191 +222,194 @@ static const uint16_t stm32l0_nvm_prog_erase_stub [] = { #include "../flashstub/stm32l05x-nvm-prog-erase.stub" }; -static uint32_t stm32lx_nvm_prog_page_size (struct target_s* target) +static uint32_t stm32lx_nvm_prog_page_size(struct target_s* target) { - switch (target->idcode) { - case 0x417: /* STM32L0xx */ - return STM32L0_NVM_PROG_PAGE_SIZE; - default: /* STM32L1xx */ - return STM32L1_NVM_PROG_PAGE_SIZE; - } + switch (target->idcode) { + case 0x417: /* STM32L0xx */ + return STM32L0_NVM_PROG_PAGE_SIZE; + default: /* STM32L1xx */ + return STM32L1_NVM_PROG_PAGE_SIZE; + } } -static bool stm32lx_is_stm32l1 (struct target_s* target) +static bool stm32lx_is_stm32l1(struct target_s* target) { - switch (target->idcode) { - case 0x417: /* STM32L0xx */ - return false; - default: /* STM32L1xx */ - return true; - } + switch (target->idcode) { + case 0x417: /* STM32L0xx */ + return false; + default: /* STM32L1xx */ + return true; + } } -static uint32_t stm32lx_nvm_eeprom_size (struct target_s* target) +static uint32_t stm32lx_nvm_eeprom_size(struct target_s* target) { - switch (target->idcode) { - case 0x417: /* STM32L0xx */ - return STM32L0_NVM_EEPROM_SIZE; - default: /* STM32L1xx */ - return STM32L1_NVM_EEPROM_SIZE; - } + switch (target->idcode) { + case 0x417: /* STM32L0xx */ + return STM32L0_NVM_EEPROM_SIZE; + default: /* STM32L1xx */ + return STM32L1_NVM_EEPROM_SIZE; + } } -static uint32_t stm32lx_nvm_phys (struct target_s* target) +static uint32_t stm32lx_nvm_phys(struct target_s* target) { - switch (target->idcode) { - case 0x417: /* STM32L0xx */ - return STM32L0_NVM_PHYS; - default: /* STM32L1xx */ - return STM32L1_NVM_PHYS; - } + switch (target->idcode) { + case 0x417: /* STM32L0xx */ + return STM32L0_NVM_PHYS; + default: /* STM32L1xx */ + return STM32L1_NVM_PHYS; + } } -static uint32_t stm32lx_nvm_data_page_size (struct target_s* target) +static uint32_t stm32lx_nvm_data_page_size(struct target_s* target) { - switch (target->idcode) { - case 0x417: /* STM32L0xx */ - return STM32L0_NVM_DATA_PAGE_SIZE; - default: /* STM32L1xx */ - return STM32L1_NVM_DATA_PAGE_SIZE; - } + switch (target->idcode) { + case 0x417: /* STM32L0xx */ + return STM32L0_NVM_DATA_PAGE_SIZE; + default: /* STM32L1xx */ + return STM32L1_NVM_DATA_PAGE_SIZE; + } } -static uint32_t stm32lx_nvm_option_size (struct target_s* target) +static uint32_t stm32lx_nvm_option_size(struct target_s* target) { - switch (target->idcode) { - case 0x417: /* STM32L0xx */ - return STM32L0_NVM_OPT_SIZE; - default: /* STM32L1xx */ - return STM32L1_NVM_OPT_SIZE; - } + switch (target->idcode) { + case 0x417: /* STM32L0xx */ + return STM32L0_NVM_OPT_SIZE; + default: /* STM32L1xx */ + return STM32L1_NVM_OPT_SIZE; + } } /** Query MCU memory for an indication as to whether or not the currently attached target is served by this module. We detect the STM32L0xx parts as well as the STM32L1xx's. */ -bool stm32l0_probe (struct target_s* target) +bool stm32l0_probe(struct target_s* target) { - uint32_t idcode; - -#if defined (CONFIG_STM32L1) - - idcode = adiv5_ap_mem_read (adiv5_target_ap (target), - STM32L1_DBGMCU_IDCODE_PHYS) & 0xfff; - switch (idcode) { - case 0x416: /* CAT. 1 device */ - case 0x429: /* CAT. 2 device */ - case 0x427: /* CAT. 3 device */ - case 0x436: /* CAT. 4 device */ - case 0x437: /* CAT. 5 device */ - target->idcode = idcode; - target->driver = stm32l1_driver_str; - target->xml_mem_map = stm32l1_xml_memory_map; - target->flash_erase = stm32lx_nvm_erase; - target->flash_write = stm32lx_nvm_write; - target_add_commands (target, stm32lx_cmd_list, "STM32L1x"); - return true; - } + uint32_t idcode; + +#if defined(CONFIG_STM32L1) + + idcode = adiv5_ap_mem_read(adiv5_target_ap(target), + STM32L1_DBGMCU_IDCODE_PHYS) & 0xfff; + switch (idcode) { + case 0x416: /* CAT. 1 device */ + case 0x429: /* CAT. 2 device */ + case 0x427: /* CAT. 3 device */ + case 0x436: /* CAT. 4 device */ + case 0x437: /* CAT. 5 device */ + target->idcode = idcode; + target->driver = stm32l1_driver_str; + target->xml_mem_map = stm32l1_xml_memory_map; + target->flash_erase = stm32lx_nvm_erase; + target->flash_write = stm32lx_nvm_write; + target_add_commands(target, stm32lx_cmd_list, "STM32L1x"); + return true; + } #endif - idcode = adiv5_ap_mem_read (adiv5_target_ap (target), - STM32L0_DBGMCU_IDCODE_PHYS) & 0xfff; - switch (idcode) { - default: - break; - - case 0x417: /* STM32L0x[123] & probably others */ - target->idcode = idcode; - target->driver = stm32l0_driver_str; - target->xml_mem_map = stm32l0_xml_memory_map; - target->flash_erase = stm32lx_nvm_erase; - target->flash_write = stm32lx_nvm_write; - target_add_commands (target, stm32lx_cmd_list, "STM32L0x"); - return true; - } - - return false; + idcode = adiv5_ap_mem_read(adiv5_target_ap(target), + STM32L0_DBGMCU_IDCODE_PHYS) & 0xfff; + switch (idcode) { + default: + break; + + case 0x417: /* STM32L0x[123] & probably others */ + target->idcode = idcode; + target->driver = stm32l0_driver_str; + target->xml_mem_map = stm32l0_xml_memory_map; + target->flash_erase = stm32lx_nvm_erase; + target->flash_write = stm32lx_nvm_write; + target_add_commands(target, stm32lx_cmd_list, "STM32L0x"); + return true; + } + + return false; } + /** Lock the NVM control registers preventing writes or erases. */ -static void stm32lx_nvm_lock (ADIv5_AP_t* ap, uint32_t nvm) +static void stm32lx_nvm_lock(ADIv5_AP_t* ap, uint32_t nvm) { - adiv5_ap_mem_write (ap, STM32Lx_NVM_PECR(nvm), STM32Lx_NVM_PECR_PELOCK); + adiv5_ap_mem_write(ap, STM32Lx_NVM_PECR(nvm), STM32Lx_NVM_PECR_PELOCK); } + /** Unlock the NVM control registers for modifying program or data flash. Returns true if the unlock succeeds. */ -static bool stm32lx_nvm_prog_data_unlock (ADIv5_AP_t* ap, uint32_t nvm) +static bool stm32lx_nvm_prog_data_unlock(ADIv5_AP_t* ap, uint32_t nvm) { - /* Always lock first because that's the only way to know that the - unlock can succeed on the STM32L0's. */ - adiv5_ap_mem_write (ap, STM32Lx_NVM_PECR(nvm), STM32Lx_NVM_PECR_PELOCK); - adiv5_ap_mem_write (ap, STM32Lx_NVM_PEKEYR(nvm), STM32Lx_NVM_PEKEY1); - adiv5_ap_mem_write (ap, STM32Lx_NVM_PEKEYR(nvm), STM32Lx_NVM_PEKEY2); - adiv5_ap_mem_write (ap, STM32Lx_NVM_PRGKEYR(nvm), STM32Lx_NVM_PRGKEY1); - adiv5_ap_mem_write (ap, STM32Lx_NVM_PRGKEYR(nvm), STM32Lx_NVM_PRGKEY2); - - return !(adiv5_ap_mem_read (ap, STM32Lx_NVM_PECR(nvm)) - & STM32Lx_NVM_PECR_PRGLOCK); + /* Always lock first because that's the only way to know that the + unlock can succeed on the STM32L0's. */ + adiv5_ap_mem_write(ap, STM32Lx_NVM_PECR(nvm), STM32Lx_NVM_PECR_PELOCK); + adiv5_ap_mem_write(ap, STM32Lx_NVM_PEKEYR(nvm), STM32Lx_NVM_PEKEY1); + adiv5_ap_mem_write(ap, STM32Lx_NVM_PEKEYR(nvm), STM32Lx_NVM_PEKEY2); + adiv5_ap_mem_write(ap, STM32Lx_NVM_PRGKEYR(nvm), STM32Lx_NVM_PRGKEY1); + adiv5_ap_mem_write(ap, STM32Lx_NVM_PRGKEYR(nvm), STM32Lx_NVM_PRGKEY2); + + return !(adiv5_ap_mem_read(ap, STM32Lx_NVM_PECR(nvm)) + & STM32Lx_NVM_PECR_PRGLOCK); } /** Unlock the NVM control registers for modifying option bytes. Returns true if the unlock succeeds. */ -static bool stm32lx_nvm_opt_unlock (ADIv5_AP_t* ap, uint32_t nvm) +static bool stm32lx_nvm_opt_unlock(ADIv5_AP_t* ap, uint32_t nvm) { - /* Always lock first because that's the only way to know that the - unlock can succeed on the STM32L0's. */ - adiv5_ap_mem_write (ap, STM32Lx_NVM_PECR(nvm), STM32Lx_NVM_PECR_PELOCK); - adiv5_ap_mem_write (ap, STM32Lx_NVM_PEKEYR(nvm), STM32Lx_NVM_PEKEY1); - adiv5_ap_mem_write (ap, STM32Lx_NVM_PEKEYR(nvm), STM32Lx_NVM_PEKEY2); - adiv5_ap_mem_write (ap, STM32Lx_NVM_OPTKEYR(nvm), STM32Lx_NVM_OPTKEY1); - adiv5_ap_mem_write (ap, STM32Lx_NVM_OPTKEYR(nvm), STM32Lx_NVM_OPTKEY2); - - return !(adiv5_ap_mem_read (ap, STM32Lx_NVM_PECR(nvm)) - & STM32Lx_NVM_PECR_OPTLOCK); + /* Always lock first because that's the only way to know that the + unlock can succeed on the STM32L0's. */ + adiv5_ap_mem_write(ap, STM32Lx_NVM_PECR(nvm), STM32Lx_NVM_PECR_PELOCK); + adiv5_ap_mem_write(ap, STM32Lx_NVM_PEKEYR(nvm), STM32Lx_NVM_PEKEY1); + adiv5_ap_mem_write(ap, STM32Lx_NVM_PEKEYR(nvm), STM32Lx_NVM_PEKEY2); + adiv5_ap_mem_write(ap, STM32Lx_NVM_OPTKEYR(nvm), STM32Lx_NVM_OPTKEY1); + adiv5_ap_mem_write(ap, STM32Lx_NVM_OPTKEYR(nvm), STM32Lx_NVM_OPTKEY2); + + return !(adiv5_ap_mem_read(ap, STM32Lx_NVM_PECR(nvm)) + & STM32Lx_NVM_PECR_OPTLOCK); } /** Erase a region of flash using a stub function. This only works - when the MCU hasn't entered a fault state (see NOTES). The flash + when the MCU hasn't entered a fault state(see NOTES). The flash array is erased for all pages from addr to addr+len inclusive. */ -static int stm32lx_nvm_prog_erase_stubbed (struct target_s* target, - uint32_t addr, int size) +static int stm32lx_nvm_prog_erase_stubbed(struct target_s* target, + uint32_t addr, int size) { - struct stm32lx_nvm_stub_info info; - const uint32_t nvm = stm32lx_nvm_phys (target); - - info.nvm = nvm; - info.page_size = stm32lx_nvm_prog_page_size (target); - - /* Load the stub */ - target_mem_write_words (target, STM32Lx_STUB_PHYS, - (void*) &stm32l0_nvm_prog_erase_stub[0], - sizeof (stm32l0_nvm_prog_erase_stub)); - - /* Setup parameters */ - info.destination = addr; - info.size = size; - - /* Copy parameters */ - target_mem_write_words (target, STM32Lx_STUB_INFO_PHYS, - (void*) &info, sizeof (info)); - - /* Execute stub */ - target_pc_write (target, STM32Lx_STUB_PHYS); - if (target_check_error (target)) - return -1; - target_halt_resume (target, 0); - while (!target_halt_wait (target)) - ; - { - ADIv5_AP_t* ap = adiv5_target_ap(target); - if (adiv5_ap_mem_read (ap, STM32Lx_NVM_SR(nvm)) & STM32Lx_NVM_SR_ERR_M) - return -1; - } - - return 0; + struct stm32lx_nvm_stub_info info; + const uint32_t nvm = stm32lx_nvm_phys(target); + + info.nvm = nvm; + info.page_size = stm32lx_nvm_prog_page_size(target); + + /* Load the stub */ + target_mem_write_words(target, STM32Lx_STUB_PHYS, + (void*) &stm32l0_nvm_prog_erase_stub[0], + sizeof(stm32l0_nvm_prog_erase_stub)); + + /* Setup parameters */ + info.destination = addr; + info.size = size; + + /* Copy parameters */ + target_mem_write_words(target, STM32Lx_STUB_INFO_PHYS, + (void*) &info, sizeof(info)); + + /* Execute stub */ + target_pc_write(target, STM32Lx_STUB_PHYS); + if (target_check_error(target)) + return -1; + target_halt_resume(target, 0); + while (!target_halt_wait(target)) + ; + { + ADIv5_AP_t* ap = adiv5_target_ap(target); + if (adiv5_ap_mem_read(ap, STM32Lx_NVM_SR(nvm)) + & STM32Lx_NVM_SR_ERR_M) + return -1; + } + + return 0; } @@ -424,259 +417,289 @@ static int stm32lx_nvm_prog_erase_stubbed (struct target_s* target, when the MCU hasn't entered a fault state. Once the MCU faults, this function will not succeed because the MCU will fault before executing a single instruction in the stub. */ -static int stm32lx_nvm_prog_write_stubbed (struct target_s* target, - uint32_t destination, - const uint8_t* source, - int size) +static int stm32lx_nvm_prog_write_stubbed(struct target_s* target, + uint32_t destination, + const uint8_t* source, + int size) { - struct stm32lx_nvm_stub_info info; - const uint32_t nvm = stm32lx_nvm_phys (target); - const size_t page_size = stm32lx_nvm_prog_page_size (target); - - /* We can't handle unaligned destination or non-word writes. */ - /* *** FIXME: we should handle misaligned writes by padding with - *** zeros. Probably, the only real time we'd see something - *** misaligned would be on a write to a final half-word. Perhaps - *** this could be handled with the stub? In fact, aligning the - *** start is going to be mandatory. We will change the code to - *** cope with a trailing half-word. */ - if ((destination & 3) || (size & 3)) - return -1; - - info.nvm = nvm; - info.page_size = page_size; - - /* Load the stub */ - target_mem_write_words (target, STM32Lx_STUB_PHYS, - (void*) &stm32l0_nvm_prog_write_stub[0], - sizeof (stm32l0_nvm_prog_write_stub)); - - while (size > 0) { - - /* Max transfer size is adjusted in the event that the - destination isn't half-page aligned. This allows the - sub to write the first partial half-page and then - as many half-pages as will fit in the buffer. */ - size_t max = STM32Lx_STUB_DATA_MAX - - (destination - (destination & ~(info.page_size/2 - 1))); - size_t cb = size; - if (cb > max) - cb = max; - - /* Setup parameters */ - info.source = STM32Lx_STUB_DATA_PHYS; - info.destination = destination; - info.size = cb; - - /* Copy data to write to flash */ - target_mem_write_words (target, info.source, (void*) source, info.size); - - /* Move pointers early */ - destination += cb; - source += cb; - size -= cb; - - /* Copy parameters */ - target_mem_write_words (target, STM32Lx_STUB_INFO_PHYS, - (void*) &info, sizeof (info)); - - /* Execute stub */ - target_pc_write (target, STM32Lx_STUB_PHYS); - if (target_check_error (target)) - return -1; - target_halt_resume (target, 0); - while (!target_halt_wait (target)) - ; - - if (adiv5_ap_mem_read (adiv5_target_ap (target), STM32Lx_NVM_SR(nvm)) - & STM32Lx_NVM_SR_ERR_M) - return -1; - } - - return 0; + struct stm32lx_nvm_stub_info info; + const uint32_t nvm = stm32lx_nvm_phys(target); + const size_t page_size = stm32lx_nvm_prog_page_size(target); + + /* We can only handle word aligned writes and even + word-multiple ranges. The stm32lx's cannot perform + anything smaller than a word write due to the ECC bits. + So, the caller must do the fixup. */ + if ((destination & 3) || (size & 3)) + return -1; + + info.nvm = nvm; + info.page_size = page_size; + + /* Load the stub */ + target_mem_write_words(target, STM32Lx_STUB_PHYS, + (void*) &stm32l0_nvm_prog_write_stub[0], + sizeof(stm32l0_nvm_prog_write_stub)); + + while (size > 0) { + + /* Max transfer size is adjusted in the event that the + destination isn't half-page aligned. This allows + the stub to write the first partial half-page and + then as many half-pages as will fit in the + buffer. */ + size_t max = STM32Lx_STUB_DATA_MAX + - (destination - (destination + & ~(info.page_size/2 - 1))); + size_t cb = size; + if (cb > max) + cb = max; + + /* Setup parameters */ + info.source = STM32Lx_STUB_DATA_PHYS; + info.destination = destination; + info.size = cb; + + /* Copy data to write to flash */ + target_mem_write_words(target, info.source, (void*) source, + info.size); + + /* Move pointers early */ + destination += cb; + source += cb; + size -= cb; + + /* Copy parameters */ + target_mem_write_words(target, STM32Lx_STUB_INFO_PHYS, + (void*) &info, sizeof(info)); + + /* Execute stub */ + target_pc_write(target, STM32Lx_STUB_PHYS); + if (target_check_error(target)) + return -1; + target_halt_resume(target, 0); + while (!target_halt_wait(target)) + ; + + if (adiv5_ap_mem_read(adiv5_target_ap(target), + STM32Lx_NVM_SR(nvm)) + & STM32Lx_NVM_SR_ERR_M) + return -1; + } + + return 0; } /** Erase a region of NVM for STM32Lx. This is the lead function and it will invoke an implementation, stubbed or not depending on the options and the range of addresses. */ -static int stm32lx_nvm_erase (struct target_s* target, uint32_t addr, int size) +static int stm32lx_nvm_erase(struct target_s* target, uint32_t addr, int size) { - if (addr >= STM32Lx_NVM_EEPROM_PHYS) - return stm32lx_nvm_data_erase (target, addr, size); + if (addr >= STM32Lx_NVM_EEPROM_PHYS) + return stm32lx_nvm_data_erase(target, addr, size); - /* Use stub if not inhibited, the MCU is in a non-exceptonal state - and there is stub. */ - volatile uint32_t regs[20]; - target_regs_read (target, ®s); - if (inhibit_stubs || (regs[16] & 0xf)) - return stm32lx_nvm_prog_erase (target, addr, size); + /* Use stub if not inhibited, the MCU is in a non-exceptonal state + and there is stub. */ + volatile uint32_t regs[20]; + target_regs_read(target, ®s); + if (inhibit_stubs || (regs[16] & 0xf)) + return stm32lx_nvm_prog_erase(target, addr, size); - return stm32lx_nvm_prog_erase_stubbed (target, addr, size); + return stm32lx_nvm_prog_erase_stubbed(target, addr, size); } -/** Write to a region on NVM for STM32L1xx. This is the lead function - and it will ibvoke an implementation, stubbed or not depending on - the options and the range of addresses. */ -static int stm32lx_nvm_write (struct target_s* target, - uint32_t destination, - const uint8_t* source, - int size) +/** Write to a region on NVM for STM32Lxxx. This is the lead function + and it will invoke an implementation, stubbed or not depending on + the options and the range of addresses. Data (EEPROM) writes + don't have to care about alignment, but the program flash does. + There is a fixup for unaligned program flash writes. */ +static int stm32lx_nvm_write(struct target_s* target, + uint32_t destination, + const uint8_t* source, + int size) { - if (destination >= STM32Lx_NVM_EEPROM_PHYS) - return stm32lx_nvm_data_write (target, destination, source, size); - - /* Skip stub if the MCU is in a questionable state or if the user - asks us to avoid stubs. */ - volatile uint32_t regs[20]; - target_regs_read (target, ®s); - if (inhibit_stubs || (regs[16] & 0xf)) - return stm32lx_nvm_prog_write (target, destination, source, size); - - return stm32lx_nvm_prog_write_stubbed (target, destination, source, size); + if (destination >= STM32Lx_NVM_EEPROM_PHYS) + return stm32lx_nvm_data_write(target, destination, source, + size); + + /* Unaligned destinations. To make this feature simple to + implement, we do a fixup on the source data as well as the + adjusting the write parameters if the caller has asked for + an unaligned operation. Padding of this data is zeros + because the STM32L's are built that way. */ + if ((destination & 3) || (size & 3)) { + size_t size_aligned = size + + (destination & 3) + + (((size + 3) & ~3) - size); + uint8_t* source_aligned = alloca (size_aligned); + memset (source_aligned, 0, size_aligned); + memcpy (source_aligned + (destination & 3), source, size); + source = source_aligned; + destination &= ~3; + size = size_aligned; + } + + /* Skip stub if the MCU is in a questionable state, or if the + user asks us to avoid stubs. */ + volatile uint32_t regs[20]; + target_regs_read(target, ®s); + if (inhibit_stubs || (regs[16] & 0xf)) + return stm32lx_nvm_prog_write(target, destination, source, + size); + + return stm32lx_nvm_prog_write_stubbed(target, destination, source, + size); } /** Erase a region of program flash using operations through the debug - interface. This is slower than stubbed versions (see NOTES). The + interface. This is slower than stubbed versions(see NOTES). The flash array is erased for all pages from addr to addr+len inclusive. NVM register file address chosen from target. */ -static int stm32lx_nvm_prog_erase (struct target_s* target, - uint32_t addr, int len) +static int stm32lx_nvm_prog_erase(struct target_s* target, + uint32_t addr, int len) { - ADIv5_AP_t* ap = adiv5_target_ap (target); - const size_t page_size = stm32lx_nvm_prog_page_size (target); - const uint32_t nvm = stm32lx_nvm_phys (target); - - /* Word align */ - len += (addr & 3); - addr &= ~3; - - if (!stm32lx_nvm_prog_data_unlock (ap, nvm)) - return -1; - - /* Flash page erase instruction */ - adiv5_ap_mem_write (ap, STM32Lx_NVM_PECR(nvm), - STM32Lx_NVM_PECR_ERASE | STM32Lx_NVM_PECR_PROG); - - { - uint32_t pecr = adiv5_ap_mem_read (ap, STM32Lx_NVM_PECR (nvm)); - if ((pecr & (STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE)) - != (STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE)) - return -1; - } - - /* Clear errors. Note that this only works when we wait for the NVM - block to complete the last operation. */ - adiv5_ap_mem_write (ap, STM32Lx_NVM_SR (nvm), STM32Lx_NVM_SR_ERR_M); - - while (len > 0) { - /* Write first word of page to 0 */ - adiv5_ap_mem_write (ap, addr, 0); - - len -= page_size; - addr += page_size; - } - - /* Disable further programming by locking PECR */ - stm32lx_nvm_lock (ap, nvm); - - /* Wait for completion or an error */ - while (1) { - uint32_t sr = adiv5_ap_mem_read (ap, STM32Lx_NVM_SR(nvm)); - if (target_check_error (target)) - return -1; - if (sr & STM32Lx_NVM_SR_BSY) - continue; - if ((sr & STM32Lx_NVM_SR_ERR_M) || !(sr & STM32Lx_NVM_SR_EOP)) - return -1; - break; - } - - return 0; + ADIv5_AP_t* ap = adiv5_target_ap(target); + const size_t page_size = stm32lx_nvm_prog_page_size(target); + const uint32_t nvm = stm32lx_nvm_phys(target); + + /* Word align */ + len += (addr & 3); + addr &= ~3; + + if (!stm32lx_nvm_prog_data_unlock(ap, nvm)) + return -1; + + /* Flash page erase instruction */ + adiv5_ap_mem_write(ap, STM32Lx_NVM_PECR(nvm), + STM32Lx_NVM_PECR_ERASE | STM32Lx_NVM_PECR_PROG); + + { + uint32_t pecr = adiv5_ap_mem_read(ap, STM32Lx_NVM_PECR(nvm)); + if ((pecr & (STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE)) + != (STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE)) + return -1; + } + + /* Clear errors. Note that this only works when we wait for the NVM + block to complete the last operation. */ + adiv5_ap_mem_write(ap, STM32Lx_NVM_SR(nvm), STM32Lx_NVM_SR_ERR_M); + + while (len > 0) { + /* Write first word of page to 0 */ + adiv5_ap_mem_write(ap, addr, 0); + + len -= page_size; + addr += page_size; + } + + /* Disable further programming by locking PECR */ + stm32lx_nvm_lock(ap, nvm); + + /* Wait for completion or an error */ + while (1) { + uint32_t sr = adiv5_ap_mem_read(ap, STM32Lx_NVM_SR(nvm)); + if (target_check_error(target)) + return -1; + if (sr & STM32Lx_NVM_SR_BSY) + continue; + if ((sr & STM32Lx_NVM_SR_ERR_M) || !(sr & STM32Lx_NVM_SR_EOP)) + return -1; + break; + } + + return 0; } /** Write to program flash using operations through the debug - interface. This is slower than the stubbed write (see NOTES). + interface. This is slower than the stubbed write(see NOTES). NVM register file address chosen from target. */ -static int stm32lx_nvm_prog_write (struct target_s* target, - uint32_t destination, - const uint8_t* source_8, - int size) +static int stm32lx_nvm_prog_write(struct target_s* target, + uint32_t destination, + const uint8_t* source_8, + int size) { - ADIv5_AP_t* ap = adiv5_target_ap (target); - const uint32_t nvm = stm32lx_nvm_phys (target); - const bool is_stm32l1 = stm32lx_is_stm32l1 (target); - - /* We can only handle word aligned writes and even word-multiple - ranges. The stm32l0 cannot perform anything smaller than a word - write due to the ECC bits. */ - if ((destination & 3) || (size & 3)) - return -1; - - if (!stm32lx_nvm_prog_data_unlock (ap, nvm)) - return -1; - - const size_t half_page_size = stm32lx_nvm_prog_page_size (target)/2; - uint32_t* source = (uint32_t*) source_8; - - while (size > 0) { - - /* Wait for BSY to clear because we cannot write the PECR until - the previous operation completes on STM32L1xx. */ - while (adiv5_ap_mem_read (ap, STM32Lx_NVM_SR(nvm)) & STM32Lx_NVM_SR_BSY) - if (target_check_error(target)) { - return -1; - } - - // Either we're not half-page aligned or we have less than a half - // page to write - if (size < half_page_size || (destination & (half_page_size - 1))) { - adiv5_ap_mem_write (ap, STM32Lx_NVM_PECR(nvm), - is_stm32l1 ? 0 : STM32Lx_NVM_PECR_PROG); - size_t c = half_page_size - (destination & (half_page_size - 1)); - - if (c > size) - c = size; - size -= c; - - target_mem_write_words (target, destination, source, c); - source += c/4; - destination += c; - } - // Or we are writing a half-page(s) - else { - adiv5_ap_mem_write (ap, STM32Lx_NVM_PECR (nvm), - STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_FPRG); - - size_t c = size & ~(half_page_size - 1); - size -= c; - target_mem_write_words (target, destination, source, c); - source += c/4; - destination += c; - } - } - - /* Disable further programming by locking PECR */ - stm32lx_nvm_lock (ap, nvm); - - /* Wait for completion or an error */ - while (1) { - uint32_t sr = adiv5_ap_mem_read (ap, STM32Lx_NVM_SR (nvm)); - if (target_check_error (target)) { - return -1; - } - if (sr & STM32Lx_NVM_SR_BSY) - continue; - if ((sr & STM32Lx_NVM_SR_ERR_M) || !(sr & STM32Lx_NVM_SR_EOP)) { - return -1; - } - break; - } - - return 0; + ADIv5_AP_t* ap = adiv5_target_ap(target); + const uint32_t nvm = stm32lx_nvm_phys(target); + const bool is_stm32l1 = stm32lx_is_stm32l1(target); + + /* We can only handle word aligned writes and even + word-multiple ranges. The stm32lx's cannot perform + anything smaller than a word write due to the ECC bits. + So, the caller must do the fixup. */ + if ((destination & 3) || (size & 3)) + return -1; + + if (!stm32lx_nvm_prog_data_unlock(ap, nvm)) + return -1; + + const size_t half_page_size = stm32lx_nvm_prog_page_size(target)/2; + uint32_t* source = (uint32_t*) source_8; + + while (size > 0) { + + /* Wait for BSY to clear because we cannot write the PECR until + the previous operation completes on STM32Lxxx. */ + while (adiv5_ap_mem_read(ap, STM32Lx_NVM_SR(nvm)) + & STM32Lx_NVM_SR_BSY) + if (target_check_error(target)) { + return -1; + } + + // Either we're not half-page aligned or we have less + // than a half page to write + if (size < half_page_size + || (destination & (half_page_size - 1))) { + adiv5_ap_mem_write(ap, STM32Lx_NVM_PECR(nvm), + is_stm32l1 + ? 0 + : STM32Lx_NVM_PECR_PROG); + size_t c = half_page_size - (destination + & (half_page_size - 1)); + + if (c > size) + c = size; + size -= c; + + target_mem_write_words(target, destination, source, c); + source += c/4; + destination += c; + } + // Or we are writing a half-page(s) + else { + adiv5_ap_mem_write(ap, STM32Lx_NVM_PECR(nvm), + STM32Lx_NVM_PECR_PROG + | STM32Lx_NVM_PECR_FPRG); + + size_t c = size & ~(half_page_size - 1); + size -= c; + target_mem_write_words(target, destination, source, c); + source += c/4; + destination += c; + } + } + + /* Disable further programming by locking PECR */ + stm32lx_nvm_lock(ap, nvm); + + /* Wait for completion or an error */ + while (1) { + uint32_t sr = adiv5_ap_mem_read(ap, STM32Lx_NVM_SR(nvm)); + if (target_check_error(target)) { + return -1; + } + if (sr & STM32Lx_NVM_SR_BSY) + continue; + if ((sr & STM32Lx_NVM_SR_ERR_M) || !(sr & STM32Lx_NVM_SR_EOP)) { + return -1; + } + break; + } + + return 0; } @@ -684,110 +707,105 @@ static int stm32lx_nvm_prog_write (struct target_s* target, interface . The flash is erased for all pages from addr to addr+len, inclusive, on a word boundary. NVM register file address chosen from target. */ -static int stm32lx_nvm_data_erase (struct target_s* target, - uint32_t addr, int len) +static int stm32lx_nvm_data_erase(struct target_s* target, + uint32_t addr, int len) { - ADIv5_AP_t* ap = adiv5_target_ap (target); - const size_t page_size = stm32lx_nvm_data_page_size (target); - const uint32_t nvm = stm32lx_nvm_phys (target); - - /* Word align */ - len += (addr & 3); - addr &= ~3; - - if (!stm32lx_nvm_prog_data_unlock (ap, nvm)) - return -1; - - /* Flash data erase instruction */ - adiv5_ap_mem_write (ap, STM32Lx_NVM_PECR(nvm), - STM32Lx_NVM_PECR_ERASE | STM32Lx_NVM_PECR_DATA); - - { - uint32_t pecr = adiv5_ap_mem_read (ap, STM32Lx_NVM_PECR(nvm)); - if ((pecr & (STM32Lx_NVM_PECR_ERASE | STM32Lx_NVM_PECR_DATA)) - != (STM32Lx_NVM_PECR_ERASE | STM32Lx_NVM_PECR_DATA)) - return -1; - } - - while (len > 0) { - /* Write first word of page to 0 */ - adiv5_ap_mem_write (ap, addr, 0); - - len -= page_size; - addr += page_size; - } - - /* Disable further programming by locking PECR */ - stm32lx_nvm_lock (ap, nvm); - - /* Wait for completion or an error */ - while (1) { - uint32_t sr = adiv5_ap_mem_read (ap, STM32Lx_NVM_SR (nvm)); - if (target_check_error (target)) - return -1; - if (sr & STM32Lx_NVM_SR_BSY) - continue; - if ((sr & STM32Lx_NVM_SR_ERR_M) || !(sr & STM32Lx_NVM_SR_EOP)) - return -1; - break; - } - - return 0; + ADIv5_AP_t* ap = adiv5_target_ap(target); + const size_t page_size = stm32lx_nvm_data_page_size(target); + const uint32_t nvm = stm32lx_nvm_phys(target); + + /* Word align */ + len += (addr & 3); + addr &= ~3; + + if (!stm32lx_nvm_prog_data_unlock(ap, nvm)) + return -1; + + /* Flash data erase instruction */ + adiv5_ap_mem_write(ap, STM32Lx_NVM_PECR(nvm), + STM32Lx_NVM_PECR_ERASE | STM32Lx_NVM_PECR_DATA); + + { + uint32_t pecr = adiv5_ap_mem_read(ap, STM32Lx_NVM_PECR(nvm)); + if ((pecr & (STM32Lx_NVM_PECR_ERASE | STM32Lx_NVM_PECR_DATA)) + != (STM32Lx_NVM_PECR_ERASE | STM32Lx_NVM_PECR_DATA)) + return -1; + } + + while (len > 0) { + /* Write first word of page to 0 */ + adiv5_ap_mem_write(ap, addr, 0); + + len -= page_size; + addr += page_size; + } + + /* Disable further programming by locking PECR */ + stm32lx_nvm_lock(ap, nvm); + + /* Wait for completion or an error */ + while (1) { + uint32_t sr = adiv5_ap_mem_read(ap, STM32Lx_NVM_SR(nvm)); + if (target_check_error(target)) + return -1; + if (sr & STM32Lx_NVM_SR_BSY) + continue; + if ((sr & STM32Lx_NVM_SR_ERR_M) || !(sr & STM32Lx_NVM_SR_EOP)) + return -1; + break; + } + + return 0; } /** Write to data flash using operations through the debug interface. - NVM register file address chosen from target. - - *** FIXME: need to make this work with writing a single byte as - well as words. */ -static int stm32lx_nvm_data_write (struct target_s* target, - uint32_t destination, - const uint8_t* source_8, - int size) + NVM register file address chosen from target. Unaligned + destination writes are supported (though unaligned sources are + not). */ +static int stm32lx_nvm_data_write(struct target_s* target, + uint32_t destination, + const uint8_t* source_8, + int size) { - ADIv5_AP_t* ap = adiv5_target_ap (target); - const uint32_t nvm = stm32lx_nvm_phys (target); - const bool is_stm32l1 = stm32lx_is_stm32l1 (target); - - /* *** FIXME: need to make this work with writing a single byte. */ - if ((destination & 3) || (size & 3)) - return -1; - - if (!stm32lx_nvm_prog_data_unlock (ap, nvm)) - return -1; - - uint32_t* source = (uint32_t*) source_8; - - adiv5_ap_mem_write (ap, STM32Lx_NVM_PECR(nvm), - is_stm32l1 ? 0 : STM32Lx_NVM_PECR_DATA); - - while (size) { - size -= 4; - uint32_t v = *source++; - adiv5_ap_mem_write (ap, destination, v); - destination += 4; - - if (target_check_error (target)) - return -1; - } - - /* Disable further programming by locking PECR */ - stm32lx_nvm_lock (ap, nvm); - - /* Wait for completion or an error */ - while (1) { - uint32_t sr = adiv5_ap_mem_read (ap, STM32Lx_NVM_SR(nvm)); - if (target_check_error (target)) - return -1; - if (sr & STM32Lx_NVM_SR_BSY) - continue; - if ((sr & STM32Lx_NVM_SR_ERR_M) || !(sr & STM32Lx_NVM_SR_EOP)) - return -1; - break; - } - - return 0; + ADIv5_AP_t* ap = adiv5_target_ap(target); + const uint32_t nvm = stm32lx_nvm_phys(target); + const bool is_stm32l1 = stm32lx_is_stm32l1(target); + uint32_t* source = (uint32_t*) source_8; + + if (!stm32lx_nvm_prog_data_unlock(ap, nvm)) + return -1; + + + adiv5_ap_mem_write(ap, STM32Lx_NVM_PECR(nvm), + is_stm32l1 ? 0 : STM32Lx_NVM_PECR_DATA); + + while (size) { + size -= 4; + uint32_t v = *source++; + adiv5_ap_mem_write(ap, destination, v); + destination += 4; + + if (target_check_error(target)) + return -1; + } + + /* Disable further programming by locking PECR */ + stm32lx_nvm_lock(ap, nvm); + + /* Wait for completion or an error */ + while (1) { + uint32_t sr = adiv5_ap_mem_read(ap, STM32Lx_NVM_SR(nvm)); + if (target_check_error(target)) + return -1; + if (sr & STM32Lx_NVM_SR_BSY) + continue; + if ((sr & STM32Lx_NVM_SR_ERR_M) || !(sr & STM32Lx_NVM_SR_EOP)) + return -1; + break; + } + + return 0; } @@ -797,21 +815,21 @@ static int stm32lx_nvm_data_write (struct target_s* target, format where the upper 16 bits are the 1s complement of the lower 16 bits. The funtion returns when the operation is complete. The return value is true if the write succeeded. */ -static bool stm32lx_option_write (target *t, uint32_t address, uint32_t value) +static bool stm32lx_option_write(target *t, uint32_t address, uint32_t value) { - ADIv5_AP_t* ap = adiv5_target_ap(t); - const uint32_t nvm = stm32lx_nvm_phys (t); + ADIv5_AP_t* ap = adiv5_target_ap(t); + const uint32_t nvm = stm32lx_nvm_phys(t); - /* Erase and program option in one go. */ - adiv5_ap_mem_write (ap, STM32Lx_NVM_PECR(nvm), STM32Lx_NVM_PECR_FIX); - adiv5_ap_mem_write (ap, address, value); + /* Erase and program option in one go. */ + adiv5_ap_mem_write(ap, STM32Lx_NVM_PECR(nvm), STM32Lx_NVM_PECR_FIX); + adiv5_ap_mem_write(ap, address, value); - uint32_t sr; - do { - sr = adiv5_ap_mem_read (ap, STM32Lx_NVM_SR(nvm)); - } while (sr & STM32Lx_NVM_SR_BSY); + uint32_t sr; + do { + sr = adiv5_ap_mem_read(ap, STM32Lx_NVM_SR(nvm)); + } while (sr & STM32Lx_NVM_SR_BSY); - return !(sr & STM32Lx_NVM_SR_ERR_M); + return !(sr & STM32Lx_NVM_SR_ERR_M); } @@ -822,255 +840,231 @@ static bool stm32lx_option_write (target *t, uint32_t address, uint32_t value) complete. The return value is true if the write succeeded. FWIW, byte writing isn't supported because the adiv5 layer doesn't support byte-level operations. */ -static bool stm32lx_eeprom_write (target *t, uint32_t address, - size_t cb, uint32_t value) +static bool stm32lx_eeprom_write(target *t, uint32_t address, + size_t cb, uint32_t value) { - ADIv5_AP_t* ap = adiv5_target_ap(t); - const uint32_t nvm = stm32lx_nvm_phys (t); - const bool is_stm32l1 = stm32lx_is_stm32l1 (t); - - /* Clear errors. */ - adiv5_ap_mem_write (ap, STM32Lx_NVM_SR (nvm), STM32Lx_NVM_SR_ERR_M); - - /* Erase and program option in one go. */ - adiv5_ap_mem_write (ap, STM32Lx_NVM_PECR(nvm), - (is_stm32l1 ? 0 : STM32Lx_NVM_PECR_DATA) - | STM32Lx_NVM_PECR_FIX); - if (cb == 4) - adiv5_ap_mem_write (ap, address, value); - else if (cb == 2) - adiv5_ap_mem_write_halfword (ap, address, value); - else - return false; - - uint32_t sr; - do { - sr = adiv5_ap_mem_read (ap, STM32Lx_NVM_SR(nvm)); - } while (sr & STM32Lx_NVM_SR_BSY); - - return !(sr & STM32Lx_NVM_SR_ERR_M); + ADIv5_AP_t* ap = adiv5_target_ap(t); + const uint32_t nvm = stm32lx_nvm_phys(t); + const bool is_stm32l1 = stm32lx_is_stm32l1(t); + + /* Clear errors. */ + adiv5_ap_mem_write(ap, STM32Lx_NVM_SR(nvm), STM32Lx_NVM_SR_ERR_M); + + /* Erase and program option in one go. */ + adiv5_ap_mem_write(ap, STM32Lx_NVM_PECR(nvm), + (is_stm32l1 ? 0 : STM32Lx_NVM_PECR_DATA) + | STM32Lx_NVM_PECR_FIX); + if (cb == 4) + adiv5_ap_mem_write(ap, address, value); + else if (cb == 2) + adiv5_ap_mem_write_halfword(ap, address, value); + else if (cb == 1) + adiv5_ap_mem_write_byte(ap, address, value); + else + return false; + + uint32_t sr; + do { + sr = adiv5_ap_mem_read(ap, STM32Lx_NVM_SR(nvm)); + } while (sr & STM32Lx_NVM_SR_BSY); + + return !(sr & STM32Lx_NVM_SR_ERR_M); } -static bool stm32lx_cmd_stubs (target* t, - int argc, char** argv) +static bool stm32lx_cmd_stubs(target* t, + int argc, char** argv) { - if (argc == 1) { - gdb_out ("usage: mon stubs [enable/disable]\n"); - } - else if (argc == 2) { - size_t cb = strlen (argv[1]); - if (!strncasecmp (argv[1], "enable", cb)) - inhibit_stubs = 0; - if (!strncasecmp (argv[1], "disable", cb)) - inhibit_stubs = 1; - } - gdb_outf ("stubs: %sabled\n", inhibit_stubs ? "dis" : "en"); - - return true; + (void) t; + if (argc == 1) { + gdb_out("usage: mon stubs [enable/disable]\n"); + } + else if (argc == 2) { + size_t cb = strlen(argv[1]); + if (!strncasecmp(argv[1], "enable", cb)) + inhibit_stubs = 0; + if (!strncasecmp(argv[1], "disable", cb)) + inhibit_stubs = 1; + } + gdb_outf("stubs: %sabled\n", inhibit_stubs ? "dis" : "en"); + + return true; } -#if 0 -static bool stm32l0_cmd_erase_mass (target* t, int argc , char** argv) +static bool stm32lx_cmd_option(target* t, int argc, char** argv) { - ADIv5_AP_t* ap = adiv5_target_ap (t); - - stm32lx_nvm_opt_unlock (ap); - - stm32l0_option_write (t, 0x1ff80000, 0xffff0000); - adiv5_ap_mem_write (ap, STM32L0_NVM_PECR, STM32L0_NVM_PECR_OBL_LAUNCH); - stm32l0_option_write (t, 0x1ff80000, 0xff5500aa); - adiv5_ap_mem_write (ap, STM32L0_NVM_PECR, STM32L0_NVM_PECR_OBL_LAUNCH); - - uint32_t sr; - do { - sr = adiv5_ap_mem_read (ap, STM32L0_NVM_SR); - } while (sr & STM32L0_NVM_SR_BSY); - - stm32l0_nvm_lock (ap); - return true; -} -#endif - -#if 0 -static bool stm32l0_cmd_reset (target* t, int argc, char** argv) -{ - gdb_out ("Resetting target\n"); - target_reset (t); - - return true; -} -#endif - -static bool stm32lx_cmd_option (target* t, int argc, char** argv) -{ - ADIv5_AP_t* ap = adiv5_target_ap (t); - const uint32_t nvm = stm32lx_nvm_phys (t); - const size_t opt_size = stm32lx_nvm_option_size (t); - - if (!stm32lx_nvm_opt_unlock (ap, nvm)) { - gdb_out ("unable to unlock NVM option bytes\n"); - return true; - } - - size_t cb = strlen (argv[1]); - - if (argc == 2 && !strncasecmp (argv[1], "obl_launch", cb)) { - adiv5_ap_mem_write (ap, STM32Lx_NVM_PECR(nvm), STM32Lx_NVM_PECR_OBL_LAUNCH); - } - else if (argc == 4 && !strncasecmp (argv[1], "raw", cb)) { - uint32_t addr = strtoul (argv[2], NULL, 0); - uint32_t val = strtoul (argv[3], NULL, 0); - gdb_outf ("raw %08x <- %08x\n", addr, val); - if ( addr < STM32Lx_NVM_OPT_PHYS - || addr >= STM32Lx_NVM_OPT_PHYS + opt_size - || (addr & 3)) - goto usage; - if (!stm32lx_option_write (t, addr, val)) - gdb_out ("option write failed\n"); - } - else if (argc == 4 && !strncasecmp (argv[1], "write", cb)) { - uint32_t addr = strtoul (argv[2], NULL, 0); - uint32_t val = strtoul (argv[3], NULL, 0); - val = (val & 0xffff) | ((~val & 0xffff) << 16); - gdb_outf ("write %08x <- %08x\n", addr, val); - if ( addr < STM32Lx_NVM_OPT_PHYS - || addr >= STM32Lx_NVM_OPT_PHYS + opt_size - || (addr & 3)) - goto usage; - if (!stm32lx_option_write (t, addr, val)) - gdb_out ("option write failed\n"); - } - else if (argc == 2 && !strncasecmp (argv[1], "show", cb)) - ; - else - goto usage; - - /* Report the current option values */ - for (int i = 0; i < opt_size; i += sizeof (uint32_t)) { - uint32_t addr = STM32Lx_NVM_OPT_PHYS + i; - uint32_t val = adiv5_ap_mem_read (ap, addr); - gdb_outf ("0x%08x: 0x%04x 0x%04x %s\n", - addr, val & 0xffff, (val >> 16) & 0xffff, - ((val & 0xffff) == ((~val >> 16) & 0xffff)) ? "OK" : "ERR"); - } - - if (stm32lx_is_stm32l1 (t)) { - uint32_t optr = adiv5_ap_mem_read (ap, STM32Lx_NVM_OPTR(nvm)); - uint8_t rdprot = (optr >> STM32L1_NVM_OPTR_RDPROT_S) - & STM32L1_NVM_OPTR_RDPROT_M; - if (rdprot == STM32L1_NVM_OPTR_RDPROT_0) - rdprot = 0; - else if (rdprot == STM32L1_NVM_OPTR_RDPROT_2) - rdprot = 2; - else - rdprot = 1; - gdb_outf ("OPTR: 0x%08x, RDPRT %d, SPRMD %d, " - "BOR %d, WDG_SW %d, nRST_STP %d, nRST_STBY %d, nBFB2 %d\n", - optr, rdprot, - (optr & STM32L1_NVM_OPTR_SPRMOD) ? 1 : 0, - (optr >> STM32L1_NVM_OPTR_BOR_LEV_S) & STM32L1_NVM_OPTR_BOR_LEV_M, - (optr & STM32L1_NVM_OPTR_WDG_SW) ? 1 : 0, - (optr & STM32L1_NVM_OPTR_nRST_STOP) ? 1 : 0, - (optr & STM32L1_NVM_OPTR_nRST_STDBY) ? 1 : 0, - (optr & STM32L1_NVM_OPTR_nBFB2) ? 1 : 0); - } - else { - uint32_t optr = adiv5_ap_mem_read (ap, STM32Lx_NVM_OPTR(nvm)); - uint8_t rdprot = (optr >> STM32L0_NVM_OPTR_RDPROT_S) - & STM32L0_NVM_OPTR_RDPROT_M; - if (rdprot == STM32L0_NVM_OPTR_RDPROT_0) - rdprot = 0; - else if (rdprot == STM32L0_NVM_OPTR_RDPROT_2) - rdprot = 2; - else - rdprot = 1; - gdb_outf ("OPTR: 0x%08x, RDPROT %d, WPRMOD %d, WDG_SW %d, BOOT1 %d\n", - optr, rdprot, - (optr & STM32L0_NVM_OPTR_WPRMOD) ? 1 : 0, - (optr & STM32L0_NVM_OPTR_WDG_SW) ? 1 : 0, - (optr & STM32L0_NVM_OPTR_BOOT1) ? 1 : 0); - } - - goto done; - - usage: - gdb_out ("usage: monitor option [ARGS]\n"); - gdb_out (" show - Show options in NVM and as loaded\n"); - gdb_out (" obl_launch - Reload options from NVM\n"); - gdb_out (" write - Set option half-word; " - "complement computed\n"); - gdb_out (" raw - Set option word\n"); - gdb_outf ("The value of must be word aligned and from 0x%08x " - "to +0x%x\n", - STM32Lx_NVM_OPT_PHYS, - STM32Lx_NVM_OPT_PHYS + opt_size - sizeof (uint32_t)); - - done: - stm32lx_nvm_lock (ap, nvm); - return true; + ADIv5_AP_t* ap = adiv5_target_ap(t); + const uint32_t nvm = stm32lx_nvm_phys(t); + const size_t opt_size = stm32lx_nvm_option_size(t); + + if (!stm32lx_nvm_opt_unlock(ap, nvm)) { + gdb_out("unable to unlock NVM option bytes\n"); + return true; + } + + size_t cb = strlen(argv[1]); + + if (argc == 2 && !strncasecmp(argv[1], "obl_launch", cb)) { + adiv5_ap_mem_write(ap, STM32Lx_NVM_PECR(nvm), + STM32Lx_NVM_PECR_OBL_LAUNCH); + } + else if (argc == 4 && !strncasecmp(argv[1], "raw", cb)) { + uint32_t addr = strtoul(argv[2], NULL, 0); + uint32_t val = strtoul(argv[3], NULL, 0); + gdb_outf("raw %08x <- %08x\n", addr, val); + if ( addr < STM32Lx_NVM_OPT_PHYS + || addr >= STM32Lx_NVM_OPT_PHYS + opt_size + || (addr & 3)) + goto usage; + if (!stm32lx_option_write(t, addr, val)) + gdb_out("option write failed\n"); + } + else if (argc == 4 && !strncasecmp(argv[1], "write", cb)) { + uint32_t addr = strtoul(argv[2], NULL, 0); + uint32_t val = strtoul(argv[3], NULL, 0); + val = (val & 0xffff) | ((~val & 0xffff) << 16); + gdb_outf("write %08x <- %08x\n", addr, val); + if ( addr < STM32Lx_NVM_OPT_PHYS + || addr >= STM32Lx_NVM_OPT_PHYS + opt_size + || (addr & 3)) + goto usage; + if (!stm32lx_option_write(t, addr, val)) + gdb_out("option write failed\n"); + } + else if (argc == 2 && !strncasecmp(argv[1], "show", cb)) + ; + else + goto usage; + + /* Report the current option values */ + for(int i = 0; i < opt_size; i += sizeof(uint32_t)) { + uint32_t addr = STM32Lx_NVM_OPT_PHYS + i; + uint32_t val = adiv5_ap_mem_read(ap, addr); + gdb_outf("0x%08x: 0x%04x 0x%04x %s\n", + addr, val & 0xffff, (val >> 16) & 0xffff, + ((val & 0xffff) == ((~val >> 16) & 0xffff)) + ? "OK" : "ERR"); + } + + if (stm32lx_is_stm32l1(t)) { + uint32_t optr = adiv5_ap_mem_read(ap, STM32Lx_NVM_OPTR(nvm)); + uint8_t rdprot = (optr >> STM32L1_NVM_OPTR_RDPROT_S) + & STM32L1_NVM_OPTR_RDPROT_M; + if (rdprot == STM32L1_NVM_OPTR_RDPROT_0) + rdprot = 0; + else if (rdprot == STM32L1_NVM_OPTR_RDPROT_2) + rdprot = 2; + else + rdprot = 1; + gdb_outf("OPTR: 0x%08x, RDPRT %d, SPRMD %d, " + "BOR %d, WDG_SW %d, nRST_STP %d, nRST_STBY %d, " + "nBFB2 %d\n", + optr, rdprot, + (optr & STM32L1_NVM_OPTR_SPRMOD) ? 1 : 0, + (optr >> STM32L1_NVM_OPTR_BOR_LEV_S) + & STM32L1_NVM_OPTR_BOR_LEV_M, + (optr & STM32L1_NVM_OPTR_WDG_SW) ? 1 : 0, + (optr & STM32L1_NVM_OPTR_nRST_STOP) ? 1 : 0, + (optr & STM32L1_NVM_OPTR_nRST_STDBY) ? 1 : 0, + (optr & STM32L1_NVM_OPTR_nBFB2) ? 1 : 0); + } + else { + uint32_t optr = adiv5_ap_mem_read(ap, STM32Lx_NVM_OPTR(nvm)); + uint8_t rdprot = (optr >> STM32L0_NVM_OPTR_RDPROT_S) + & STM32L0_NVM_OPTR_RDPROT_M; + if (rdprot == STM32L0_NVM_OPTR_RDPROT_0) + rdprot = 0; + else if (rdprot == STM32L0_NVM_OPTR_RDPROT_2) + rdprot = 2; + else + rdprot = 1; + gdb_outf("OPTR: 0x%08x, RDPROT %d, WPRMOD %d, WDG_SW %d, " + "BOOT1 %d\n", + optr, rdprot, + (optr & STM32L0_NVM_OPTR_WPRMOD) ? 1 : 0, + (optr & STM32L0_NVM_OPTR_WDG_SW) ? 1 : 0, + (optr & STM32L0_NVM_OPTR_BOOT1) ? 1 : 0); + } + + goto done; + +usage: + gdb_out("usage: monitor option [ARGS]\n"); + gdb_out(" show - Show options in NVM and as" + " loaded\n"); + gdb_out(" obl_launch - Reload options from NVM\n"); + gdb_out(" write - Set option half-word; " + "complement computed\n"); + gdb_out(" raw - Set option word\n"); + gdb_outf("The value of must be word aligned and from 0x%08x " + "to +0x%x\n", + STM32Lx_NVM_OPT_PHYS, + STM32Lx_NVM_OPT_PHYS + opt_size - sizeof(uint32_t)); + +done: + stm32lx_nvm_lock(ap, nvm); + return true; } -static bool stm32lx_cmd_eeprom (target* t, int argc, char** argv) +static bool stm32lx_cmd_eeprom(target* t, int argc, char** argv) { - ADIv5_AP_t* ap = adiv5_target_ap (t); - const uint32_t nvm = stm32lx_nvm_phys (t); - - if (!stm32lx_nvm_prog_data_unlock (ap, nvm)) { - gdb_out ("unable to unlock EEPROM\n"); - return true; - } - - size_t cb = strlen (argv[1]); - - if (argc == 4) { - uint32_t addr = strtoul (argv[2], NULL, 0); - uint32_t val = strtoul (argv[3], NULL, 0); - - if ( addr < STM32Lx_NVM_EEPROM_PHYS - || addr >= STM32Lx_NVM_EEPROM_PHYS + stm32lx_nvm_eeprom_size (t)) - goto usage; - -#if 0 - if (!strncasecmp (argv[1], "byte", cb)) { - gdb_outf ("write byte 0x%08x <- 0x%08x\n", addr, val); - if (!stm32l0_eeprom_write (t, addr, 1, val)) - gdb_out ("eeprom write failed\n"); - } else -#endif - if (!strncasecmp (argv[1], "halfword", cb)) { - val &= 0xffff; - gdb_outf ("write halfword 0x%08x <- 0x%04x\n", addr, val); - if (addr & 1) - goto usage; - if (!stm32lx_eeprom_write (t, addr, 2, val)) - gdb_out ("eeprom write failed\n"); - } else if (!strncasecmp (argv[1], "word", cb)) { - gdb_outf ("write word 0x%08x <- 0x%08x\n", addr, val); - if (addr & 3) - goto usage; - if (!stm32lx_eeprom_write (t, addr, 4, val)) - gdb_out ("eeprom write failed\n"); - } - else - goto usage; - } - else - goto usage; - - goto done; - - usage: - gdb_out ("usage: monitor eeprom [ARGS]\n"); -// gdb_out (" byte - Write a byte\n"); - gdb_out (" halfword - Write a half-word\n"); - gdb_out (" word - Write a word\n"); - gdb_outf ("The value of must in the interval [0x%08x, 0x%x)\n", - STM32Lx_NVM_EEPROM_PHYS, - STM32Lx_NVM_EEPROM_PHYS - + stm32lx_nvm_eeprom_size (t)); - - done: - stm32lx_nvm_lock (ap, nvm); - return true; + ADIv5_AP_t* ap = adiv5_target_ap(t); + const uint32_t nvm = stm32lx_nvm_phys(t); + + if (!stm32lx_nvm_prog_data_unlock(ap, nvm)) { + gdb_out("unable to unlock EEPROM\n"); + return true; + } + + size_t cb = strlen(argv[1]); + + if (argc == 4) { + uint32_t addr = strtoul(argv[2], NULL, 0); + uint32_t val = strtoul(argv[3], NULL, 0); + + if ( addr < STM32Lx_NVM_EEPROM_PHYS + || addr >= STM32Lx_NVM_EEPROM_PHYS + + stm32lx_nvm_eeprom_size(t)) + goto usage; + + if (!strncasecmp(argv[1], "byte", cb)) { + gdb_outf("write byte 0x%08x <- 0x%08x\n", addr, val); + if (!stm32lx_eeprom_write(t, addr, 1, val)) + gdb_out("eeprom write failed\n"); + } else if (!strncasecmp(argv[1], "halfword", cb)) { + val &= 0xffff; + gdb_outf("write halfword 0x%08x <- 0x%04x\n", + addr, val); + if (addr & 1) + goto usage; + if (!stm32lx_eeprom_write(t, addr, 2, val)) + gdb_out("eeprom write failed\n"); + } else if (!strncasecmp(argv[1], "word", cb)) { + gdb_outf("write word 0x%08x <- 0x%08x\n", addr, val); + if (addr & 3) + goto usage; + if (!stm32lx_eeprom_write(t, addr, 4, val)) + gdb_out("eeprom write failed\n"); + } + else + goto usage; + } + else + goto usage; + + goto done; + +usage: + gdb_out("usage: monitor eeprom [ARGS]\n"); + gdb_out(" byte - Write a byte\n"); + gdb_out(" halfword - Write a half-word\n"); + gdb_out(" word - Write a word\n"); + gdb_outf("The value of must in the interval [0x%08x, 0x%x)\n", + STM32Lx_NVM_EEPROM_PHYS, + STM32Lx_NVM_EEPROM_PHYS + + stm32lx_nvm_eeprom_size(t)); + +done: + stm32lx_nvm_lock(ap, nvm); + return true; } -- cgit v1.2.3 From 7c1c19881f5048abf353744f55c07e757c93c112 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Wed, 11 Mar 2015 05:45:43 -0700 Subject: Reassert DCD after DTR is written. Fixes #41. --- src/platforms/common/cdcacm.c | 33 ++++++++++++++++++++------------- 1 file changed, 20 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/platforms/common/cdcacm.c b/src/platforms/common/cdcacm.c index 8e95a9a..d8c376e 100644 --- a/src/platforms/common/cdcacm.c +++ b/src/platforms/common/cdcacm.c @@ -49,6 +49,7 @@ usbd_device * usbdev; static int configured; static int cdcacm_gdb_dtr = 1; +static void cdcacm_set_modem_state(usbd_device *dev, int iface, bool dsr, bool dcd); static const struct usb_device_descriptor dev = { .bLength = USB_DT_DEVICE_SIZE, @@ -430,6 +431,7 @@ static int cdcacm_control_request(usbd_device *dev, return 1; cdcacm_gdb_dtr = req->wValue & 1; + cdcacm_set_modem_state(dev, 0, true, true); return 1; case USB_CDC_REQ_SET_LINE_CODING: @@ -476,6 +478,23 @@ int cdcacm_get_dtr(void) return cdcacm_gdb_dtr; } +static void cdcacm_set_modem_state(usbd_device *dev, int iface, bool dsr, bool dcd) +{ + char buf[10]; + struct usb_cdc_notification *notif = (void*)buf; + /* We echo signals back to host as notification */ + notif->bmRequestType = 0xA1; + notif->bNotification = USB_CDC_NOTIFY_SERIAL_STATE; + notif->wValue = 0; + notif->wIndex = iface; + notif->wLength = 2; + buf[8] = (dsr ? 2 : 0) | (dcd ? 1 : 0); + buf[9] = 0; + usbd_ep_write_packet(dev, 0x82, buf, 10); + notif->wIndex = 2; + usbd_ep_write_packet(dev, 0x84, buf, 10); +} + static void cdcacm_set_config(usbd_device *dev, uint16_t wValue) { configured = wValue; @@ -513,19 +532,7 @@ static void cdcacm_set_config(usbd_device *dev, uint16_t wValue) /* Notify the host that DCD is asserted. * Allows the use of /dev/tty* devices on *BSD/MacOS */ - char buf[10]; - struct usb_cdc_notification *notif = (void*)buf; - /* We echo signals back to host as notification */ - notif->bmRequestType = 0xA1; - notif->bNotification = USB_CDC_NOTIFY_SERIAL_STATE; - notif->wValue = 0; - notif->wIndex = 0; - notif->wLength = 2; - buf[8] = 3; /* DCD | DSR */ - buf[9] = 0; - usbd_ep_write_packet(dev, 0x82, buf, 10); - notif->wIndex = 2; - usbd_ep_write_packet(dev, 0x84, buf, 10); + cdcacm_set_modem_state(dev, 0, true, true); } /* We need a special large control buffer for this device: */ -- cgit v1.2.3 From 4baa8aba4f03e9690caece538e0887ac09f1eafc Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Wed, 11 Mar 2015 20:13:38 -0700 Subject: cdcacm: Fix DCD for second ACM interface. --- src/platforms/common/cdcacm.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/platforms/common/cdcacm.c b/src/platforms/common/cdcacm.c index d8c376e..ab8294e 100644 --- a/src/platforms/common/cdcacm.c +++ b/src/platforms/common/cdcacm.c @@ -426,12 +426,12 @@ static int cdcacm_control_request(usbd_device *dev, switch(req->bRequest) { case USB_CDC_REQ_SET_CONTROL_LINE_STATE: + cdcacm_set_modem_state(dev, req->wIndex, true, true); /* Ignore if not for GDB interface */ if(req->wIndex != 0) return 1; cdcacm_gdb_dtr = req->wValue & 1; - cdcacm_set_modem_state(dev, 0, true, true); return 1; case USB_CDC_REQ_SET_LINE_CODING: @@ -490,9 +490,7 @@ static void cdcacm_set_modem_state(usbd_device *dev, int iface, bool dsr, bool d notif->wLength = 2; buf[8] = (dsr ? 2 : 0) | (dcd ? 1 : 0); buf[9] = 0; - usbd_ep_write_packet(dev, 0x82, buf, 10); - notif->wIndex = 2; - usbd_ep_write_packet(dev, 0x84, buf, 10); + usbd_ep_write_packet(dev, 0x82 + iface, buf, 10); } static void cdcacm_set_config(usbd_device *dev, uint16_t wValue) @@ -533,6 +531,7 @@ static void cdcacm_set_config(usbd_device *dev, uint16_t wValue) * Allows the use of /dev/tty* devices on *BSD/MacOS */ cdcacm_set_modem_state(dev, 0, true, true); + cdcacm_set_modem_state(dev, 2, true, true); } /* We need a special large control buffer for this device: */ -- cgit v1.2.3 From 3d28c1418c11cb62e6c4c2f483a0bb7f308255a4 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Wed, 11 Mar 2015 20:31:01 -0700 Subject: Cleaned up printf/scanf for C99 integer types. --- src/gdb_main.c | 16 ++++++++-------- src/include/general.h | 1 + src/platforms/libftdi/Makefile.inc | 2 +- 3 files changed, 10 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/gdb_main.c b/src/gdb_main.c index 17ad9a5..0c3dd77 100644 --- a/src/gdb_main.c +++ b/src/gdb_main.c @@ -85,8 +85,8 @@ gdb_main(void) case 'm': { /* 'm addr,len': Read len bytes from addr */ uint32_t addr, len; ERROR_IF_NO_TARGET(); - sscanf(pbuf, "m%08lx,%08lx", &addr, &len); - DEBUG("m packet: addr = %08lX, len = %08lX\n", addr, len); + sscanf(pbuf, "m%" SCNx32 ",%" SCNx32, &addr, &len); + DEBUG("m packet: addr = %" PRIx32 ", len = %" PRIx32 "\n", addr, len); uint8_t mem[len]; if(((addr & 3) == 0) && ((len & 3) == 0)) target_mem_read_words(cur_target, (void*)mem, addr, len); @@ -112,8 +112,8 @@ gdb_main(void) uint32_t addr, len; int hex; ERROR_IF_NO_TARGET(); - sscanf(pbuf, "M%08lx,%08lx:%n", &addr, &len, &hex); - DEBUG("M packet: addr = %08lX, len = %08lX\n", addr, len); + sscanf(pbuf, "M%" SCNx32 ",%" SCNx32 ":%n", &addr, &len, &hex); + DEBUG("M packet: addr = %" PRIx32 ", len = %" PRIx32 "\n", addr, len); uint8_t mem[len]; unhexify(mem, pbuf + hex, len); if(((addr & 3) == 0) && ((len & 3) == 0)) @@ -242,8 +242,8 @@ gdb_main(void) uint32_t addr, len; int bin; ERROR_IF_NO_TARGET(); - sscanf(pbuf, "X%08lx,%08lx:%n", &addr, &len, &bin); - DEBUG("X packet: addr = %08lX, len = %08lX\n", addr, len); + sscanf(pbuf, "X%" SCNx32 ",%" SCNx32 ":%n", &addr, &len, &bin); + DEBUG("X packet: addr = %" PRIx32 ", len = %" PRIx32 "\n", addr, len); if(((addr & 3) == 0) && ((len & 3) == 0)) target_mem_write_words(cur_target, addr, (void*)pbuf+bin, len); else @@ -352,7 +352,7 @@ handle_q_packet(char *packet, int len) return; } handle_q_string_reply(cur_target->tdesc, packet + 31); - } else if (sscanf(packet, "qCRC:%08lx,%08lx", &addr, &alen) == 2) { + } else if (sscanf(packet, "qCRC:%" PRIx32 ",%" PRIx32, &addr, &alen) == 2) { if(!cur_target) { gdb_putpacketz("E01"); return; @@ -454,7 +454,7 @@ handle_z_packet(char *packet, int plen) * with real sscanf() though... */ //sscanf(packet, "%*[zZ]%hhd,%08lX,%hhd", &type, &addr, &len); type = packet[1] - '0'; - sscanf(packet + 2, ",%08lx,%d", &addr, &len); + sscanf(packet + 2, ",%" PRIx32 ",%d", &addr, &len); switch(type) { case 1: /* Hardware breakpoint */ if(!cur_target->set_hw_bp) { /* Not supported */ diff --git a/src/include/general.h b/src/include/general.h index b4e9aeb..2cb4bd9 100644 --- a/src/include/general.h +++ b/src/include/general.h @@ -28,6 +28,7 @@ #include #include #include +#include #include "platform.h" #include "platform_support.h" diff --git a/src/platforms/libftdi/Makefile.inc b/src/platforms/libftdi/Makefile.inc index f7cc9c5..fa6292b 100644 --- a/src/platforms/libftdi/Makefile.inc +++ b/src/platforms/libftdi/Makefile.inc @@ -1,2 +1,2 @@ -CFLAGS += -DLIBFTDI -Wno-format +CFLAGS += -DLIBFTDI LDFLAGS += -lftdi -lusb -- cgit v1.2.3 From 1196b03d66c9187b12f6cc6502589e88df11c5aa Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Wed, 11 Mar 2015 20:40:48 -0700 Subject: stm32l0: Fix pointer/integer casting warnings. --- src/include/stm32lx-nvm.h | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) (limited to 'src') diff --git a/src/include/stm32lx-nvm.h b/src/include/stm32lx-nvm.h index 190a8ab..2e9d8c5 100644 --- a/src/include/stm32lx-nvm.h +++ b/src/include/stm32lx-nvm.h @@ -159,25 +159,12 @@ namespace { typedef uint32_t stm32lx_stub_pointer_t; -struct stm32lx_nvm { - volatile uint32_t acr; - volatile uint32_t pecr; - volatile uint32_t pdkeyr; - volatile uint32_t pekeyr; - volatile uint32_t prgkeyr; - volatile uint32_t optkeyr; - volatile uint32_t sr; - volatile uint32_t optr; /* or obr */ - volatile uint32_t wrprot; /* or wprot1 */ -}; - -#define STM32Lx_NVM(p) (*(struct stm32lx_nvm*) (p)) -#define STM32Lx_NVM_PECR(p) ((uint32_t) &STM32Lx_NVM(p).pecr) -#define STM32Lx_NVM_PEKEYR(p) ((uint32_t) &STM32Lx_NVM(p).pekeyr) -#define STM32Lx_NVM_PRGKEYR(p) ((uint32_t) &STM32Lx_NVM(p).prgkeyr) -#define STM32Lx_NVM_OPTKEYR(p) ((uint32_t) &STM32Lx_NVM(p).optkeyr) -#define STM32Lx_NVM_SR(p) ((uint32_t) &STM32Lx_NVM(p).sr) -#define STM32Lx_NVM_OPTR(p) ((uint32_t) &STM32Lx_NVM(p).optr) +#define STM32Lx_NVM_PECR(p) ((p) + 0x04) +#define STM32Lx_NVM_PEKEYR(p) ((p) + 0x0C) +#define STM32Lx_NVM_PRGKEYR(p) ((p) + 0x10) +#define STM32Lx_NVM_OPTKEYR(p) ((p) + 0x14) +#define STM32Lx_NVM_SR(p) ((p) + 0x18) +#define STM32Lx_NVM_OPTR(p) ((p) + 0x1C) #endif -- cgit v1.2.3 From f52a51403f4b9e5d0264cc355bf2414634bb5500 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Wed, 11 Mar 2015 20:46:26 -0700 Subject: stm32l0: cleanup includes. --- src/stm32l0.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'src') diff --git a/src/stm32l0.c b/src/stm32l0.c index 954a277..0de028f 100644 --- a/src/stm32l0.c +++ b/src/stm32l0.c @@ -114,14 +114,11 @@ #define CONFIG_STM32L1 /* Include support for STM32L1 */ -#include -#include -#include - #include "general.h" #include "adiv5.h" #include "target.h" #include "command.h" +#include "gdb_packet.h" #include "stm32lx-nvm.h" -- cgit v1.2.3 From f5c856af3b3b0155050e793f50c29965d2c8326d Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Fri, 13 Mar 2015 20:35:39 -0700 Subject: Fix pointer sign warnings and remove -Wno-pointer-sign. --- src/Makefile | 2 +- src/cortexm.c | 3 ++- src/gdb_main.c | 6 +++--- src/gdb_packet.c | 7 +++---- src/hex_utils.c | 20 +++++++++++--------- src/include/gdb_packet.h | 6 +++--- src/include/hex_utils.h | 5 ++--- src/jtag_scan.c | 2 +- src/platforms/libftdi/jtagtap.c | 2 +- src/platforms/libftdi/swdptap.c | 13 +++---------- 10 files changed, 30 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 7a1f141..7ea7865 100644 --- a/src/Makefile +++ b/src/Makefile @@ -9,7 +9,7 @@ endif BUILDDATE := `date +"%Y%m%d"` -CFLAGS += -Wall -Wextra -Wno-pointer-sign -Wno-char-subscripts\ +CFLAGS += -Wall -Wextra -Wno-char-subscripts\ -Wno-sign-compare \ -O2 -std=gnu99 -g3 -DBUILDDATE=\"$(BUILDDATE)\"\ -I. -Iinclude -Iplatforms/common -I$(PLATFORM_DIR) \ diff --git a/src/cortexm.c b/src/cortexm.c index 71d0c6c..b3b657f 100644 --- a/src/cortexm.c +++ b/src/cortexm.c @@ -853,7 +853,8 @@ static int cortexm_hostio_request(target *t) uint32_t pflag = flags[params[1] >> 1]; char filename[4]; - target_mem_read_bytes(t, filename, params[0], sizeof(filename)); + target_mem_read_bytes(t, (uint8_t *)filename, + params[0], sizeof(filename)); /* handle requests for console i/o */ if (!strcmp(filename, ":tt")) { if (pflag == FILEIO_O_RDONLY) diff --git a/src/gdb_main.c b/src/gdb_main.c index 0c3dd77..ab4fc8a 100644 --- a/src/gdb_main.c +++ b/src/gdb_main.c @@ -41,7 +41,7 @@ #define ERROR_IF_NO_TARGET() \ if(!cur_target) { gdb_putpacketz("EFF"); break; } -static unsigned char pbuf[BUF_SIZE]; +static char pbuf[BUF_SIZE]; static target *cur_target; static target *last_target; @@ -287,7 +287,7 @@ handle_q_string_reply(const char *str, const char *param) return; } if (addr < strlen (str)) { - uint8_t reply[len+2]; + char reply[len+2]; reply[0] = 'm'; strncpy (reply + 1, &str[addr], len); if(len > strlen(&str[addr])) @@ -305,7 +305,7 @@ handle_q_packet(char *packet, int len) uint32_t addr, alen; if(!strncmp(packet, "qRcmd,", 6)) { - unsigned char *data; + char *data; int datalen; /* calculate size and allocate buffer for command */ diff --git a/src/gdb_packet.c b/src/gdb_packet.c index 4dc934f..fb3335e 100644 --- a/src/gdb_packet.c +++ b/src/gdb_packet.c @@ -29,8 +29,7 @@ #include -int -gdb_getpacket(unsigned char *packet, int size) +int gdb_getpacket(char *packet, int size) { unsigned char c; unsigned char csum; @@ -89,7 +88,7 @@ gdb_getpacket(unsigned char *packet, int size) return i; } -void gdb_putpacket(unsigned char *packet, int size) +void gdb_putpacket(const char *packet, int size) { int i; unsigned char csum; @@ -130,7 +129,7 @@ void gdb_putpacket(unsigned char *packet, int size) } while((gdb_if_getchar_to(2000) != '+') && (tries++ < 3)); } -void gdb_putpacket_f(const unsigned char *fmt, ...) +void gdb_putpacket_f(const char *fmt, ...) { va_list ap; char *buf; diff --git a/src/hex_utils.c b/src/hex_utils.c index 45382ff..e18df58 100644 --- a/src/hex_utils.c +++ b/src/hex_utils.c @@ -24,15 +24,16 @@ #include "general.h" #include "hex_utils.h" -static char hexdigits[] = "0123456789abcdef"; +static const char hexdigits[] = "0123456789abcdef"; -char * hexify(char *hex, const unsigned char *buf, int size) +char * hexify(char *hex, const void *buf, size_t size) { char *tmp = hex; + const uint8_t *b = buf; - while(size--) { - *tmp++ = hexdigits[*buf >> 4]; - *tmp++ = hexdigits[*buf++ & 0xF]; + while (size--) { + *tmp++ = hexdigits[*b >> 4]; + *tmp++ = hexdigits[*b++ & 0xF]; } *tmp++ = 0; @@ -49,11 +50,12 @@ static uint8_t unhex_digit(char hex) return tmp; } -char * unhexify(unsigned char *buf, const char *hex, int size) +char * unhexify(void *buf, const char *hex, size_t size) { - while(size--) { - *buf = unhex_digit(*hex++) << 4; - *buf++ |= unhex_digit(*hex++); + uint8_t *b = buf; + while (size--) { + *b = unhex_digit(*hex++) << 4; + *b++ |= unhex_digit(*hex++); } return buf; } diff --git a/src/include/gdb_packet.h b/src/include/gdb_packet.h index 222b86d..aa1a654 100644 --- a/src/include/gdb_packet.h +++ b/src/include/gdb_packet.h @@ -21,10 +21,10 @@ #ifndef __GDB_PACKET_H #define __GDB_PACKET_H -int gdb_getpacket(unsigned char *packet, int size); -void gdb_putpacket(unsigned char *packet, int size); +int gdb_getpacket(char *packet, int size); +void gdb_putpacket(const char *packet, int size); #define gdb_putpacketz(packet) gdb_putpacket((packet), strlen(packet)) -void gdb_putpacket_f(const unsigned char *packet, ...); +void gdb_putpacket_f(const char *packet, ...); void gdb_out(const char *buf); void gdb_outf(const char *fmt, ...); diff --git a/src/include/hex_utils.h b/src/include/hex_utils.h index 3aa210b..8a0d092 100644 --- a/src/include/hex_utils.h +++ b/src/include/hex_utils.h @@ -21,9 +21,8 @@ #ifndef __HEX_UTILS_H #define __HEX_UTILS_H -char * hexify(char *hex, const unsigned char *buf, int size); - -char * unhexify(unsigned char *buf, const char *hex, int size); +char * hexify(char *hex, const void *buf, size_t size); +char * unhexify(void *buf, const char *hex, size_t size); #endif diff --git a/src/jtag_scan.c b/src/jtag_scan.c index 208a1db..c4e80cf 100644 --- a/src/jtag_scan.c +++ b/src/jtag_scan.c @@ -74,7 +74,7 @@ static struct jtag_dev_descr_s { }; /* bucket of ones for don't care TDI */ -static const char ones[] = "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"; +static const uint8_t ones[] = "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF"; /* Scan JTAG chain for devices, store IR length and IDCODE (if present). * Reset TAP state machine. diff --git a/src/platforms/libftdi/jtagtap.c b/src/platforms/libftdi/jtagtap.c index c9bc876..c416892 100644 --- a/src/platforms/libftdi/jtagtap.c +++ b/src/platforms/libftdi/jtagtap.c @@ -97,7 +97,7 @@ jtagtap_tms_seq(uint32_t MS, int ticks) void jtagtap_tdi_seq(const uint8_t final_tms, const uint8_t *DI, int ticks) { - char *tmp; + uint8_t *tmp; int index = 0; int rticks; diff --git a/src/platforms/libftdi/swdptap.c b/src/platforms/libftdi/swdptap.c index eb6e65e..6aafa7d 100644 --- a/src/platforms/libftdi/swdptap.c +++ b/src/platforms/libftdi/swdptap.c @@ -45,7 +45,7 @@ int swdptap_init(void) abort(); } - assert(ftdi_write_data(ftdic, "\xAB\xA8", 2) == 2); + assert(ftdi_write_data(ftdic, (void*)"\xAB\xA8", 2) == 2); /* This must be investigated in more detail. * As described in STM32 Reference Manual... */ @@ -70,7 +70,6 @@ static void swdptap_turnaround(uint8_t dir) { static uint8_t olddir = 0; - /*DEBUG("%s", dir ? "\n-> ":"\n<- ");*/ platform_buffer_flush(); if(dir == olddir) return; @@ -80,7 +79,7 @@ static void swdptap_turnaround(uint8_t dir) assert(ftdi_set_bitmode(ftdic, 0xA3, BITMODE_BITBANG) == 0); /* One clock cycle */ - ftdi_write_data(ftdic, "\xAB\xA8", 2); + ftdi_write_data(ftdic, (void *)"\xAB\xA8", 2); if(!dir) /* SWDIO goes to output */ assert(ftdi_set_bitmode(ftdic, 0xAB, BITMODE_BITBANG) == 0); @@ -90,12 +89,9 @@ static uint8_t swdptap_bit_in(void) { uint8_t ret; - //ftdi_read_data(ftdic, &ret, 1); ftdi_read_pins(ftdic, &ret); ret &= 0x08; - ftdi_write_data(ftdic, "\xA1\xA0", 2); - - //DEBUG("%d", ret?1:0); + ftdi_write_data(ftdic, (void *)"\xA1\xA0", 2); return ret; } @@ -104,13 +100,10 @@ static void swdptap_bit_out(uint8_t val) { uint8_t buf[3] = "\xA0\xA1\xA0"; - //DEBUG("%d", val); - if(val) { for(int i = 0; i < 3; i++) buf[i] |= 0x08; } - //ftdi_write_data(ftdic, buf, 3); platform_buffer_write(buf, 3); } -- cgit v1.2.3 From 6f5b1873d7b986fe7b3bc1f267bae9f7649630a5 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sat, 14 Mar 2015 15:18:22 -0700 Subject: Use size_t for sizes in flash functions. Fix all sign compare warnings. --- src/Makefile | 1 - src/cortexm.c | 4 ++-- src/include/target.h | 4 ++-- src/kinetis.c | 8 ++++---- src/lmi.c | 8 ++++---- src/lpc11xx.c | 12 ++++++------ src/lpc43xx.c | 10 +++++----- src/nrf51.c | 8 ++++---- src/platforms/libftdi/platform.c | 2 +- src/sam3x.c | 12 ++++++------ src/samd.c | 8 ++++---- src/stm32f1.c | 17 +++++++++-------- src/stm32f4.c | 8 ++++---- src/stm32l0.c | 34 +++++++++++++++++----------------- src/stm32l1.c | 9 +++++---- 15 files changed, 73 insertions(+), 72 deletions(-) (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 7ea7865..80e86fe 100644 --- a/src/Makefile +++ b/src/Makefile @@ -10,7 +10,6 @@ endif BUILDDATE := `date +"%Y%m%d"` CFLAGS += -Wall -Wextra -Wno-char-subscripts\ - -Wno-sign-compare \ -O2 -std=gnu99 -g3 -DBUILDDATE=\"$(BUILDDATE)\"\ -I. -Iinclude -Iplatforms/common -I$(PLATFORM_DIR) \ -DVERSION_SUFFIX=\"`../scripts/setlocalversion`\" -MD diff --git a/src/cortexm.c b/src/cortexm.c index b3b657f..b1d3569 100644 --- a/src/cortexm.c +++ b/src/cortexm.c @@ -757,13 +757,13 @@ static bool cortexm_vector_catch(target *t, int argc, char *argv[]) const char *vectors[] = {"reset", NULL, NULL, NULL, "mm", "nocp", "chk", "stat", "bus", "int", "hard"}; uint32_t tmp = 0; - unsigned i, j; + unsigned i; if ((argc < 3) || ((argv[1][0] != 'e') && (argv[1][0] != 'd'))) { gdb_out("usage: monitor vector_catch (enable|disable) " "(hard|int|bus|stat|chk|nocp|mm|reset)\n"); } else { - for (j = 0; j < argc; j++) + for (int j = 0; j < argc; j++) for (i = 0; i < sizeof(vectors) / sizeof(char*); i++) { if (vectors[i] && !strcmp(vectors[i], argv[j])) tmp |= 1 << i; diff --git a/src/include/target.h b/src/include/target.h index a2369e3..5db79a7 100644 --- a/src/include/target.h +++ b/src/include/target.h @@ -180,9 +180,9 @@ struct target_s { /* Flash memory access functions */ const char *xml_mem_map; - int (*flash_erase)(struct target_s *target, uint32_t addr, int len); + int (*flash_erase)(struct target_s *target, uint32_t addr, size_t len); int (*flash_write)(struct target_s *target, uint32_t dest, - const uint8_t *src, int len); + const uint8_t *src, size_t len); /* Host I/O support */ void (*hostio_reply)(target *t, int32_t retcode, uint32_t errcode); diff --git a/src/kinetis.c b/src/kinetis.c index 4b7cf31..b260d2a 100644 --- a/src/kinetis.c +++ b/src/kinetis.c @@ -54,9 +54,9 @@ #define KL25_PAGESIZE 0x400 -static int kl25_flash_erase(struct target_s *target, uint32_t addr, int len); +static int kl25_flash_erase(struct target_s *target, uint32_t addr, size_t len); static int kl25_flash_write(struct target_s *target, uint32_t dest, - const uint8_t *src, int len); + const uint8_t *src, size_t len); static const char kl25_xml_memory_map[] = "" /* ">2)+2]; data[0] = dest; diff --git a/src/lpc11xx.c b/src/lpc11xx.c index d9e918e..b6309c2 100644 --- a/src/lpc11xx.c +++ b/src/lpc11xx.c @@ -63,9 +63,9 @@ static const char lpc8xx_driver[] = "lpc8xx"; static const char lpc11xx_driver[] = "lpc11xx"; static void lpc11x_iap_call(struct target_s *target, struct flash_param *param, unsigned param_len); static int lpc11xx_flash_prepare(struct target_s *target, uint32_t addr, int len); -static int lpc11xx_flash_erase(struct target_s *target, uint32_t addr, int len); +static int lpc11xx_flash_erase(struct target_s *target, uint32_t addr, size_t len); static int lpc11xx_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, - int len); + size_t len); /* * Note that this memory map is actually for the largest of the lpc11xx devices; @@ -220,7 +220,7 @@ lpc11xx_flash_prepare(struct target_s *target, uint32_t addr, int len) } static int -lpc11xx_flash_erase(struct target_s *target, uint32_t addr, int len) +lpc11xx_flash_erase(struct target_s *target, uint32_t addr, size_t len) { if (addr % flash_page_size(target)) @@ -249,7 +249,7 @@ lpc11xx_flash_erase(struct target_s *target, uint32_t addr, int len) } static int -lpc11xx_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, int len) +lpc11xx_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, size_t len) { unsigned first_chunk = dest / IAP_PGM_CHUNKSIZE; unsigned last_chunk = (dest + len - 1) / IAP_PGM_CHUNKSIZE; @@ -258,7 +258,7 @@ lpc11xx_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, for (chunk = first_chunk; chunk <= last_chunk; chunk++) { - DEBUG("chunk %u len %d\n", chunk, len); + DEBUG("chunk %u len %zu\n", chunk, len); /* first and last chunk may require special handling */ if ((chunk == first_chunk) || (chunk == last_chunk)) { @@ -266,7 +266,7 @@ lpc11xx_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, memset(flash_pgm.data, 0xff, sizeof(flash_pgm.data)); /* copy as much as fits */ - int copylen = IAP_PGM_CHUNKSIZE - chunk_offset; + size_t copylen = IAP_PGM_CHUNKSIZE - chunk_offset; if (copylen > len) copylen = len; memcpy(&flash_pgm.data[chunk_offset], src, copylen); diff --git a/src/lpc43xx.c b/src/lpc43xx.c index 3940fed..eca7338 100644 --- a/src/lpc43xx.c +++ b/src/lpc43xx.c @@ -127,9 +127,9 @@ static void lpc43xx_iap_call(struct target_s *target, struct flash_param *param, unsigned param_len); static int lpc43xx_flash_prepare(struct target_s *target, uint32_t addr, int len); -static int lpc43xx_flash_erase(struct target_s *target, uint32_t addr, int len); +static int lpc43xx_flash_erase(struct target_s *target, uint32_t addr, size_t len); static int lpc43xx_flash_write(struct target_s *target, - uint32_t dest, const uint8_t *src, int len); + uint32_t dest, const uint8_t *src, size_t len); static void lpc43xx_set_internal_clock(struct target_s *target); static void lpc43xx_wdt_set_period(struct target_s *target); static void lpc43xx_wdt_pet(struct target_s *target); @@ -384,7 +384,7 @@ static int lpc43xx_flash_prepare(struct target_s *target, uint32_t addr, int len return 0; } -static int lpc43xx_flash_erase(struct target_s *target, uint32_t addr, int len) +static int lpc43xx_flash_erase(struct target_s *target, uint32_t addr, size_t len) { struct flash_program flash_pgm; @@ -433,7 +433,7 @@ static void lpc43xx_set_internal_clock(struct target_s *target) } static int lpc43xx_flash_write(struct target_s *target, - uint32_t dest, const uint8_t *src, int len) + uint32_t dest, const uint8_t *src, size_t len) { unsigned first_chunk = dest / IAP_PGM_CHUNKSIZE; unsigned last_chunk = (dest + len - 1) / IAP_PGM_CHUNKSIZE; @@ -455,7 +455,7 @@ static int lpc43xx_flash_write(struct target_s *target, memset(flash_pgm.data, 0xff, sizeof(flash_pgm.data)); /* copy as much as fits */ - int copylen = IAP_PGM_CHUNKSIZE - chunk_offset; + size_t copylen = IAP_PGM_CHUNKSIZE - chunk_offset; if (copylen > len) copylen = len; diff --git a/src/nrf51.c b/src/nrf51.c index 6c1a8b9..55c9a58 100644 --- a/src/nrf51.c +++ b/src/nrf51.c @@ -27,9 +27,9 @@ #include "command.h" #include "gdb_packet.h" -static int nrf51_flash_erase(struct target_s *target, uint32_t addr, int len); +static int nrf51_flash_erase(struct target_s *target, uint32_t addr, size_t len); static int nrf51_flash_write(struct target_s *target, uint32_t dest, - const uint8_t *src, int len); + const uint8_t *src, size_t len); static bool nrf51_cmd_erase_all(target *t); static bool nrf51_cmd_read_hwid(target *t); @@ -163,7 +163,7 @@ bool nrf51_probe(struct target_s *target) return false; } -static int nrf51_flash_erase(struct target_s *target, uint32_t addr, int len) +static int nrf51_flash_erase(struct target_s *target, uint32_t addr, size_t len) { ADIv5_AP_t *ap = adiv5_target_ap(target); @@ -210,7 +210,7 @@ static int nrf51_flash_erase(struct target_s *target, uint32_t addr, int len) } static int nrf51_flash_write(struct target_s *target, uint32_t dest, - const uint8_t *src, int len) + const uint8_t *src, size_t len) { ADIv5_AP_t *ap = adiv5_target_ap(target); uint32_t offset = dest % 4; diff --git a/src/platforms/libftdi/platform.c b/src/platforms/libftdi/platform.c index e53f011..634090d 100644 --- a/src/platforms/libftdi/platform.c +++ b/src/platforms/libftdi/platform.c @@ -121,7 +121,7 @@ void platform_init(int argc, char **argv) { int err; int c; - int index = 0; + unsigned index = 0; char *serial = NULL; char * cablename = "ftdi"; uint8_t ftdi_init[9] = {TCK_DIVISOR, 0x01, 0x00, SET_BITS_LOW, 0,0, diff --git a/src/sam3x.c b/src/sam3x.c index 902f267..7141cb5 100644 --- a/src/sam3x.c +++ b/src/sam3x.c @@ -28,9 +28,9 @@ #include "command.h" #include "gdb_packet.h" -static int sam3x_flash_erase(struct target_s *target, uint32_t addr, int len); +static int sam3x_flash_erase(struct target_s *target, uint32_t addr, size_t len); static int sam3x_flash_write(struct target_s *target, uint32_t dest, - const uint8_t *src, int len); + const uint8_t *src, size_t len); static bool sam3x_cmd_gpnvm_get(target *t); static bool sam3x_cmd_gpnvm_set(target *t, int argc, char *argv[]); @@ -285,7 +285,7 @@ sam3x_flash_base(struct target_s *target, uint32_t addr, uint32_t *offset) return SAM3N_EEFC_BASE; } -static int sam3x_flash_erase(struct target_s *target, uint32_t addr, int len) +static int sam3x_flash_erase(struct target_s *target, uint32_t addr, size_t len) { uint32_t offset; uint32_t base = sam3x_flash_base(target, addr, &offset); @@ -341,7 +341,7 @@ static int sam3x_flash_erase(struct target_s *target, uint32_t addr, int len) } static int sam3x_flash_write(struct target_s *target, uint32_t dest, - const uint8_t *src, int len) + const uint8_t *src, size_t len) { unsigned page_size; if (strcmp(target->driver, "Atmel SAM4S") == 0) { @@ -359,7 +359,7 @@ static int sam3x_flash_write(struct target_s *target, uint32_t dest, for (unsigned chunk = first_chunk; chunk <= last_chunk; chunk++) { - DEBUG("chunk %u len %d\n", chunk, len); + DEBUG("chunk %u len %zu\n", chunk, len); /* first and last chunk may require special handling */ if ((chunk == first_chunk) || (chunk == last_chunk)) { @@ -367,7 +367,7 @@ static int sam3x_flash_write(struct target_s *target, uint32_t dest, memset(buf, 0xff, sizeof(buf)); /* copy as much as fits */ - int copylen = page_size - offset; + size_t copylen = page_size - offset; if (copylen > len) copylen = len; memcpy(&buf[offset], src, copylen); diff --git a/src/samd.c b/src/samd.c index 1a7a553..6f73956 100644 --- a/src/samd.c +++ b/src/samd.c @@ -40,9 +40,9 @@ #include "gdb_packet.h" #include "cortexm.h" -static int samd_flash_erase(struct target_s *target, uint32_t addr, int len); +static int samd_flash_erase(struct target_s *target, uint32_t addr, size_t len); static int samd_flash_write(struct target_s *target, uint32_t dest, - const uint8_t *src, int len); + const uint8_t *src, size_t len); static bool samd_cmd_erase_all(target *t); static bool samd_cmd_lock_flash(target *t); @@ -479,7 +479,7 @@ static void samd_unlock_current_address(struct target_s *target) /** * Erase flash row by row */ -static int samd_flash_erase(struct target_s *target, uint32_t addr, int len) +static int samd_flash_erase(struct target_s *target, uint32_t addr, size_t len) { ADIv5_AP_t *ap = adiv5_target_ap(target); @@ -515,7 +515,7 @@ static int samd_flash_erase(struct target_s *target, uint32_t addr, int len) * Write flash page by page */ static int samd_flash_write(struct target_s *target, uint32_t dest, - const uint8_t *src, int len) + const uint8_t *src, size_t len) { ADIv5_AP_t *ap = adiv5_target_ap(target); diff --git a/src/stm32f1.c b/src/stm32f1.c index 017196a..405bc1a 100644 --- a/src/stm32f1.c +++ b/src/stm32f1.c @@ -45,12 +45,12 @@ const struct command_s stm32f1_cmd_list[] = { }; -static int stm32md_flash_erase(struct target_s *target, uint32_t addr, int len); -static int stm32hd_flash_erase(struct target_s *target, uint32_t addr, int len); -static int stm32f1_flash_erase(struct target_s *target, uint32_t addr, int len, +static int stm32md_flash_erase(struct target_s *target, uint32_t addr, size_t len); +static int stm32hd_flash_erase(struct target_s *target, uint32_t addr, size_t len); +static int stm32f1_flash_erase(struct target_s *target, uint32_t addr, size_t len, uint32_t pagesize); static int stm32f1_flash_write(struct target_s *target, uint32_t dest, - const uint8_t *src, int len); + const uint8_t *src, size_t len); static const char stm32f1_driver_str[] = "STM32, Medium density."; static const char stm32hd_driver_str[] = "STM32, High density."; @@ -229,7 +229,8 @@ static void stm32f1_flash_unlock(ADIv5_AP_t *ap) adiv5_ap_mem_write(ap, FLASH_KEYR, KEY2); } -static int stm32f1_flash_erase(struct target_s *target, uint32_t addr, int len, uint32_t pagesize) +static int stm32f1_flash_erase(struct target_s *target, uint32_t addr, + size_t len, uint32_t pagesize) { ADIv5_AP_t *ap = adiv5_target_ap(target); uint16_t sr; @@ -264,18 +265,18 @@ static int stm32f1_flash_erase(struct target_s *target, uint32_t addr, int len, return 0; } -static int stm32hd_flash_erase(struct target_s *target, uint32_t addr, int len) +static int stm32hd_flash_erase(struct target_s *target, uint32_t addr, size_t len) { return stm32f1_flash_erase(target, addr, len, 0x800); } -static int stm32md_flash_erase(struct target_s *target, uint32_t addr, int len) +static int stm32md_flash_erase(struct target_s *target, uint32_t addr, size_t len) { return stm32f1_flash_erase(target, addr, len, 0x400); } static int stm32f1_flash_write(struct target_s *target, uint32_t dest, - const uint8_t *src, int len) + const uint8_t *src, size_t len) { ADIv5_AP_t *ap = adiv5_target_ap(target); uint32_t offset = dest % 4; diff --git a/src/stm32f4.c b/src/stm32f4.c index bc3572f..fac097a 100644 --- a/src/stm32f4.c +++ b/src/stm32f4.c @@ -46,9 +46,9 @@ const struct command_s stm32f4_cmd_list[] = { }; -static int stm32f4_flash_erase(struct target_s *target, uint32_t addr, int len); +static int stm32f4_flash_erase(struct target_s *target, uint32_t addr, size_t len); static int stm32f4_flash_write(struct target_s *target, uint32_t dest, - const uint8_t *src, int len); + const uint8_t *src, size_t len); static const char stm32f4_driver_str[] = "STM32F4xx"; @@ -189,7 +189,7 @@ static void stm32f4_flash_unlock(ADIv5_AP_t *ap) } } -static int stm32f4_flash_erase(struct target_s *target, uint32_t addr, int len) +static int stm32f4_flash_erase(struct target_s *target, uint32_t addr, size_t len) { ADIv5_AP_t *ap = adiv5_target_ap(target); uint16_t sr; @@ -237,7 +237,7 @@ static int stm32f4_flash_erase(struct target_s *target, uint32_t addr, int len) } static int stm32f4_flash_write(struct target_s *target, uint32_t dest, - const uint8_t *src, int len) + const uint8_t *src, size_t len) { ADIv5_AP_t *ap = adiv5_target_ap(target); uint32_t offset = dest % 4; diff --git a/src/stm32l0.c b/src/stm32l0.c index 0de028f..2e30035 100644 --- a/src/stm32l0.c +++ b/src/stm32l0.c @@ -125,32 +125,32 @@ static int inhibit_stubs; /* Local option to force non-stub flash IO */ static int stm32lx_nvm_erase(struct target_s* target, - uint32_t addr, int len); + uint32_t addr, size_t len); static int stm32lx_nvm_write(struct target_s* target, uint32_t destination, const uint8_t* source, - int size); + size_t size); static int stm32lx_nvm_prog_erase(struct target_s* target, - uint32_t addr, int len); + uint32_t addr, size_t len); static int stm32lx_nvm_prog_write(struct target_s* target, uint32_t destination, const uint8_t* source, - int size); + size_t size); static int stm32lx_nvm_prog_erase_stubbed(struct target_s* target, - uint32_t addr, int len); + uint32_t addr, size_t len); static int stm32lx_nvm_prog_write_stubbed(struct target_s* target, uint32_t destination, const uint8_t* source, - int size); + size_t size); static int stm32lx_nvm_data_erase(struct target_s* target, - uint32_t addr, int len); + uint32_t addr, size_t len); static int stm32lx_nvm_data_write(struct target_s* target, uint32_t destination, const uint8_t* source, - int size); + size_t size); static bool stm32lx_cmd_option (target* t, int argc, char** argv); static bool stm32lx_cmd_eeprom (target* t, int argc, char** argv); @@ -371,7 +371,7 @@ static bool stm32lx_nvm_opt_unlock(ADIv5_AP_t* ap, uint32_t nvm) when the MCU hasn't entered a fault state(see NOTES). The flash array is erased for all pages from addr to addr+len inclusive. */ static int stm32lx_nvm_prog_erase_stubbed(struct target_s* target, - uint32_t addr, int size) + uint32_t addr, size_t size) { struct stm32lx_nvm_stub_info info; const uint32_t nvm = stm32lx_nvm_phys(target); @@ -417,7 +417,7 @@ static int stm32lx_nvm_prog_erase_stubbed(struct target_s* target, static int stm32lx_nvm_prog_write_stubbed(struct target_s* target, uint32_t destination, const uint8_t* source, - int size) + size_t size) { struct stm32lx_nvm_stub_info info; const uint32_t nvm = stm32lx_nvm_phys(target); @@ -491,7 +491,7 @@ static int stm32lx_nvm_prog_write_stubbed(struct target_s* target, /** Erase a region of NVM for STM32Lx. This is the lead function and it will invoke an implementation, stubbed or not depending on the options and the range of addresses. */ -static int stm32lx_nvm_erase(struct target_s* target, uint32_t addr, int size) +static int stm32lx_nvm_erase(struct target_s* target, uint32_t addr, size_t size) { if (addr >= STM32Lx_NVM_EEPROM_PHYS) return stm32lx_nvm_data_erase(target, addr, size); @@ -515,7 +515,7 @@ static int stm32lx_nvm_erase(struct target_s* target, uint32_t addr, int size) static int stm32lx_nvm_write(struct target_s* target, uint32_t destination, const uint8_t* source, - int size) + size_t size) { if (destination >= STM32Lx_NVM_EEPROM_PHYS) return stm32lx_nvm_data_write(target, destination, source, @@ -556,7 +556,7 @@ static int stm32lx_nvm_write(struct target_s* target, flash array is erased for all pages from addr to addr+len inclusive. NVM register file address chosen from target. */ static int stm32lx_nvm_prog_erase(struct target_s* target, - uint32_t addr, int len) + uint32_t addr, size_t len) { ADIv5_AP_t* ap = adiv5_target_ap(target); const size_t page_size = stm32lx_nvm_prog_page_size(target); @@ -617,7 +617,7 @@ static int stm32lx_nvm_prog_erase(struct target_s* target, static int stm32lx_nvm_prog_write(struct target_s* target, uint32_t destination, const uint8_t* source_8, - int size) + size_t size) { ADIv5_AP_t* ap = adiv5_target_ap(target); const uint32_t nvm = stm32lx_nvm_phys(target); @@ -705,7 +705,7 @@ static int stm32lx_nvm_prog_write(struct target_s* target, addr+len, inclusive, on a word boundary. NVM register file address chosen from target. */ static int stm32lx_nvm_data_erase(struct target_s* target, - uint32_t addr, int len) + uint32_t addr, size_t len) { ADIv5_AP_t* ap = adiv5_target_ap(target); const size_t page_size = stm32lx_nvm_data_page_size(target); @@ -763,7 +763,7 @@ static int stm32lx_nvm_data_erase(struct target_s* target, static int stm32lx_nvm_data_write(struct target_s* target, uint32_t destination, const uint8_t* source_8, - int size) + size_t size) { ADIv5_AP_t* ap = adiv5_target_ap(target); const uint32_t nvm = stm32lx_nvm_phys(target); @@ -933,7 +933,7 @@ static bool stm32lx_cmd_option(target* t, int argc, char** argv) goto usage; /* Report the current option values */ - for(int i = 0; i < opt_size; i += sizeof(uint32_t)) { + for(unsigned i = 0; i < opt_size; i += sizeof(uint32_t)) { uint32_t addr = STM32Lx_NVM_OPT_PHYS + i; uint32_t val = adiv5_ap_mem_read(ap, addr); gdb_outf("0x%08x: 0x%04x 0x%04x %s\n", diff --git a/src/stm32l1.c b/src/stm32l1.c index 227f67c..86298e5 100644 --- a/src/stm32l1.c +++ b/src/stm32l1.c @@ -35,9 +35,10 @@ #include "command.h" #include "gdb_packet.h" -static int stm32l1_flash_erase(struct target_s *target, uint32_t addr, int len); +static int stm32l1_flash_erase(struct target_s *target, uint32_t addr, + size_t len); static int stm32l1_flash_write(struct target_s *target, uint32_t dest, - const uint8_t *src, int len); + const uint8_t *src, size_t len); static const char stm32l1_driver_str[] = "STM32L1xx"; @@ -112,7 +113,7 @@ static void stm32l1_flash_unlock(ADIv5_AP_t *ap) adiv5_ap_mem_write(ap, STM32L1_FLASH_PRGKEYR, STM32L1_PRGKEY2); } -static int stm32l1_flash_erase(struct target_s *target, uint32_t addr, int len) +static int stm32l1_flash_erase(struct target_s *target, uint32_t addr, size_t len) { ADIv5_AP_t *ap = adiv5_target_ap(target); uint16_t sr; @@ -150,7 +151,7 @@ static int stm32l1_flash_erase(struct target_s *target, uint32_t addr, int len) } static int stm32l1_flash_write(struct target_s *target, uint32_t dest, - const uint8_t *src, int len) + const uint8_t *src, size_t len) { ADIv5_AP_t *ap = adiv5_target_ap(target); uint16_t sr; -- cgit v1.2.3 From 2e785e56fa4e77549878eac88f2c4891af043e64 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sat, 14 Mar 2015 18:03:04 -0700 Subject: adiv5: Encode APnDP into register definition. Clean up magic numbers in adiv5 calls. Removed old adiv5_dp_write_ap and adiv5_dp_read_ap.--- src/adiv5.c | 90 +++++++++++++++++++---------------------------------- src/adiv5_jtagdp.c | 31 +++++++++--------- src/adiv5_swdp.c | 28 +++++++++++------ src/cortexm.c | 35 ++++++++++++--------- src/include/adiv5.h | 57 +++++++++++++++++---------------- src/lmi.c | 11 ++++--- src/samd.c | 4 +-- 7 files changed, 123 insertions(+), 133 deletions(-) (limited to 'src') diff --git a/src/adiv5.c b/src/adiv5.c index 361cd75..aee8471 100644 --- a/src/adiv5.c +++ b/src/adiv5.c @@ -160,23 +160,6 @@ void adiv5_dp_init(ADIv5_DP_t *dp) adiv5_dp_unref(dp); } -void adiv5_dp_write_ap(ADIv5_DP_t *dp, uint8_t addr, uint32_t value) -{ - adiv5_dp_low_access(dp, ADIV5_LOW_AP, ADIV5_LOW_WRITE, addr, value); -} - -uint32_t adiv5_dp_read_ap(ADIv5_DP_t *dp, uint8_t addr) -{ - uint32_t ret; - - adiv5_dp_low_access(dp, ADIV5_LOW_AP, ADIV5_LOW_READ, addr, 0); - ret = adiv5_dp_low_access(dp, ADIV5_LOW_DP, ADIV5_LOW_READ, - ADIV5_DP_RDBUFF, 0); - - return ret; -} - - static int ap_check_error(struct target_s *target) { @@ -194,26 +177,24 @@ ap_mem_read_words(struct target_s *target, uint32_t *dest, uint32_t src, int len adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw | ADIV5_AP_CSW_SIZE_WORD | ADIV5_AP_CSW_ADDRINC_SINGLE); - adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP, ADIV5_LOW_WRITE, - ADIV5_AP_TAR, src); - adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP, ADIV5_LOW_READ, - ADIV5_AP_DRW, 0); + adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_TAR, src); + adiv5_dp_low_access(ap->dp, ADIV5_LOW_READ, ADIV5_AP_DRW, 0); while(--len) { - *dest++ = adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP, + *dest++ = adiv5_dp_low_access(ap->dp, ADIV5_LOW_READ, ADIV5_AP_DRW, 0); src += 4; /* Check for 10 bit address overflow */ if ((src ^ osrc) & 0xfffffc00) { osrc = src; - adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP, + adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_TAR, src); - adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP, + adiv5_dp_low_access(ap->dp, ADIV5_LOW_READ, ADIV5_AP_DRW, 0); } } - *dest++ = adiv5_dp_low_access(ap->dp, ADIV5_LOW_DP, ADIV5_LOW_READ, - ADIV5_DP_RDBUFF, 0); + *dest++ = adiv5_dp_low_access(ap->dp, ADIV5_LOW_READ, + ADIV5_DP_RDBUFF, 0); return 0; } @@ -229,12 +210,10 @@ ap_mem_read_halfwords(struct target_s *target, uint16_t *dest, uint32_t src, int adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw | ADIV5_AP_CSW_SIZE_HALFWORD | ADIV5_AP_CSW_ADDRINC_SINGLE); - adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP, ADIV5_LOW_WRITE, - ADIV5_AP_TAR, src); - adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP, ADIV5_LOW_READ, - ADIV5_AP_DRW, 0); + adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_TAR, src); + adiv5_dp_low_access(ap->dp, ADIV5_LOW_READ, ADIV5_AP_DRW, 0); while(--len) { - tmp = adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP, ADIV5_LOW_READ, + tmp = adiv5_dp_low_access(ap->dp, ADIV5_LOW_READ, ADIV5_AP_DRW, 0); *dest++ = (tmp >> ((src & 0x2) << 3) & 0xFFFF); @@ -242,13 +221,13 @@ ap_mem_read_halfwords(struct target_s *target, uint16_t *dest, uint32_t src, int /* Check for 10 bit address overflow */ if ((src ^ osrc) & 0xfffffc00) { osrc = src; - adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP, + adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_TAR, src); - adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP, + adiv5_dp_low_access(ap->dp, ADIV5_LOW_READ, ADIV5_AP_DRW, 0); } } - tmp = adiv5_dp_low_access(ap->dp, 0, 1, ADIV5_DP_RDBUFF, 0); + tmp = adiv5_dp_low_access(ap->dp, ADIV5_LOW_READ, ADIV5_DP_RDBUFF, 0); *dest++ = (tmp >> ((src & 0x2) << 3) & 0xFFFF); return 0; @@ -263,25 +242,23 @@ ap_mem_read_bytes(struct target_s *target, uint8_t *dest, uint32_t src, int len) adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw | ADIV5_AP_CSW_SIZE_BYTE | ADIV5_AP_CSW_ADDRINC_SINGLE); - adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP, ADIV5_LOW_WRITE, - ADIV5_AP_TAR, src); - adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP, ADIV5_LOW_READ, - ADIV5_AP_DRW, 0); + adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_TAR, src); + adiv5_dp_low_access(ap->dp, ADIV5_LOW_READ, ADIV5_AP_DRW, 0); while(--len) { - tmp = adiv5_dp_low_access(ap->dp, 1, 1, ADIV5_AP_DRW, 0); + tmp = adiv5_dp_low_access(ap->dp, ADIV5_LOW_READ, ADIV5_AP_DRW, 0); *dest++ = (tmp >> ((src & 0x3) << 3) & 0xFF); src++; /* Check for 10 bit address overflow */ if ((src ^ osrc) & 0xfffffc00) { osrc = src; - adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP, + adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_TAR, src); - adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP, + adiv5_dp_low_access(ap->dp, ADIV5_LOW_READ, ADIV5_AP_DRW, 0); } } - tmp = adiv5_dp_low_access(ap->dp, 0, 1, ADIV5_DP_RDBUFF, 0); + tmp = adiv5_dp_low_access(ap->dp, ADIV5_LOW_READ, ADIV5_DP_RDBUFF, 0); *dest++ = (tmp >> ((src++ & 0x3) << 3) & 0xFF); return 0; @@ -298,16 +275,15 @@ ap_mem_write_words(struct target_s *target, uint32_t dest, const uint32_t *src, adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw | ADIV5_AP_CSW_SIZE_WORD | ADIV5_AP_CSW_ADDRINC_SINGLE); - adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP, ADIV5_LOW_WRITE, - ADIV5_AP_TAR, dest); + adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_TAR, dest); while(len--) { - adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP, ADIV5_LOW_WRITE, + adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_DRW, *src++); dest += 4; /* Check for 10 bit address overflow */ if ((dest ^ odest) & 0xfffffc00) { odest = dest; - adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP, + adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_TAR, dest); } } @@ -325,17 +301,16 @@ ap_mem_write_halfwords(struct target_s *target, uint32_t dest, const uint16_t *s adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw | ADIV5_AP_CSW_SIZE_HALFWORD | ADIV5_AP_CSW_ADDRINC_SINGLE); - adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP, ADIV5_LOW_WRITE, - ADIV5_AP_TAR, dest); + adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_TAR, dest); while(len--) { uint32_t tmp = (uint32_t)*src++ << ((dest & 2) << 3); - adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP, ADIV5_LOW_WRITE, + adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_DRW, tmp); dest += 2; /* Check for 10 bit address overflow */ if ((dest ^ odest) & 0xfffffc00) { odest = dest; - adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP, + adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_TAR, dest); } } @@ -350,17 +325,16 @@ ap_mem_write_bytes(struct target_s *target, uint32_t dest, const uint8_t *src, i adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw | ADIV5_AP_CSW_SIZE_BYTE | ADIV5_AP_CSW_ADDRINC_SINGLE); - adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP, ADIV5_LOW_WRITE, - ADIV5_AP_TAR, dest); + adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_TAR, dest); while(len--) { uint32_t tmp = (uint32_t)*src++ << ((dest++ & 3) << 3); - adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP, ADIV5_LOW_WRITE, + adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_DRW, tmp); /* Check for 10 bit address overflow */ if ((dest ^ odest) & 0xfffffc00) { odest = dest; - adiv5_dp_low_access(ap->dp, ADIV5_LOW_AP, + adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_TAR, dest); } } @@ -429,19 +403,19 @@ void adiv5_ap_mem_write_byte(ADIv5_AP_t *ap, uint32_t addr, uint8_t value) adiv5_ap_write(ap, ADIV5_AP_DRW, v); } -void adiv5_ap_write(ADIv5_AP_t *ap, uint8_t addr, uint32_t value) +void adiv5_ap_write(ADIv5_AP_t *ap, uint16_t addr, uint32_t value) { adiv5_dp_write(ap->dp, ADIV5_DP_SELECT, ((uint32_t)ap->apsel << 24)|(addr & 0xF0)); - adiv5_dp_write_ap(ap->dp, addr, value); + adiv5_dp_write(ap->dp, addr, value); } -uint32_t adiv5_ap_read(ADIv5_AP_t *ap, uint8_t addr) +uint32_t adiv5_ap_read(ADIv5_AP_t *ap, uint16_t addr) { uint32_t ret; adiv5_dp_write(ap->dp, ADIV5_DP_SELECT, ((uint32_t)ap->apsel << 24)|(addr & 0xF0)); - ret = adiv5_dp_read_ap(ap->dp, addr); + ret = adiv5_dp_read(ap->dp, addr); return ret; } diff --git a/src/adiv5_jtagdp.c b/src/adiv5_jtagdp.c index 8f62a11..eb60caa 100644 --- a/src/adiv5_jtagdp.c +++ b/src/adiv5_jtagdp.c @@ -36,13 +36,13 @@ #define IR_DPACC 0xA #define IR_APACC 0xB -static void adiv5_jtagdp_write(ADIv5_DP_t *dp, uint8_t addr, uint32_t value); -static uint32_t adiv5_jtagdp_read(ADIv5_DP_t *dp, uint8_t addr); +static void adiv5_jtagdp_write(ADIv5_DP_t *dp, uint16_t addr, uint32_t value); +static uint32_t adiv5_jtagdp_read(ADIv5_DP_t *dp, uint16_t addr); static uint32_t adiv5_jtagdp_error(ADIv5_DP_t *dp); -static uint32_t adiv5_jtagdp_low_access(ADIv5_DP_t *dp, uint8_t APnDP, uint8_t RnW, - uint8_t addr, uint32_t value); +static uint32_t adiv5_jtagdp_low_access(ADIv5_DP_t *dp, uint8_t RnW, + uint16_t addr, uint32_t value); void adiv5_jtag_dp_handler(jtag_dev_t *dev) @@ -60,35 +60,36 @@ void adiv5_jtag_dp_handler(jtag_dev_t *dev) adiv5_dp_init(dp); } -static void adiv5_jtagdp_write(ADIv5_DP_t *dp, uint8_t addr, uint32_t value) +static void adiv5_jtagdp_write(ADIv5_DP_t *dp, uint16_t addr, uint32_t value) { - adiv5_jtagdp_low_access(dp, ADIV5_LOW_DP, ADIV5_LOW_WRITE, addr, value); + adiv5_jtagdp_low_access(dp, ADIV5_LOW_WRITE, addr, value); } -static uint32_t adiv5_jtagdp_read(ADIv5_DP_t *dp, uint8_t addr) +static uint32_t adiv5_jtagdp_read(ADIv5_DP_t *dp, uint16_t addr) { - adiv5_jtagdp_low_access(dp, ADIV5_LOW_DP, ADIV5_LOW_READ, addr, 0); - return adiv5_jtagdp_low_access(dp, ADIV5_LOW_DP, ADIV5_LOW_READ, + adiv5_jtagdp_low_access(dp, ADIV5_LOW_READ, addr, 0); + return adiv5_jtagdp_low_access(dp, ADIV5_LOW_READ, ADIV5_DP_RDBUFF, 0); } static uint32_t adiv5_jtagdp_error(ADIv5_DP_t *dp) { - adiv5_jtagdp_low_access(dp, ADIV5_LOW_DP, ADIV5_LOW_READ, - ADIV5_DP_CTRLSTAT, 0); - return adiv5_jtagdp_low_access(dp, ADIV5_LOW_DP, ADIV5_LOW_WRITE, + adiv5_jtagdp_low_access(dp, ADIV5_LOW_READ, ADIV5_DP_CTRLSTAT, 0); + return adiv5_jtagdp_low_access(dp, ADIV5_LOW_WRITE, ADIV5_DP_CTRLSTAT, 0xF0000032) & 0x32; } -static uint32_t adiv5_jtagdp_low_access(ADIv5_DP_t *dp, uint8_t APnDP, uint8_t RnW, - uint8_t addr, uint32_t value) +static uint32_t adiv5_jtagdp_low_access(ADIv5_DP_t *dp, uint8_t RnW, + uint16_t addr, uint32_t value) { + bool APnDP = addr & ADIV5_APnDP; + addr &= 0xff; uint64_t request, response; uint8_t ack; request = ((uint64_t)value << 3) | ((addr >> 1) & 0x06) | (RnW?1:0); - jtag_dev_write_ir(dp->dev, APnDP?IR_APACC:IR_DPACC); + jtag_dev_write_ir(dp->dev, APnDP ? IR_APACC : IR_DPACC); int tries = 1000; do { diff --git a/src/adiv5_swdp.c b/src/adiv5_swdp.c index 9df362f..3e775cc 100644 --- a/src/adiv5_swdp.c +++ b/src/adiv5_swdp.c @@ -33,13 +33,13 @@ #define SWDP_ACK_WAIT 0x02 #define SWDP_ACK_FAULT 0x04 -static void adiv5_swdp_write(ADIv5_DP_t *dp, uint8_t addr, uint32_t value); -static uint32_t adiv5_swdp_read(ADIv5_DP_t *dp, uint8_t addr); +static void adiv5_swdp_write(ADIv5_DP_t *dp, uint16_t addr, uint32_t value); +static uint32_t adiv5_swdp_read(ADIv5_DP_t *dp, uint16_t addr); static uint32_t adiv5_swdp_error(ADIv5_DP_t *dp); -static uint32_t adiv5_swdp_low_access(ADIv5_DP_t *dp, uint8_t APnDP, uint8_t RnW, - uint8_t addr, uint32_t value); +static uint32_t adiv5_swdp_low_access(ADIv5_DP_t *dp, uint8_t RnW, + uint16_t addr, uint32_t value); int adiv5_swdp_scan(void) @@ -78,14 +78,20 @@ int adiv5_swdp_scan(void) return target_list?1:0; } -static void adiv5_swdp_write(ADIv5_DP_t *dp, uint8_t addr, uint32_t value) +static void adiv5_swdp_write(ADIv5_DP_t *dp, uint16_t addr, uint32_t value) { - adiv5_swdp_low_access(dp, ADIV5_LOW_DP, ADIV5_LOW_WRITE, addr, value); + adiv5_swdp_low_access(dp, ADIV5_LOW_WRITE, addr, value); } -static uint32_t adiv5_swdp_read(ADIv5_DP_t *dp, uint8_t addr) +static uint32_t adiv5_swdp_read(ADIv5_DP_t *dp, uint16_t addr) { - return adiv5_swdp_low_access(dp, ADIV5_LOW_DP, ADIV5_LOW_READ, addr, 0); + if (addr & ADIV5_APnDP) { + adiv5_dp_low_access(dp, ADIV5_LOW_READ, addr, 0); + return adiv5_dp_low_access(dp, ADIV5_LOW_READ, + ADIV5_DP_RDBUFF, 0); + } else { + return adiv5_swdp_low_access(dp, ADIV5_LOW_READ, addr, 0); + } } static uint32_t adiv5_swdp_error(ADIv5_DP_t *dp) @@ -111,9 +117,11 @@ static uint32_t adiv5_swdp_error(ADIv5_DP_t *dp) return err; } -static uint32_t adiv5_swdp_low_access(ADIv5_DP_t *dp, uint8_t APnDP, uint8_t RnW, - uint8_t addr, uint32_t value) +static uint32_t adiv5_swdp_low_access(ADIv5_DP_t *dp, uint8_t RnW, + uint16_t addr, uint32_t value) { + bool APnDP = addr & ADIV5_APnDP; + addr &= 0xff; uint8_t request = 0x81; uint32_t response; uint8_t ack; diff --git a/src/cortexm.c b/src/cortexm.c index b1d3569..da48f8e 100644 --- a/src/cortexm.c +++ b/src/cortexm.c @@ -359,20 +359,23 @@ cortexm_regs_read(struct target_s *target, void *data) /* Map the banked data registers (0x10-0x1c) to the * debug registers DHCSR, DCRSR, DCRDR and DEMCR respectively */ - adiv5_dp_low_access(ap->dp, 1, 0, ADIV5_AP_TAR, CORTEXM_DHCSR); + adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_TAR, CORTEXM_DHCSR); /* Walk the regnum_cortex_m array, reading the registers it * calls out. */ adiv5_ap_write(ap, ADIV5_AP_DB(1), regnum_cortex_m[0]); /* Required to switch banks */ - *regs++ = adiv5_dp_read_ap(ap->dp, ADIV5_AP_DB(2)); + *regs++ = adiv5_dp_read(ap->dp, ADIV5_AP_DB(2)); for(i = 1; i < sizeof(regnum_cortex_m) / 4; i++) { - adiv5_dp_low_access(ap->dp, 1, 0, ADIV5_AP_DB(1), regnum_cortex_m[i]); - *regs++ = adiv5_dp_read_ap(ap->dp, ADIV5_AP_DB(2)); + adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_DB(1), + regnum_cortex_m[i]); + *regs++ = adiv5_dp_read(ap->dp, ADIV5_AP_DB(2)); } if (target->target_options & TOPT_FLAVOUR_V7MF) for(i = 0; i < sizeof(regnum_cortex_mf) / 4; i++) { - adiv5_dp_low_access(ap->dp, 1, 0, ADIV5_AP_DB(1), regnum_cortex_mf[i]); - *regs++ = adiv5_dp_read_ap(ap->dp, ADIV5_AP_DB(2)); + adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, + ADIV5_AP_DB(1), + regnum_cortex_mf[i]); + *regs++ = adiv5_dp_read(ap->dp, ADIV5_AP_DB(2)); } return 0; @@ -391,22 +394,26 @@ cortexm_regs_write(struct target_s *target, const void *data) /* Map the banked data registers (0x10-0x1c) to the * debug registers DHCSR, DCRSR, DCRDR and DEMCR respectively */ - adiv5_dp_low_access(ap->dp, 1, 0, ADIV5_AP_TAR, CORTEXM_DHCSR); + adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_TAR, CORTEXM_DHCSR); /* Walk the regnum_cortex_m array, writing the registers it * calls out. */ adiv5_ap_write(ap, ADIV5_AP_DB(2), *regs++); /* Required to switch banks */ - adiv5_dp_low_access(ap->dp, 1, 0, ADIV5_AP_DB(1), 0x10000 | regnum_cortex_m[0]); + adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_DB(1), + 0x10000 | regnum_cortex_m[0]); for(i = 1; i < sizeof(regnum_cortex_m) / 4; i++) { - adiv5_dp_low_access(ap->dp, 1, 0, ADIV5_AP_DB(2), *regs++); - adiv5_dp_low_access(ap->dp, 1, 0, ADIV5_AP_DB(1), - 0x10000 | regnum_cortex_m[i]); + adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, + ADIV5_AP_DB(2), *regs++); + adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_DB(1), + 0x10000 | regnum_cortex_m[i]); } if (target->target_options & TOPT_FLAVOUR_V7MF) for(i = 0; i < sizeof(regnum_cortex_mf) / 4; i++) { - adiv5_dp_low_access(ap->dp, 1, 0, ADIV5_AP_DB(2), *regs++); - adiv5_dp_low_access(ap->dp, 1, 0, ADIV5_AP_DB(1), - 0x10000 | regnum_cortex_mf[i]); + adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, + ADIV5_AP_DB(2), *regs++); + adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, + ADIV5_AP_DB(1), + 0x10000 | regnum_cortex_mf[i]); } return 0; diff --git a/src/include/adiv5.h b/src/include/adiv5.h index e0ce9cf..cfdb4e5 100644 --- a/src/include/adiv5.h +++ b/src/include/adiv5.h @@ -24,12 +24,16 @@ #include "jtag_scan.h" #include "target.h" +#define ADIV5_APnDP 0x100 +#define ADIV5_DP_REG(x) (x) +#define ADIV5_AP_REG(x) (ADIV5_APnDP | (x)) + /* ADIv5 DP Register addresses */ -#define ADIV5_DP_IDCODE 0x0 -#define ADIV5_DP_ABORT 0x0 -#define ADIV5_DP_CTRLSTAT 0x4 -#define ADIV5_DP_SELECT 0x8 -#define ADIV5_DP_RDBUFF 0xC +#define ADIV5_DP_IDCODE ADIV5_DP_REG(0x0) +#define ADIV5_DP_ABORT ADIV5_DP_REG(0x0) +#define ADIV5_DP_CTRLSTAT ADIV5_DP_REG(0x4) +#define ADIV5_DP_SELECT ADIV5_DP_REG(0x8) +#define ADIV5_DP_RDBUFF ADIV5_DP_REG(0xC) /* AP Abort Register (ABORT) */ /* Bits 31:5 - Reserved */ @@ -63,15 +67,15 @@ /* ADIv5 MEM-AP Registers */ -#define ADIV5_AP_CSW 0x00 -#define ADIV5_AP_TAR 0x04 +#define ADIV5_AP_CSW ADIV5_AP_REG(0x00) +#define ADIV5_AP_TAR ADIV5_AP_REG(0x04) /* 0x08 - Reserved */ -#define ADIV5_AP_DRW 0x0C -#define ADIV5_AP_DB(x) (0x10 + (4*(x))) +#define ADIV5_AP_DRW ADIV5_AP_REG(0x0C) +#define ADIV5_AP_DB(x) ADIV5_AP_REG(0x10 + (4*(x))) /* 0x20:0xF0 - Reserved */ -#define ADIV5_AP_CFG 0xF4 -#define ADIV5_AP_BASE 0xF8 -#define ADIV5_AP_IDR 0xFC +#define ADIV5_AP_CFG ADIV5_AP_REG(0xF4) +#define ADIV5_AP_BASE ADIV5_AP_REG(0xF8) +#define ADIV5_AP_IDR ADIV5_AP_REG(0xFC) /* AP Control and Status Word (CSW) */ #define ADIV5_AP_CSW_DBGSWENABLE (1u << 31) @@ -93,11 +97,9 @@ #define ADIV5_AP_CSW_SIZE_WORD (2u << 0) #define ADIV5_AP_CSW_SIZE_MASK (7u << 0) -/* Constants to make RnW and APnDP parameters more clear in code */ +/* Constants to make RnW parameters more clear in code */ #define ADIV5_LOW_WRITE 0 #define ADIV5_LOW_READ 1 -#define ADIV5_LOW_DP 0 -#define ADIV5_LOW_AP 1 /* Try to keep this somewhat absract for later adding SW-DP */ typedef struct ADIv5_DP_s { @@ -107,13 +109,13 @@ typedef struct ADIv5_DP_s { bool allow_timeout; - void (*dp_write)(struct ADIv5_DP_s *dp, uint8_t addr, uint32_t value); - uint32_t (*dp_read)(struct ADIv5_DP_s *dp, uint8_t addr); + void (*dp_write)(struct ADIv5_DP_s *dp, uint16_t addr, uint32_t value); + uint32_t (*dp_read)(struct ADIv5_DP_s *dp, uint16_t addr); uint32_t (*error)(struct ADIv5_DP_s *dp); - uint32_t (*low_access)(struct ADIv5_DP_s *dp, uint8_t APnDP, uint8_t RnW, - uint8_t addr, uint32_t value); + uint32_t (*low_access)(struct ADIv5_DP_s *dp, uint8_t RnW, + uint16_t addr, uint32_t value); union { jtag_dev_t *dev; @@ -121,12 +123,12 @@ typedef struct ADIv5_DP_s { }; } ADIv5_DP_t; -static inline void adiv5_dp_write(ADIv5_DP_t *dp, uint8_t addr, uint32_t value) +static inline void adiv5_dp_write(ADIv5_DP_t *dp, uint16_t addr, uint32_t value) { dp->dp_write(dp, addr, value); } -static inline uint32_t adiv5_dp_read(ADIv5_DP_t *dp, uint8_t addr) +static inline uint32_t adiv5_dp_read(ADIv5_DP_t *dp, uint16_t addr) { return dp->dp_read(dp, addr); } @@ -136,10 +138,10 @@ static inline uint32_t adiv5_dp_error(ADIv5_DP_t *dp) return dp->error(dp); } -static inline uint32_t adiv5_dp_low_access(struct ADIv5_DP_s *dp, uint8_t APnDP, - uint8_t RnW, uint8_t addr, uint32_t value) +static inline uint32_t adiv5_dp_low_access(struct ADIv5_DP_s *dp, uint8_t RnW, + uint16_t addr, uint32_t value) { - return dp->low_access(dp, APnDP, RnW, addr, value); + return dp->low_access(dp, RnW, addr, value); } typedef struct ADIv5_AP_s { @@ -164,9 +166,6 @@ void adiv5_ap_ref(ADIv5_AP_t *ap); void adiv5_dp_unref(ADIv5_DP_t *dp); void adiv5_ap_unref(ADIv5_AP_t *ap); -void adiv5_dp_write_ap(ADIv5_DP_t *dp, uint8_t addr, uint32_t value); -uint32_t adiv5_dp_read_ap(ADIv5_DP_t *dp, uint8_t addr); - uint32_t adiv5_ap_mem_read(ADIv5_AP_t *ap, uint32_t addr); void adiv5_ap_mem_write(ADIv5_AP_t *ap, uint32_t addr, uint32_t value); uint16_t adiv5_ap_mem_read_halfword(ADIv5_AP_t *ap, uint32_t addr); @@ -174,8 +173,8 @@ void adiv5_ap_mem_write_halfword(ADIv5_AP_t *ap, uint32_t addr, uint16_t value); uint8_t adiv5_ap_mem_read_byte(ADIv5_AP_t *ap, uint32_t addr); void adiv5_ap_mem_write_byte(ADIv5_AP_t *ap, uint32_t addr, uint8_t value); -void adiv5_ap_write(ADIv5_AP_t *ap, uint8_t addr, uint32_t value); -uint32_t adiv5_ap_read(ADIv5_AP_t *ap, uint8_t addr); +void adiv5_ap_write(ADIv5_AP_t *ap, uint16_t addr, uint32_t value); +uint32_t adiv5_ap_read(ADIv5_AP_t *ap, uint16_t addr); void adiv5_jtag_dp_handler(jtag_dev_t *dev); int adiv5_swdp_scan(void); diff --git a/src/lmi.c b/src/lmi.c index 0f16db4..9359458 100644 --- a/src/lmi.c +++ b/src/lmi.c @@ -131,17 +131,18 @@ int lmi_flash_erase(struct target_s *target, uint32_t addr, size_t len) adiv5_ap_write(ap, 0x00, 0xA2000052); /* select Flash Control */ - adiv5_dp_low_access(ap->dp, 1, 0, 0x04, 0x400FD000); + adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, 0x04, 0x400FD000); while(len) { /* write address to FMA */ - adiv5_ap_write(ap, 0x10, addr); /* Required to switch banks */ + adiv5_ap_write(ap, ADIV5_AP_DB(0), addr); /* Required to switch banks */ /* set ERASE bit in FMC */ - adiv5_dp_low_access(ap->dp, 1, 0, 0x08, 0xA4420002); + adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_DB(2), 0xA4420002); /* Read FMC to poll for ERASE bit */ - adiv5_dp_low_access(ap->dp, 1, 1, 0x08, 0); + adiv5_dp_low_access(ap->dp, ADIV5_LOW_READ, ADIV5_AP_DB(2), 0); do { - tmp = adiv5_dp_low_access(ap->dp, 1, 1, 0x08, 0); + tmp = adiv5_dp_low_access(ap->dp, ADIV5_LOW_READ, + ADIV5_AP_DB(2), 0); } while (tmp & 2); len -= 0x400; diff --git a/src/samd.c b/src/samd.c index 6f73956..2719763 100644 --- a/src/samd.c +++ b/src/samd.c @@ -553,7 +553,7 @@ static int samd_flash_write(struct target_s *target, uint32_t dest, /* Partial, manual page write */ for (; addr <= MINIMUM(end, end_of_this_page); addr += 4, i++) { - adiv5_dp_write_ap(ap->dp, ADIV5_AP_DRW, data[i]); + adiv5_dp_write(ap->dp, ADIV5_AP_DRW, data[i]); } /* Unlock */ @@ -578,7 +578,7 @@ static int samd_flash_write(struct target_s *target, uint32_t dest, /* Full, automatic page write */ for (; addr < page + SAMD_PAGE_SIZE; addr += 4, i++) { - adiv5_dp_write_ap(ap->dp, ADIV5_AP_DRW, data[i]); + adiv5_dp_write(ap->dp, ADIV5_AP_DRW, data[i]); } } -- cgit v1.2.3 From ee3af96a736139b71678a0e590865f9ffafc2f35 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sun, 15 Mar 2015 14:31:57 -0700 Subject: Consolidate target_mem_read* and target_mem_write* methods. There are now only mem_read and mem_write, that must handle all alignments. These methods return void, errors must be checked with target_check_error.--- src/adiv5.c | 224 ++++++++++++++++++--------------------------------- src/arm7tdmi.c | 8 +- src/cortexm.c | 9 +-- src/crc32.c | 9 +-- src/gdb_main.c | 19 +---- src/include/target.h | 39 ++------- src/lmi.c | 4 +- src/lpc11xx.c | 4 +- src/lpc43xx.c | 24 +++--- src/nrf51.c | 4 +- src/sam3x.c | 4 +- src/stm32f1.c | 4 +- src/stm32f4.c | 4 +- src/stm32l0.c | 27 +++---- src/stm32l1.c | 6 +- 15 files changed, 137 insertions(+), 252 deletions(-) (limited to 'src') diff --git a/src/adiv5.c b/src/adiv5.c index aee8471..8f99a9d 100644 --- a/src/adiv5.c +++ b/src/adiv5.c @@ -1,7 +1,7 @@ /* * This file is part of the Black Magic Debug project. * - * Copyright (C) 2011 Black Sphere Technologies Ltd. + * Copyright (C) 2015 Black Sphere Technologies Ltd. * Written by Gareth McMullin * * This program is free software: you can redistribute it and/or modify @@ -39,12 +39,10 @@ static const char adiv5_driver_str[] = "ARM ADIv5 MEM-AP"; static int ap_check_error(struct target_s *target); -static int ap_mem_read_words(struct target_s *target, uint32_t *dest, uint32_t src, int len); -static int ap_mem_write_words(struct target_s *target, uint32_t dest, const uint32_t *src, int len); -static int ap_mem_read_halfwords(struct target_s *target, uint16_t *dest, uint32_t src, int len); -static int ap_mem_write_halfwords(struct target_s *target, uint32_t dest, const uint16_t *src, int len); -static int ap_mem_read_bytes(struct target_s *target, uint8_t *dest, uint32_t src, int len); -static int ap_mem_write_bytes(struct target_s *target, uint32_t dest, const uint8_t *src, int len); +static void ap_mem_read(struct target_s *target, void *dest, uint32_t src, + size_t len); +static void ap_mem_write(struct target_s *target, uint32_t dest, + const void *src, size_t len); void adiv5_dp_ref(ADIv5_DP_t *dp) { @@ -147,12 +145,8 @@ void adiv5_dp_init(ADIv5_DP_t *dp) t->driver = adiv5_driver_str; t->check_error = ap_check_error; - t->mem_read_words = ap_mem_read_words; - t->mem_write_words = ap_mem_write_words; - t->mem_read_halfwords = ap_mem_read_halfwords; - t->mem_write_halfwords = ap_mem_write_halfwords; - t->mem_read_bytes = ap_mem_read_bytes; - t->mem_write_bytes = ap_mem_write_bytes; + t->mem_read = ap_mem_read; + t->mem_write = ap_mem_write; /* The rest sould only be added after checking ROM table */ cortexm_probe(t); @@ -167,88 +161,69 @@ ap_check_error(struct target_s *target) return adiv5_dp_error(ap->dp); } -static int -ap_mem_read_words(struct target_s *target, uint32_t *dest, uint32_t src, int len) +enum align { + ALIGN_BYTE = 0, + ALIGN_HALFWORD = 1, + ALIGN_WORD = 2 +}; +#define ALIGNOF(x) (((x) & 3) == 0 ? ALIGN_WORD : \ + (((x) & 1) == 0 ? ALIGN_HALFWORD : ALIGN_BYTE)) +#undef MIN +#define MIN(x, y) (((x) < (y)) ? (x) : (y)) + +/* Program the CSW and TAR for sequencial access at a given width */ +static void ap_mem_access_setup(ADIv5_AP_t *ap, uint32_t addr, enum align align) { - ADIv5_AP_t *ap = adiv5_target_ap(target); - uint32_t osrc = src; - - len >>= 2; - - adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw | - ADIV5_AP_CSW_SIZE_WORD | ADIV5_AP_CSW_ADDRINC_SINGLE); - adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_TAR, src); - adiv5_dp_low_access(ap->dp, ADIV5_LOW_READ, ADIV5_AP_DRW, 0); - while(--len) { - *dest++ = adiv5_dp_low_access(ap->dp, - ADIV5_LOW_READ, ADIV5_AP_DRW, 0); - src += 4; - /* Check for 10 bit address overflow */ - if ((src ^ osrc) & 0xfffffc00) { - osrc = src; - adiv5_dp_low_access(ap->dp, - ADIV5_LOW_WRITE, ADIV5_AP_TAR, src); - adiv5_dp_low_access(ap->dp, - ADIV5_LOW_READ, ADIV5_AP_DRW, 0); - } - + uint32_t csw = ap->csw | ADIV5_AP_CSW_ADDRINC_SINGLE; + + switch (align) { + case ALIGN_BYTE: + csw |= ADIV5_AP_CSW_SIZE_BYTE; + break; + case ALIGN_HALFWORD: + csw |= ADIV5_AP_CSW_SIZE_HALFWORD; + break; + case ALIGN_WORD: + csw |= ADIV5_AP_CSW_SIZE_WORD; + break; } - *dest++ = adiv5_dp_low_access(ap->dp, ADIV5_LOW_READ, - ADIV5_DP_RDBUFF, 0); - - return 0; + adiv5_ap_write(ap, ADIV5_AP_CSW, csw); + adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_TAR, addr); } -static int -ap_mem_read_halfwords(struct target_s *target, uint16_t *dest, uint32_t src, int len) +/* Extract read data from data lane based on align and src address */ +static void * extract(void *dest, uint32_t src, uint32_t val, enum align align) { - ADIv5_AP_t *ap = adiv5_target_ap(target); - uint32_t tmp; - uint32_t osrc = src; - - len >>= 1; - - adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw | - ADIV5_AP_CSW_SIZE_HALFWORD | ADIV5_AP_CSW_ADDRINC_SINGLE); - adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_TAR, src); - adiv5_dp_low_access(ap->dp, ADIV5_LOW_READ, ADIV5_AP_DRW, 0); - while(--len) { - tmp = adiv5_dp_low_access(ap->dp, ADIV5_LOW_READ, - ADIV5_AP_DRW, 0); - *dest++ = (tmp >> ((src & 0x2) << 3) & 0xFFFF); - - src += 2; - /* Check for 10 bit address overflow */ - if ((src ^ osrc) & 0xfffffc00) { - osrc = src; - adiv5_dp_low_access(ap->dp, - ADIV5_LOW_WRITE, ADIV5_AP_TAR, src); - adiv5_dp_low_access(ap->dp, - ADIV5_LOW_READ, ADIV5_AP_DRW, 0); - } + switch (align) { + case ALIGN_BYTE: + *(uint8_t *)dest = (val >> ((src & 0x3) << 3) & 0xFF); + break; + case ALIGN_HALFWORD: + *(uint16_t *)dest = (val >> ((src & 0x2) << 3) & 0xFFFF); + break; + case ALIGN_WORD: + *(uint32_t *)dest = val; + break; } - tmp = adiv5_dp_low_access(ap->dp, ADIV5_LOW_READ, ADIV5_DP_RDBUFF, 0); - *dest++ = (tmp >> ((src & 0x2) << 3) & 0xFFFF); - - return 0; + return (uint8_t *)dest + (1 << align); } -static int -ap_mem_read_bytes(struct target_s *target, uint8_t *dest, uint32_t src, int len) +static void +ap_mem_read(struct target_s *target, void *dest, uint32_t src, size_t len) { ADIv5_AP_t *ap = adiv5_target_ap(target); uint32_t tmp; uint32_t osrc = src; + enum align align = MIN(ALIGNOF(src), ALIGNOF(len)); - adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw | - ADIV5_AP_CSW_SIZE_BYTE | ADIV5_AP_CSW_ADDRINC_SINGLE); - adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_TAR, src); + len >>= align; + ap_mem_access_setup(ap, src, align); adiv5_dp_low_access(ap->dp, ADIV5_LOW_READ, ADIV5_AP_DRW, 0); - while(--len) { + while (--len) { tmp = adiv5_dp_low_access(ap->dp, ADIV5_LOW_READ, ADIV5_AP_DRW, 0); - *dest++ = (tmp >> ((src & 0x3) << 3) & 0xFF); + dest = extract(dest, src, tmp, align); - src++; + src += (1 << align); /* Check for 10 bit address overflow */ if ((src ^ osrc) & 0xfffffc00) { osrc = src; @@ -259,77 +234,35 @@ ap_mem_read_bytes(struct target_s *target, uint8_t *dest, uint32_t src, int len) } } tmp = adiv5_dp_low_access(ap->dp, ADIV5_LOW_READ, ADIV5_DP_RDBUFF, 0); - *dest++ = (tmp >> ((src++ & 0x3) << 3) & 0xFF); - - return 0; + extract(dest, src, tmp, align); } - -static int -ap_mem_write_words(struct target_s *target, uint32_t dest, const uint32_t *src, int len) -{ - ADIv5_AP_t *ap = adiv5_target_ap(target); - uint32_t odest = dest; - - len >>= 2; - - adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw | - ADIV5_AP_CSW_SIZE_WORD | ADIV5_AP_CSW_ADDRINC_SINGLE); - adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_TAR, dest); - while(len--) { - adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, - ADIV5_AP_DRW, *src++); - dest += 4; - /* Check for 10 bit address overflow */ - if ((dest ^ odest) & 0xfffffc00) { - odest = dest; - adiv5_dp_low_access(ap->dp, - ADIV5_LOW_WRITE, ADIV5_AP_TAR, dest); - } - } - - return 0; -} - -static int -ap_mem_write_halfwords(struct target_s *target, uint32_t dest, const uint16_t *src, int len) +static void +ap_mem_write(struct target_s *target, uint32_t dest, const void *src, size_t len) { ADIv5_AP_t *ap = adiv5_target_ap(target); uint32_t odest = dest; - - len >>= 1; - - adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw | - ADIV5_AP_CSW_SIZE_HALFWORD | ADIV5_AP_CSW_ADDRINC_SINGLE); - adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_TAR, dest); - while(len--) { - uint32_t tmp = (uint32_t)*src++ << ((dest & 2) << 3); - adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, - ADIV5_AP_DRW, tmp); - dest += 2; - /* Check for 10 bit address overflow */ - if ((dest ^ odest) & 0xfffffc00) { - odest = dest; - adiv5_dp_low_access(ap->dp, - ADIV5_LOW_WRITE, ADIV5_AP_TAR, dest); + enum align align = MIN(ALIGNOF(dest), ALIGNOF(len)); + + len >>= align; + ap_mem_access_setup(ap, dest, align); + while (len--) { + uint32_t tmp = 0; + /* Pack data into correct data lane */ + switch (align) { + case ALIGN_BYTE: + tmp = ((uint32_t)*(uint8_t *)src) << ((dest & 3) << 3); + break; + case ALIGN_HALFWORD: + tmp = ((uint32_t)*(uint16_t *)src) << ((dest & 2) << 3); + break; + case ALIGN_WORD: + tmp = *(uint32_t *)src; + break; } - } - return 0; -} - -static int -ap_mem_write_bytes(struct target_s *target, uint32_t dest, const uint8_t *src, int len) -{ - ADIv5_AP_t *ap = adiv5_target_ap(target); - uint32_t odest = dest; - - adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw | - ADIV5_AP_CSW_SIZE_BYTE | ADIV5_AP_CSW_ADDRINC_SINGLE); - adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_TAR, dest); - while(len--) { - uint32_t tmp = (uint32_t)*src++ << ((dest++ & 3) << 3); - adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, - ADIV5_AP_DRW, tmp); + src = (uint8_t *)src + (1 << align); + dest += (1 << align); + adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_DRW, tmp); /* Check for 10 bit address overflow */ if ((dest ^ odest) & 0xfffffc00) { @@ -338,11 +271,8 @@ ap_mem_write_bytes(struct target_s *target, uint32_t dest, const uint8_t *src, i ADIV5_LOW_WRITE, ADIV5_AP_TAR, dest); } } - return 0; } - - uint32_t adiv5_ap_mem_read(ADIv5_AP_t *ap, uint32_t addr) { adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw | diff --git a/src/arm7tdmi.c b/src/arm7tdmi.c index 1721787..afd623c 100644 --- a/src/arm7tdmi.c +++ b/src/arm7tdmi.c @@ -123,12 +123,8 @@ void arm7tdmi_jtag_handler(jtag_dev_t *dev) t->attach = arm7_attach; t->detach = (void *)do_nothing; t->check_error = (void *)do_nothing; - t->mem_read_words = (void *)do_nothing; - t->mem_write_words = (void *)do_nothing; - t->mem_read_halfwords = (void *)do_nothing; - t->mem_write_halfwords = (void *)do_nothing; - t->mem_read_bytes = (void *)do_nothing; - t->mem_write_bytes = (void *)do_nothing; + t->mem_read = (void *)do_nothing; + t->mem_write = (void *)do_nothing; t->regs_size = 16 * sizeof(uint32_t); t->regs_read = (void *)arm7_regs_read; t->regs_write = (void *)arm7_regs_write; diff --git a/src/cortexm.c b/src/cortexm.c index da48f8e..fcc6a9d 100644 --- a/src/cortexm.c +++ b/src/cortexm.c @@ -502,7 +502,7 @@ cortexm_halt_wait(struct target_s *target) * call. */ uint32_t pc = cortexm_pc_read(target); uint16_t bkpt_instr; - target_mem_read_bytes(target, (uint8_t *)&bkpt_instr, pc, 2); + target_mem_read(target, &bkpt_instr, pc, 2); if (bkpt_instr == 0xBEAB) { int n = cortexm_hostio_request(target); if (n > 0) { @@ -571,7 +571,7 @@ static int cortexm_fault_unwind(struct target_s *target) bool fpca = !(retcode & (1<<4)); /* Read stack for pre-exception registers */ uint32_t sp = spsel ? regs[REG_PSP] : regs[REG_MSP]; - target_mem_read_words(target, stack, sp, sizeof(stack)); + target_mem_read(target, stack, sp, sizeof(stack)); if (target_check_error(target)) return 0; regs[REG_LR] = stack[5]; /* restore LR to pre-exception state */ @@ -840,7 +840,7 @@ static int cortexm_hostio_request(target *t) uint32_t params[4]; target_regs_read(t, arm_regs); - target_mem_read_words(t, params, arm_regs[1], sizeof(params)); + target_mem_read(t, params, arm_regs[1], sizeof(params)); priv->syscall = arm_regs[0]; DEBUG("syscall 0x%x (%x %x %x %x)\n", priv->syscall, @@ -860,8 +860,7 @@ static int cortexm_hostio_request(target *t) uint32_t pflag = flags[params[1] >> 1]; char filename[4]; - target_mem_read_bytes(t, (uint8_t *)filename, - params[0], sizeof(filename)); + target_mem_read(t, filename, params[0], sizeof(filename)); /* handle requests for console i/o */ if (!strcmp(filename, ":tt")) { if (pflag == FILEIO_O_RDONLY) diff --git a/src/crc32.c b/src/crc32.c index 42d1d48..fffc04c 100644 --- a/src/crc32.c +++ b/src/crc32.c @@ -100,8 +100,7 @@ uint32_t generic_crc32(struct target_s *target, uint32_t base, int len) uint8_t byte; while (len--) { - if (target_mem_read_bytes(target, &byte, base, 1) != 0) - return -1; + target_mem_read(target, &byte, base, 1); crc = crc32_calc(crc, byte); base++; @@ -119,8 +118,7 @@ uint32_t generic_crc32(struct target_s *target, uint32_t base, int len) CRC_CR |= CRC_CR_RESET; while (len > 3) { - if (target_mem_read_words(target, &data, base, 4) != 0) - return -1; + target_mem_read(target, &data, base, 4); CRC_DR = __builtin_bswap32(data); base += 4; @@ -130,8 +128,7 @@ uint32_t generic_crc32(struct target_s *target, uint32_t base, int len) crc = CRC_DR; while (len--) { - if (target_mem_read_bytes(target, (uint8_t *)&data, base++, 1) != 0) - return -1; + target_mem_read(target, &data, base++, 1); crc ^= data << 24; for (i = 0; i < 8; i++) { diff --git a/src/gdb_main.c b/src/gdb_main.c index ab4fc8a..7bb788b 100644 --- a/src/gdb_main.c +++ b/src/gdb_main.c @@ -88,12 +88,7 @@ gdb_main(void) sscanf(pbuf, "m%" SCNx32 ",%" SCNx32, &addr, &len); DEBUG("m packet: addr = %" PRIx32 ", len = %" PRIx32 "\n", addr, len); uint8_t mem[len]; - if(((addr & 3) == 0) && ((len & 3) == 0)) - target_mem_read_words(cur_target, (void*)mem, addr, len); - else if(((addr & 1) == 0) && ((len & 1) == 0)) - target_mem_read_halfwords(cur_target, (void*)mem, addr, len); - else - target_mem_read_bytes(cur_target, (void*)mem, addr, len); + target_mem_read(cur_target, mem, addr, len); if(target_check_error(cur_target)) gdb_putpacketz("E01"); else @@ -116,12 +111,7 @@ gdb_main(void) DEBUG("M packet: addr = %" PRIx32 ", len = %" PRIx32 "\n", addr, len); uint8_t mem[len]; unhexify(mem, pbuf + hex, len); - if(((addr & 3) == 0) && ((len & 3) == 0)) - target_mem_write_words(cur_target, addr, (void*)mem, len); - else if(((addr & 1) == 0) && ((len & 1) == 0)) - target_mem_write_halfwords(cur_target, addr, (void*)mem, len); - else - target_mem_write_bytes(cur_target, addr, (void*)mem, len); + target_mem_write(cur_target, addr, mem, len); if(target_check_error(cur_target)) gdb_putpacketz("E01"); else @@ -244,10 +234,7 @@ gdb_main(void) ERROR_IF_NO_TARGET(); sscanf(pbuf, "X%" SCNx32 ",%" SCNx32 ":%n", &addr, &len, &bin); DEBUG("X packet: addr = %" PRIx32 ", len = %" PRIx32 "\n", addr, len); - if(((addr & 3) == 0) && ((len & 3) == 0)) - target_mem_write_words(cur_target, addr, (void*)pbuf+bin, len); - else - target_mem_write_bytes(cur_target, addr, (void*)pbuf+bin, len); + target_mem_write(cur_target, addr, pbuf+bin, len); if(target_check_error(cur_target)) gdb_putpacketz("E01"); else diff --git a/src/include/target.h b/src/include/target.h index 5db79a7..b48e054 100644 --- a/src/include/target.h +++ b/src/include/target.h @@ -48,24 +48,11 @@ target *target_attach(target *t, target_destroy_callback destroy_cb); (target)->check_error(target) /* Memory access functions */ -#define target_mem_read_words(target, dest, src, len) \ - (target)->mem_read_words((target), (dest), (src), (len)) - -#define target_mem_write_words(target, dest, src, len) \ - (target)->mem_write_words((target), (dest), (src), (len)) - -#define target_mem_read_halfwords(target, dest, src, len) \ - (target)->mem_read_halfwords((target), (dest), (src), (len)) - -#define target_mem_write_halfwords(target, dest, src, len) \ - (target)->mem_write_halfwords((target), (dest), (src), (len)) - -#define target_mem_read_bytes(target, dest, src, len) \ - (target)->mem_read_bytes((target), (dest), (src), (len)) - -#define target_mem_write_bytes(target, dest, src, len) \ - (target)->mem_write_bytes((target), (dest), (src), (len)) +#define target_mem_read(target, dest, src, len) \ + (target)->mem_read((target), (dest), (src), (len)) +#define target_mem_write(target, dest, src, len) \ + (target)->mem_write((target), (dest), (src), (len)) /* Register access functions */ #define target_regs_read(target, data) \ @@ -135,20 +122,10 @@ struct target_s { int (*check_error)(struct target_s *target); /* Memory access functions */ - int (*mem_read_words)(struct target_s *target, uint32_t *dest, uint32_t src, - int len); - int (*mem_write_words)(struct target_s *target, uint32_t dest, - const uint32_t *src, int len); - - int (*mem_read_halfwords)(struct target_s *target, uint16_t *dest, uint32_t src, - int len); - int (*mem_write_halfwords)(struct target_s *target, uint32_t dest, - const uint16_t *src, int len); - - int (*mem_read_bytes)(struct target_s *target, uint8_t *dest, uint32_t src, - int len); - int (*mem_write_bytes)(struct target_s *target, uint32_t dest, - const uint8_t *src, int len); + void (*mem_read)(struct target_s *target, void *dest, uint32_t src, + size_t len); + void (*mem_write)(struct target_s *target, uint32_t dest, + const void *src, size_t len); /* Register access functions */ int regs_size; diff --git a/src/lmi.c b/src/lmi.c index 9359458..8c5e143 100644 --- a/src/lmi.c +++ b/src/lmi.c @@ -159,9 +159,9 @@ int lmi_flash_write(struct target_s *target, uint32_t dest, data[1] = len >> 2; memcpy(&data[2], src, len); DEBUG("Sending stub\n"); - target_mem_write_words(target, 0x20000000, (void*)lmi_flash_write_stub, 0x30); + target_mem_write(target, 0x20000000, (void*)lmi_flash_write_stub, 0x30); DEBUG("Sending data\n"); - target_mem_write_words(target, 0x20000030, data, len + 8); + target_mem_write(target, 0x20000030, data, len + 8); DEBUG("Running stub\n"); target_pc_write(target, 0x20000000); target_halt_resume(target, 0); diff --git a/src/lpc11xx.c b/src/lpc11xx.c index b6309c2..eca3daf 100644 --- a/src/lpc11xx.c +++ b/src/lpc11xx.c @@ -170,7 +170,7 @@ lpc11x_iap_call(struct target_s *target, struct flash_param *param, unsigned par /* fill out the remainder of the parameters and copy the structure to RAM */ param->opcodes[0] = 0xbe00; param->opcodes[1] = 0x0000; - target_mem_write_words(target, IAP_RAM_BASE, (void *)param, param_len); + target_mem_write(target, IAP_RAM_BASE, param, param_len); /* set up for the call to the IAP ROM */ target_regs_read(target, regs); @@ -191,7 +191,7 @@ lpc11x_iap_call(struct target_s *target, struct flash_param *param, unsigned par while (!target_halt_wait(target)); /* copy back just the parameters structure */ - target_mem_read_words(target, (void *)param, IAP_RAM_BASE, sizeof(struct flash_param)); + target_mem_read(target, param, IAP_RAM_BASE, sizeof(struct flash_param)); } static int flash_page_size(struct target_s *target) diff --git a/src/lpc43xx.c b/src/lpc43xx.c index eca7338..0ae9418 100644 --- a/src/lpc43xx.c +++ b/src/lpc43xx.c @@ -224,7 +224,7 @@ static bool lpc43xx_cmd_reset(target *target, int argc, const char *argv[]) static const uint32_t reset_val = 0x05FA0004; /* System reset on target */ - target_mem_write_words(target, AIRCR, &reset_val, sizeof(reset_val)); + target_mem_write(target, AIRCR, &reset_val, sizeof(reset_val)); return true; } @@ -340,12 +340,12 @@ static void lpc43xx_iap_call(struct target_s *target, struct flash_param *param, /* Pet WDT before each IAP call, if it is on */ lpc43xx_wdt_pet(target); - target_mem_read_words(target, &iap_entry, IAP_ENTRYPOINT_LOCATION, sizeof(iap_entry)); + target_mem_read(target, &iap_entry, IAP_ENTRYPOINT_LOCATION, sizeof(iap_entry)); /* fill out the remainder of the parameters and copy the structure to RAM */ param->opcode = ARM_THUMB_BREAKPOINT; /* breakpoint */ param->pad0 = 0x0000; /* pad */ - target_mem_write_words(target, IAP_RAM_BASE, (void *)param, param_len); + target_mem_write(target, IAP_RAM_BASE, param, param_len); /* set up for the call to the IAP ROM */ target_regs_read(target, regs); @@ -362,7 +362,7 @@ static void lpc43xx_iap_call(struct target_s *target, struct flash_param *param, while (!target_halt_wait(target)); /* copy back just the parameters structure */ - target_mem_read_words(target, (void *)param, IAP_RAM_BASE, sizeof(struct flash_param)); + target_mem_read(target, param, IAP_RAM_BASE, sizeof(struct flash_param)); } static int lpc43xx_flash_prepare(struct target_s *target, uint32_t addr, int len) @@ -429,7 +429,7 @@ static int lpc43xx_flash_erase(struct target_s *target, uint32_t addr, size_t le static void lpc43xx_set_internal_clock(struct target_s *target) { const uint32_t val2 = (1 << 11) | (1 << 24); - target_mem_write_words(target, 0x40050000 + 0x06C, &val2, sizeof(val2)); + target_mem_write(target, 0x40050000 + 0x06C, &val2, sizeof(val2)); } static int lpc43xx_flash_write(struct target_s *target, @@ -477,9 +477,9 @@ static int lpc43xx_flash_write(struct target_s *target, } /* copy buffer into target memory */ - target_mem_write_words(target, + target_mem_write(target, IAP_RAM_BASE + offsetof(struct flash_program, data), - (uint32_t*)flash_pgm.data, sizeof(flash_pgm.data)); + flash_pgm.data, sizeof(flash_pgm.data)); /* set the destination address and program */ flash_pgm.p.command = IAP_CMD_PROGRAM; @@ -541,7 +541,7 @@ static void lpc43xx_wdt_set_period(struct target_s *target) { uint32_t wdt_mode = 0; /* Check if WDT is on */ - target_mem_read_words(target, &wdt_mode, LPC43XX_WDT_MODE, sizeof(wdt_mode)); + target_mem_read(target, &wdt_mode, LPC43XX_WDT_MODE, sizeof(wdt_mode)); /* If WDT on, we can't disable it, but we may be able to set a long period */ if (wdt_mode && !(wdt_mode & LPC43XX_WDT_PROTECT)) @@ -549,7 +549,7 @@ static void lpc43xx_wdt_set_period(struct target_s *target) const uint32_t wdt_period = LPC43XX_WDT_PERIOD_MAX; - target_mem_write_words(target, LPC43XX_WDT_CNT, &wdt_period, sizeof(wdt_period)); + target_mem_write(target, LPC43XX_WDT_CNT, &wdt_period, sizeof(wdt_period)); } } @@ -557,7 +557,7 @@ static void lpc43xx_wdt_pet(struct target_s *target) { uint32_t wdt_mode = 0; /* Check if WDT is on */ - target_mem_read_words(target, &wdt_mode, LPC43XX_WDT_MODE, sizeof(wdt_mode)); + target_mem_read(target, &wdt_mode, LPC43XX_WDT_MODE, sizeof(wdt_mode)); /* If WDT on, pet */ if (wdt_mode) @@ -566,7 +566,7 @@ static void lpc43xx_wdt_pet(struct target_s *target) const uint32_t feed2 = 0x55;; - target_mem_write_words(target, LPC43XX_WDT_FEED, &feed1, sizeof(feed1)); - target_mem_write_words(target, LPC43XX_WDT_FEED, &feed2, sizeof(feed2)); + target_mem_write(target, LPC43XX_WDT_FEED, &feed1, sizeof(feed1)); + target_mem_write(target, LPC43XX_WDT_FEED, &feed2, sizeof(feed2)); } } diff --git a/src/nrf51.c b/src/nrf51.c index 55c9a58..a4396bb 100644 --- a/src/nrf51.c +++ b/src/nrf51.c @@ -233,8 +233,8 @@ static int nrf51_flash_write(struct target_s *target, uint32_t dest, return -1; /* Write stub and data to target ram and set PC */ - target_mem_write_words(target, 0x20000000, (void*)nrf51_flash_write_stub, 0x28); - target_mem_write_words(target, 0x20000028, data, len + 8); + target_mem_write(target, 0x20000000, nrf51_flash_write_stub, 0x28); + target_mem_write(target, 0x20000028, data, len + 8); target_pc_write(target, 0x20000000); if(target_check_error(target)) return -1; diff --git a/src/sam3x.c b/src/sam3x.c index 7141cb5..211fc92 100644 --- a/src/sam3x.c +++ b/src/sam3x.c @@ -326,7 +326,7 @@ static int sam3x_flash_erase(struct target_s *target, uint32_t addr, size_t len) memset(buf, 0xff, sizeof(buf)); /* Only do this once, since it doesn't change. */ - target_mem_write_words(target, addr, (void*)buf, SAM3_PAGE_SIZE); + target_mem_write(target, addr, buf, SAM3_PAGE_SIZE); while (len) { if(sam3x_flash_cmd(target, base, EEFC_FCR_FCMD_EWP, chunk)) @@ -384,7 +384,7 @@ static int sam3x_flash_write(struct target_s *target, uint32_t dest, src += page_size; } - target_mem_write_words(target, dest, (void*)buf, page_size); + target_mem_write(target, dest, buf, page_size); if(sam3x_flash_cmd(target, base, EEFC_FCR_FCMD_WP, chunk)) return -1; } diff --git a/src/stm32f1.c b/src/stm32f1.c index 405bc1a..ca55fad 100644 --- a/src/stm32f1.c +++ b/src/stm32f1.c @@ -293,8 +293,8 @@ static int stm32f1_flash_write(struct target_s *target, uint32_t dest, memcpy((uint8_t *)&data[2] + offset, src, len); /* Write stub and data to target ram and set PC */ - target_mem_write_words(target, 0x20000000, (void*)stm32f1_flash_write_stub, 0x2C); - target_mem_write_words(target, 0x2000002C, data, sizeof(data)); + target_mem_write(target, 0x20000000, stm32f1_flash_write_stub, 0x2C); + target_mem_write(target, 0x2000002C, data, sizeof(data)); target_pc_write(target, 0x20000000); if(target_check_error(target)) return -1; diff --git a/src/stm32f4.c b/src/stm32f4.c index fac097a..58d1328 100644 --- a/src/stm32f4.c +++ b/src/stm32f4.c @@ -253,8 +253,8 @@ static int stm32f4_flash_write(struct target_s *target, uint32_t dest, memcpy((uint8_t *)&data[2] + offset, src, len); /* Write stub and data to target ram and set PC */ - target_mem_write_words(target, 0x20000000, (void*)stm32f4_flash_write_stub, 0x30); - target_mem_write_words(target, 0x20000030, data, sizeof(data)); + target_mem_write(target, 0x20000000, stm32f4_flash_write_stub, 0x30); + target_mem_write(target, 0x20000030, data, sizeof(data)); target_pc_write(target, 0x20000000); if(target_check_error(target)) return -1; diff --git a/src/stm32l0.c b/src/stm32l0.c index 2e30035..028f2a1 100644 --- a/src/stm32l0.c +++ b/src/stm32l0.c @@ -380,17 +380,17 @@ static int stm32lx_nvm_prog_erase_stubbed(struct target_s* target, info.page_size = stm32lx_nvm_prog_page_size(target); /* Load the stub */ - target_mem_write_words(target, STM32Lx_STUB_PHYS, - (void*) &stm32l0_nvm_prog_erase_stub[0], - sizeof(stm32l0_nvm_prog_erase_stub)); + target_mem_write(target, STM32Lx_STUB_PHYS, + &stm32l0_nvm_prog_erase_stub[0], + sizeof(stm32l0_nvm_prog_erase_stub)); /* Setup parameters */ info.destination = addr; info.size = size; /* Copy parameters */ - target_mem_write_words(target, STM32Lx_STUB_INFO_PHYS, - (void*) &info, sizeof(info)); + target_mem_write(target, STM32Lx_STUB_INFO_PHYS, + &info, sizeof(info)); /* Execute stub */ target_pc_write(target, STM32Lx_STUB_PHYS); @@ -434,9 +434,9 @@ static int stm32lx_nvm_prog_write_stubbed(struct target_s* target, info.page_size = page_size; /* Load the stub */ - target_mem_write_words(target, STM32Lx_STUB_PHYS, - (void*) &stm32l0_nvm_prog_write_stub[0], - sizeof(stm32l0_nvm_prog_write_stub)); + target_mem_write(target, STM32Lx_STUB_PHYS, + &stm32l0_nvm_prog_write_stub[0], + sizeof(stm32l0_nvm_prog_write_stub)); while (size > 0) { @@ -458,8 +458,7 @@ static int stm32lx_nvm_prog_write_stubbed(struct target_s* target, info.size = cb; /* Copy data to write to flash */ - target_mem_write_words(target, info.source, (void*) source, - info.size); + target_mem_write(target, info.source, source, info.size); /* Move pointers early */ destination += cb; @@ -467,8 +466,8 @@ static int stm32lx_nvm_prog_write_stubbed(struct target_s* target, size -= cb; /* Copy parameters */ - target_mem_write_words(target, STM32Lx_STUB_INFO_PHYS, - (void*) &info, sizeof(info)); + target_mem_write(target, STM32Lx_STUB_INFO_PHYS, + &info, sizeof(info)); /* Execute stub */ target_pc_write(target, STM32Lx_STUB_PHYS); @@ -661,7 +660,7 @@ static int stm32lx_nvm_prog_write(struct target_s* target, c = size; size -= c; - target_mem_write_words(target, destination, source, c); + target_mem_write(target, destination, source, c); source += c/4; destination += c; } @@ -673,7 +672,7 @@ static int stm32lx_nvm_prog_write(struct target_s* target, size_t c = size & ~(half_page_size - 1); size -= c; - target_mem_write_words(target, destination, source, c); + target_mem_write(target, destination, source, c); source += c/4; destination += c; } diff --git a/src/stm32l1.c b/src/stm32l1.c index 86298e5..c72cccd 100644 --- a/src/stm32l1.c +++ b/src/stm32l1.c @@ -176,7 +176,7 @@ static int stm32l1_flash_write(struct target_s *target, uint32_t dest, if(xlen > len) xlen = len & ~3; - target_mem_write_words(target, dest, (uint32_t*)src, xlen); + target_mem_write(target, dest, src, xlen); src += xlen; dest += xlen; len -= xlen; @@ -192,7 +192,7 @@ static int stm32l1_flash_write(struct target_s *target, uint32_t dest, if(target_check_error(target)) return -1; - target_mem_write_words(target, dest, (uint32_t*)src, len & ~127); + target_mem_write(target, dest, src, len & ~127); src += len & ~127; dest += len & ~127; len -= len & ~127; @@ -208,7 +208,7 @@ static int stm32l1_flash_write(struct target_s *target, uint32_t dest, /* Handle non-full page at the end */ if(len >= 4) { - target_mem_write_words(target, dest, (uint32_t*)src, len & ~3); + target_mem_write(target, dest, src, len & ~3); src += len & ~3; dest += len & ~3; len -= len & ~3; -- cgit v1.2.3 From 2bf54f9a72bd9ee57e668f09075b65486e418216 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sun, 15 Mar 2015 16:02:09 -0700 Subject: Replace adiv5_ap_mem* functions with inline wrappers to target mem*. --- src/adiv5.c | 60 ---------------------- src/cortexm.c | 100 ++++++++++++++++++------------------- src/crc32.c | 6 +-- src/include/adiv5.h | 7 --- src/include/target.h | 38 +++++++++++++- src/kinetis.c | 15 +++--- src/lmi.c | 2 +- src/lpc11xx.c | 2 +- src/lpc43xx.c | 4 +- src/nrf51.c | 60 ++++++++-------------- src/sam3x.c | 49 ++++++++---------- src/samd.c | 134 +++++++++++++++++++++---------------------------- src/stm32f1.c | 73 ++++++++++++--------------- src/stm32f4.c | 56 +++++++++------------ src/stm32l0.c | 138 ++++++++++++++++++++++++--------------------------- src/stm32l1.c | 40 +++++++-------- 16 files changed, 336 insertions(+), 448 deletions(-) (limited to 'src') diff --git a/src/adiv5.c b/src/adiv5.c index 8f99a9d..2179ca6 100644 --- a/src/adiv5.c +++ b/src/adiv5.c @@ -273,66 +273,6 @@ ap_mem_write(struct target_s *target, uint32_t dest, const void *src, size_t len } } -uint32_t adiv5_ap_mem_read(ADIv5_AP_t *ap, uint32_t addr) -{ - adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw | - ADIV5_AP_CSW_SIZE_WORD | ADIV5_AP_CSW_ADDRINC_SINGLE); - adiv5_ap_write(ap, ADIV5_AP_TAR, addr); - return adiv5_ap_read(ap, ADIV5_AP_DRW); -} - -void adiv5_ap_mem_write(ADIv5_AP_t *ap, uint32_t addr, uint32_t value) -{ - adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw | - ADIV5_AP_CSW_SIZE_WORD | ADIV5_AP_CSW_ADDRINC_SINGLE); - adiv5_ap_write(ap, ADIV5_AP_TAR, addr); - adiv5_ap_write(ap, ADIV5_AP_DRW, value); -} - -uint16_t adiv5_ap_mem_read_halfword(ADIv5_AP_t *ap, uint32_t addr) -{ - adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw | - ADIV5_AP_CSW_SIZE_HALFWORD | ADIV5_AP_CSW_ADDRINC_SINGLE); - adiv5_ap_write(ap, ADIV5_AP_TAR, addr); - uint32_t v = adiv5_ap_read(ap, ADIV5_AP_DRW); - if (addr & 2) - return v >> 16; - else - return v & 0xFFFF; -} - -void adiv5_ap_mem_write_halfword(ADIv5_AP_t *ap, uint32_t addr, uint16_t value) -{ - uint32_t v = value; - if (addr & 2) - v <<= 16; - - adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw | - ADIV5_AP_CSW_SIZE_HALFWORD | ADIV5_AP_CSW_ADDRINC_SINGLE); - adiv5_ap_write(ap, ADIV5_AP_TAR, addr); - adiv5_ap_write(ap, ADIV5_AP_DRW, v); -} - -uint8_t adiv5_ap_mem_read_byte(ADIv5_AP_t *ap, uint32_t addr) -{ - adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw | - ADIV5_AP_CSW_SIZE_BYTE | ADIV5_AP_CSW_ADDRINC_SINGLE); - adiv5_ap_write(ap, ADIV5_AP_TAR, addr); - uint32_t v = adiv5_ap_read(ap, ADIV5_AP_DRW); - - return v >> ((addr & 3) * 8); -} - -void adiv5_ap_mem_write_byte(ADIv5_AP_t *ap, uint32_t addr, uint8_t value) -{ - uint32_t v = value << ((addr & 3) * 8); - - adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw | - ADIV5_AP_CSW_SIZE_BYTE | ADIV5_AP_CSW_ADDRINC_SINGLE); - adiv5_ap_write(ap, ADIV5_AP_TAR, addr); - adiv5_ap_write(ap, ADIV5_AP_DRW, v); -} - void adiv5_ap_write(ADIv5_AP_t *ap, uint16_t addr, uint32_t value) { adiv5_dp_write(ap->dp, ADIV5_DP_SELECT, diff --git a/src/cortexm.c b/src/cortexm.c index fcc6a9d..4bfb4d9 100644 --- a/src/cortexm.c +++ b/src/cortexm.c @@ -228,16 +228,16 @@ cortexm_probe(struct target_s *target) target_add_commands(target, cortexm_cmd_list, cortexm_driver_str); /* Probe for FP extension */ - ADIv5_AP_t *ap = adiv5_target_ap(target); - uint32_t cpacr = adiv5_ap_mem_read(ap, CORTEXM_CPACR); + uint32_t cpacr = target_mem_read32(target, CORTEXM_CPACR); cpacr |= 0x00F00000; /* CP10 = 0b11, CP11 = 0b11 */ - adiv5_ap_mem_write(ap, CORTEXM_CPACR, cpacr); - if (adiv5_ap_mem_read(ap, CORTEXM_CPACR) == cpacr) { + target_mem_write32(target, CORTEXM_CPACR, cpacr); + if (target_mem_read32(target, CORTEXM_CPACR) == cpacr) { target->target_options |= TOPT_FLAVOUR_V7MF; target->regs_size += sizeof(regnum_cortex_mf); target->tdesc = tdesc_cortex_mf; } + ADIv5_AP_t *ap = adiv5_target_ap(target); struct cortexm_priv *priv = calloc(1, sizeof(*priv)); ap->priv = priv; ap->priv_free = free; @@ -284,35 +284,35 @@ bool cortexm_attach(struct target_s *target) return false; /* Request halt on reset */ - adiv5_ap_mem_write(ap, CORTEXM_DEMCR, priv->demcr); + target_mem_write32(target, CORTEXM_DEMCR, priv->demcr); /* Reset DFSR flags */ - adiv5_ap_mem_write(ap, CORTEXM_DFSR, CORTEXM_DFSR_RESETALL); + target_mem_write32(target, CORTEXM_DFSR, CORTEXM_DFSR_RESETALL); /* size the break/watchpoint units */ priv->hw_breakpoint_max = CORTEXM_MAX_BREAKPOINTS; - r = adiv5_ap_mem_read(ap, CORTEXM_FPB_CTRL); + r = target_mem_read32(target, CORTEXM_FPB_CTRL); if (((r >> 4) & 0xf) < priv->hw_breakpoint_max) /* only look at NUM_COMP1 */ priv->hw_breakpoint_max = (r >> 4) & 0xf; priv->hw_watchpoint_max = CORTEXM_MAX_WATCHPOINTS; - r = adiv5_ap_mem_read(ap, CORTEXM_DWT_CTRL); + r = target_mem_read32(target, CORTEXM_DWT_CTRL); if ((r >> 28) > priv->hw_watchpoint_max) priv->hw_watchpoint_max = r >> 28; /* Clear any stale breakpoints */ for(i = 0; i < priv->hw_breakpoint_max; i++) { - adiv5_ap_mem_write(ap, CORTEXM_FPB_COMP(i), 0); + target_mem_write32(target, CORTEXM_FPB_COMP(i), 0); priv->hw_breakpoint[i] = 0; } /* Clear any stale watchpoints */ for(i = 0; i < priv->hw_watchpoint_max; i++) { - adiv5_ap_mem_write(ap, CORTEXM_DWT_FUNC(i), 0); + target_mem_write32(target, CORTEXM_DWT_FUNC(i), 0); priv->hw_watchpoint[i].type = 0; } /* Flash Patch Control Register: set ENABLE */ - adiv5_ap_mem_write(ap, CORTEXM_FPB_CTRL, + target_mem_write32(target, CORTEXM_FPB_CTRL, CORTEXM_FPB_CTRL_KEY | CORTEXM_FPB_CTRL_ENABLE); target->set_hw_bp = cortexm_set_hw_bp; target->clear_hw_bp = cortexm_clear_hw_bp; @@ -336,14 +336,14 @@ void cortexm_detach(struct target_s *target) /* Clear any stale breakpoints */ for(i = 0; i < priv->hw_breakpoint_max; i++) - adiv5_ap_mem_write(ap, CORTEXM_FPB_COMP(i), 0); + target_mem_write32(target, CORTEXM_FPB_COMP(i), 0); /* Clear any stale watchpoints */ for(i = 0; i < priv->hw_watchpoint_max; i++) - adiv5_ap_mem_write(ap, CORTEXM_DWT_FUNC(i), 0); + target_mem_write32(target, CORTEXM_DWT_FUNC(i), 0); /* Disable debug */ - adiv5_ap_mem_write(ap, CORTEXM_DHCSR, CORTEXM_DHCSR_DBGKEY); + target_mem_write32(target, CORTEXM_DHCSR, CORTEXM_DHCSR_DBGKEY); } static int @@ -422,10 +422,8 @@ cortexm_regs_write(struct target_s *target, const void *data) static uint32_t cortexm_pc_read(struct target_s *target) { - ADIv5_AP_t *ap = adiv5_target_ap(target); - - adiv5_ap_mem_write(ap, CORTEXM_DCRSR, 0x0F); - return adiv5_ap_mem_read(ap, CORTEXM_DCRDR); + target_mem_write32(target, CORTEXM_DCRSR, 0x0F); + return target_mem_read32(target, CORTEXM_DCRDR); return 0; } @@ -433,10 +431,8 @@ cortexm_pc_read(struct target_s *target) static int cortexm_pc_write(struct target_s *target, const uint32_t val) { - ADIv5_AP_t *ap = adiv5_target_ap(target); - - adiv5_ap_mem_write(ap, CORTEXM_DCRDR, val); - adiv5_ap_mem_write(ap, CORTEXM_DCRSR, CORTEXM_DCRSR_REGWnR | 0x0F); + target_mem_write32(target, CORTEXM_DCRDR, val); + target_mem_write32(target, CORTEXM_DCRSR, CORTEXM_DCRSR_REGWnR | 0x0F); return 0; } @@ -446,26 +442,24 @@ cortexm_pc_write(struct target_s *target, const uint32_t val) static void cortexm_reset(struct target_s *target) { - ADIv5_AP_t *ap = adiv5_target_ap(target); - jtagtap_srst(true); jtagtap_srst(false); /* Read DHCSR here to clear S_RESET_ST bit before reset */ - adiv5_ap_mem_read(ap, CORTEXM_DHCSR); + target_mem_read32(target, CORTEXM_DHCSR); /* Request system reset from NVIC: SRST doesn't work correctly */ /* This could be VECTRESET: 0x05FA0001 (reset only core) * or SYSRESETREQ: 0x05FA0004 (system reset) */ - adiv5_ap_mem_write(ap, CORTEXM_AIRCR, - CORTEXM_AIRCR_VECTKEY | CORTEXM_AIRCR_SYSRESETREQ); + target_mem_write32(target, CORTEXM_AIRCR, + CORTEXM_AIRCR_VECTKEY | CORTEXM_AIRCR_SYSRESETREQ); /* Poll for release from reset */ - while(adiv5_ap_mem_read(ap, CORTEXM_DHCSR) & CORTEXM_DHCSR_S_RESET_ST); + while (target_mem_read32(target, CORTEXM_DHCSR) & CORTEXM_DHCSR_S_RESET_ST); /* Reset DFSR flags */ - adiv5_ap_mem_write(ap, CORTEXM_DFSR, CORTEXM_DFSR_RESETALL); + target_mem_write32(target, CORTEXM_DFSR, CORTEXM_DFSR_RESETALL); } static void @@ -474,8 +468,9 @@ cortexm_halt_request(struct target_s *target) ADIv5_AP_t *ap = adiv5_target_ap(target); ap->dp->allow_timeout = false; - adiv5_ap_mem_write(ap, CORTEXM_DHCSR, - CORTEXM_DHCSR_DBGKEY | CORTEXM_DHCSR_C_HALT | CORTEXM_DHCSR_C_DEBUGEN); + target_mem_write32(target, CORTEXM_DHCSR, + CORTEXM_DHCSR_DBGKEY | CORTEXM_DHCSR_C_HALT | + CORTEXM_DHCSR_C_DEBUGEN); } static int @@ -483,14 +478,14 @@ cortexm_halt_wait(struct target_s *target) { ADIv5_AP_t *ap = adiv5_target_ap(target); struct cortexm_priv *priv = ap->priv; - if (!(adiv5_ap_mem_read(ap, CORTEXM_DHCSR) & CORTEXM_DHCSR_S_HALT)) + if (!(target_mem_read32(target, CORTEXM_DHCSR) & CORTEXM_DHCSR_S_HALT)) return 0; ap->dp->allow_timeout = false; /* We've halted. Let's find out why. */ - uint32_t dfsr = adiv5_ap_mem_read(ap, CORTEXM_DFSR); - adiv5_ap_mem_write(ap, CORTEXM_DFSR, dfsr); /* write back to reset */ + uint32_t dfsr = target_mem_read32(target, CORTEXM_DFSR); + target_mem_write32(target, CORTEXM_DFSR, dfsr); /* write back to reset */ if ((dfsr & CORTEXM_DFSR_VCATCH) && cortexm_fault_unwind(target)) return SIGSEGV; @@ -502,7 +497,7 @@ cortexm_halt_wait(struct target_s *target) * call. */ uint32_t pc = cortexm_pc_read(target); uint16_t bkpt_instr; - target_mem_read(target, &bkpt_instr, pc, 2); + bkpt_instr = target_mem_read16(target, pc); if (bkpt_instr == 0xBEAB) { int n = cortexm_hostio_request(target); if (n > 0) { @@ -535,27 +530,26 @@ void cortexm_halt_resume(struct target_s *target, bool step) /* Disable interrupts while single stepping... */ if(step != priv->stepping) { - adiv5_ap_mem_write(ap, CORTEXM_DHCSR, dhcsr | CORTEXM_DHCSR_C_HALT); + target_mem_write32(target, CORTEXM_DHCSR, dhcsr | CORTEXM_DHCSR_C_HALT); priv->stepping = step; } if (priv->on_bkpt) { uint32_t pc = cortexm_pc_read(target); - if ((adiv5_ap_mem_read_halfword(ap, pc) & 0xFF00) == 0xBE00) + if ((target_mem_read16(target, pc) & 0xFF00) == 0xBE00) cortexm_pc_write(target, pc + 2); } - adiv5_ap_mem_write(ap, CORTEXM_DHCSR, dhcsr); + target_mem_write32(target, CORTEXM_DHCSR, dhcsr); ap->dp->allow_timeout = true; } static int cortexm_fault_unwind(struct target_s *target) { - ADIv5_AP_t *ap = adiv5_target_ap(target); - uint32_t hfsr = adiv5_ap_mem_read(ap, CORTEXM_HFSR); - uint32_t cfsr = adiv5_ap_mem_read(ap, CORTEXM_CFSR); - adiv5_ap_mem_write(ap, CORTEXM_HFSR, hfsr);/* write back to reset */ - adiv5_ap_mem_write(ap, CORTEXM_CFSR, cfsr);/* write back to reset */ + uint32_t hfsr = target_mem_read32(target, CORTEXM_HFSR); + uint32_t cfsr = target_mem_read32(target, CORTEXM_CFSR); + target_mem_write32(target, CORTEXM_HFSR, hfsr);/* write back to reset */ + target_mem_write32(target, CORTEXM_CFSR, cfsr);/* write back to reset */ /* We check for FORCED in the HardFault Status Register or * for a configurable fault to avoid catching core resets */ if((hfsr & CORTEXM_HFSR_FORCED) || cfsr) { @@ -598,7 +592,7 @@ static int cortexm_fault_unwind(struct target_s *target) /* Reset exception state to allow resuming from restored * state. */ - adiv5_ap_mem_write(ap, CORTEXM_AIRCR, + target_mem_write32(target, CORTEXM_AIRCR, CORTEXM_AIRCR_VECTKEY | CORTEXM_AIRCR_VECTCLRACTIVE); /* Write pre-exception registers back to core */ @@ -630,7 +624,7 @@ cortexm_set_hw_bp(struct target_s *target, uint32_t addr) priv->hw_breakpoint[i] = addr | 1; - adiv5_ap_mem_write(ap, CORTEXM_FPB_COMP(i), val); + target_mem_write32(target, CORTEXM_FPB_COMP(i), val); return 0; } @@ -649,7 +643,7 @@ cortexm_clear_hw_bp(struct target_s *target, uint32_t addr) priv->hw_breakpoint[i] = 0; - adiv5_ap_mem_write(ap, CORTEXM_FPB_COMP(i), 0); + target_mem_write32(target, CORTEXM_FPB_COMP(i), 0); return 0; } @@ -683,7 +677,7 @@ cortexm_set_hw_wp(struct target_s *target, uint8_t type, uint32_t addr, uint8_t for(i = 0; i < priv->hw_watchpoint_max; i++) if((priv->hw_watchpoint[i].type == 0) && - ((adiv5_ap_mem_read(ap, CORTEXM_DWT_FUNC(i)) & 0xF) == 0)) + ((target_mem_read32(target, CORTEXM_DWT_FUNC(i)) & 0xF) == 0)) break; if(i == priv->hw_watchpoint_max) return -2; @@ -692,9 +686,9 @@ cortexm_set_hw_wp(struct target_s *target, uint8_t type, uint32_t addr, uint8_t priv->hw_watchpoint[i].addr = addr; priv->hw_watchpoint[i].size = len; - adiv5_ap_mem_write(ap, CORTEXM_DWT_COMP(i), addr); - adiv5_ap_mem_write(ap, CORTEXM_DWT_MASK(i), len); - adiv5_ap_mem_write(ap, CORTEXM_DWT_FUNC(i), type | + target_mem_write32(target, CORTEXM_DWT_COMP(i), addr); + target_mem_write32(target, CORTEXM_DWT_MASK(i), len); + target_mem_write32(target, CORTEXM_DWT_FUNC(i), type | ((target->target_options & TOPT_FLAVOUR_V6M) ? 0: CORTEXM_DWT_FUNC_DATAVSIZE_WORD)); return 0; @@ -732,7 +726,7 @@ cortexm_clear_hw_wp(struct target_s *target, uint8_t type, uint32_t addr, uint8_ priv->hw_watchpoint[i].type = 0; - adiv5_ap_mem_write(ap, CORTEXM_DWT_FUNC(i), 0); + target_mem_write32(target, CORTEXM_DWT_FUNC(i), 0); return 0; } @@ -747,7 +741,7 @@ cortexm_check_hw_wp(struct target_s *target, uint32_t *addr) for(i = 0; i < priv->hw_watchpoint_max; i++) /* if SET and MATCHED then break */ if(priv->hw_watchpoint[i].type && - (adiv5_ap_mem_read(ap, CORTEXM_DWT_FUNC(i)) & + (target_mem_read32(target, CORTEXM_DWT_FUNC(i)) & CORTEXM_DWT_FUNC_MATCHED)) break; @@ -781,7 +775,7 @@ static bool cortexm_vector_catch(target *t, int argc, char *argv[]) else priv->demcr &= ~tmp; - adiv5_ap_mem_write(ap, CORTEXM_DEMCR, priv->demcr); + target_mem_write32(t, CORTEXM_DEMCR, priv->demcr); } gdb_out("Catching vectors: "); diff --git a/src/crc32.c b/src/crc32.c index fffc04c..e8a046d 100644 --- a/src/crc32.c +++ b/src/crc32.c @@ -100,7 +100,7 @@ uint32_t generic_crc32(struct target_s *target, uint32_t base, int len) uint8_t byte; while (len--) { - target_mem_read(target, &byte, base, 1); + byte = target_mem_read8(target, base); crc = crc32_calc(crc, byte); base++; @@ -118,7 +118,7 @@ uint32_t generic_crc32(struct target_s *target, uint32_t base, int len) CRC_CR |= CRC_CR_RESET; while (len > 3) { - target_mem_read(target, &data, base, 4); + data = target_mem_read32(target, base); CRC_DR = __builtin_bswap32(data); base += 4; @@ -128,7 +128,7 @@ uint32_t generic_crc32(struct target_s *target, uint32_t base, int len) crc = CRC_DR; while (len--) { - target_mem_read(target, &data, base++, 1); + data = target_mem_read8(target, base++); crc ^= data << 24; for (i = 0; i < 8; i++) { diff --git a/src/include/adiv5.h b/src/include/adiv5.h index cfdb4e5..4bc3905 100644 --- a/src/include/adiv5.h +++ b/src/include/adiv5.h @@ -166,13 +166,6 @@ void adiv5_ap_ref(ADIv5_AP_t *ap); void adiv5_dp_unref(ADIv5_DP_t *dp); void adiv5_ap_unref(ADIv5_AP_t *ap); -uint32_t adiv5_ap_mem_read(ADIv5_AP_t *ap, uint32_t addr); -void adiv5_ap_mem_write(ADIv5_AP_t *ap, uint32_t addr, uint32_t value); -uint16_t adiv5_ap_mem_read_halfword(ADIv5_AP_t *ap, uint32_t addr); -void adiv5_ap_mem_write_halfword(ADIv5_AP_t *ap, uint32_t addr, uint16_t value); -uint8_t adiv5_ap_mem_read_byte(ADIv5_AP_t *ap, uint32_t addr); -void adiv5_ap_mem_write_byte(ADIv5_AP_t *ap, uint32_t addr, uint8_t value); - void adiv5_ap_write(ADIv5_AP_t *ap, uint16_t addr, uint32_t value); uint32_t adiv5_ap_read(ADIv5_AP_t *ap, uint16_t addr); diff --git a/src/include/target.h b/src/include/target.h index b48e054..b6ea67d 100644 --- a/src/include/target.h +++ b/src/include/target.h @@ -111,7 +111,6 @@ target *target_attach(target *t, target_destroy_callback destroy_cb); #define target_hostio_reply(target, recode, errcode) \ (target)->hostio_reply((target), (retcode), (errcode)) - struct target_s { /* Notify controlling debugger if target is lost */ target_destroy_callback destroy_callback; @@ -187,6 +186,43 @@ target *target_new(unsigned size); void target_list_free(void); void target_add_commands(target *t, const struct command_s *cmds, const char *name); +static inline uint32_t target_mem_read32(target *t, uint32_t addr) +{ + uint32_t ret; + target_mem_read(t, &ret, addr, sizeof(ret)); + return ret; +} + +static inline void target_mem_write32(target *t, uint32_t addr, uint32_t value) +{ + target_mem_write(t, addr, &value, sizeof(value)); +} + +static inline uint16_t target_mem_read16(target *t, uint32_t addr) +{ + uint16_t ret; + target_mem_read(t, &ret, addr, sizeof(ret)); + return ret; +} + +static inline void target_mem_write16(target *t, uint32_t addr, uint16_t value) +{ + target_mem_write(t, addr, &value, sizeof(value)); +} + +static inline uint8_t target_mem_read8(target *t, uint32_t addr) +{ + uint8_t ret; + target_mem_read(t, &ret, addr, sizeof(ret)); + return ret; +} + +static inline void target_mem_write8(target *t, uint32_t addr, uint8_t value) +{ + target_mem_write(t, addr, &value, sizeof(value)); +} + + /* Probe for various targets. * Actual functions implemented in their respective drivers. */ diff --git a/src/kinetis.c b/src/kinetis.c index b260d2a..9f27d9b 100644 --- a/src/kinetis.c +++ b/src/kinetis.c @@ -72,7 +72,7 @@ static const char kl25_xml_memory_map[] = "" bool kinetis_probe(struct target_s *t) { - uint32_t sdid = adiv5_ap_mem_read(adiv5_target_ap(t), SIM_SDID); + uint32_t sdid = target_mem_read32(t, SIM_SDID); switch (sdid >> 20) { case 0x251: t->driver = "KL25"; @@ -87,12 +87,11 @@ bool kinetis_probe(struct target_s *t) static bool kl25_command(struct target_s *t, uint8_t cmd, uint32_t addr, const uint8_t data[8]) { - ADIv5_AP_t *ap = adiv5_target_ap(t); uint8_t fstat; /* Wait for CCIF to be high */ do { - fstat = adiv5_ap_mem_read_byte(ap, FTFA_FSTAT); + fstat = target_mem_read8(t, FTFA_FSTAT); /* Check ACCERR and FPVIOL are zero in FSTAT */ if (fstat & (FTFA_FSTAT_ACCERR | FTFA_FSTAT_FPVIOL)) return false; @@ -101,18 +100,18 @@ kl25_command(struct target_s *t, uint8_t cmd, uint32_t addr, const uint8_t data[ /* Write command to FCCOB */ addr &= 0xffffff; addr |= (uint32_t)cmd << 24; - adiv5_ap_mem_write(ap, FTFA_FCCOB(0), addr); + target_mem_write32(t, FTFA_FCCOB(0), addr); if (data) { - adiv5_ap_mem_write(ap, FTFA_FCCOB(4), *(uint32_t*)&data[0]); - adiv5_ap_mem_write(ap, FTFA_FCCOB(8), *(uint32_t*)&data[4]); + target_mem_write32(t, FTFA_FCCOB(4), *(uint32_t*)&data[0]); + target_mem_write32(t, FTFA_FCCOB(8), *(uint32_t*)&data[4]); } /* Enable execution by clearing CCIF */ - adiv5_ap_mem_write_byte(ap, FTFA_FSTAT, FTFA_FSTAT_CCIF); + target_mem_write8(t, FTFA_FSTAT, FTFA_FSTAT_CCIF); /* Wait for execution to complete */ do { - fstat = adiv5_ap_mem_read_byte(ap, FTFA_FSTAT); + fstat = target_mem_read8(t, FTFA_FSTAT); /* Check ACCERR and FPVIOL are zero in FSTAT */ if (fstat & (FTFA_FSTAT_ACCERR | FTFA_FSTAT_FPVIOL)) return false; diff --git a/src/lmi.c b/src/lmi.c index 8c5e143..d9aa613 100644 --- a/src/lmi.c +++ b/src/lmi.c @@ -100,7 +100,7 @@ static const uint16_t lmi_flash_write_stub[] = { bool lmi_probe(struct target_s *target) { - uint32_t did1 = adiv5_ap_mem_read(adiv5_target_ap(target), 0x400FE004); + uint32_t did1 = target_mem_read32(target, 0x400FE004); switch (did1 >> 16) { case 0x1049: /* LM3S3748 */ target->driver = lmi_driver_str; diff --git a/src/lpc11xx.c b/src/lpc11xx.c index eca3daf..6224464 100644 --- a/src/lpc11xx.c +++ b/src/lpc11xx.c @@ -108,7 +108,7 @@ lpc11xx_probe(struct target_s *target) uint32_t idcode; /* read the device ID register */ - idcode = adiv5_ap_mem_read(adiv5_target_ap(target), 0x400483F4); + idcode = target_mem_read32(target, 0x400483F4); switch (idcode) { diff --git a/src/lpc43xx.c b/src/lpc43xx.c index 0ae9418..29e202a 100644 --- a/src/lpc43xx.c +++ b/src/lpc43xx.c @@ -170,8 +170,8 @@ bool lpc43xx_probe(struct target_s *target) { uint32_t chipid, cpuid; - chipid = adiv5_ap_mem_read(adiv5_target_ap(target), LPC43XX_CHIPID); - cpuid = adiv5_ap_mem_read(adiv5_target_ap(target), ARM_CPUID); + chipid = target_mem_read32(target, LPC43XX_CHIPID); + cpuid = target_mem_read32(target, ARM_CPUID); switch(chipid) { case 0x4906002B: /* Parts with on-chip flash */ diff --git a/src/nrf51.c b/src/nrf51.c index a4396bb..ed0137c 100644 --- a/src/nrf51.c +++ b/src/nrf51.c @@ -136,9 +136,7 @@ static const uint16_t nrf51_flash_write_stub[] = { bool nrf51_probe(struct target_s *target) { - ADIv5_AP_t *ap = adiv5_target_ap(target); - - target->idcode = adiv5_ap_mem_read(ap, NRF51_FICR_CONFIGID) & 0xFFFF; + target->idcode = target_mem_read32(target, NRF51_FICR_CONFIGID) & 0xFFFF; switch (target->idcode) { case 0x001D: @@ -165,32 +163,29 @@ bool nrf51_probe(struct target_s *target) static int nrf51_flash_erase(struct target_s *target, uint32_t addr, size_t len) { - - ADIv5_AP_t *ap = adiv5_target_ap(target); - addr &= ~(NRF51_PAGE_SIZE - 1); len &= ~(NRF51_PAGE_SIZE - 1); /* Enable erase */ - adiv5_ap_mem_write(ap, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_EEN); + target_mem_write32(target, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_EEN); /* Poll for NVMC_READY */ - while(adiv5_ap_mem_read(ap, NRF51_NVMC_READY) == 0) + while (target_mem_read32(target, NRF51_NVMC_READY) == 0) if(target_check_error(target)) return -1; while (len) { if (addr == NRF51_UICR) { // Special Case /* Write to the ERASE_UICR register to erase */ - adiv5_ap_mem_write(ap, NRF51_NVMC_ERASEUICR, 0x1); + target_mem_write32(target, NRF51_NVMC_ERASEUICR, 0x1); } else { // Standard Flash Page /* Write address of first word in page to erase it */ - adiv5_ap_mem_write(ap, NRF51_NVMC_ERASEPAGE, addr); + target_mem_write32(target, NRF51_NVMC_ERASEPAGE, addr); } /* Poll for NVMC_READY */ - while(adiv5_ap_mem_read(ap, NRF51_NVMC_READY) == 0) + while (target_mem_read32(target, NRF51_NVMC_READY) == 0) if(target_check_error(target)) return -1; @@ -199,10 +194,10 @@ static int nrf51_flash_erase(struct target_s *target, uint32_t addr, size_t len) } /* Return to read-only */ - adiv5_ap_mem_write(ap, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_REN); + target_mem_write32(target, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_REN); /* Poll for NVMC_READY */ - while(adiv5_ap_mem_read(ap, NRF51_NVMC_READY) == 0) + while (target_mem_read32(target, NRF51_NVMC_READY) == 0) if(target_check_error(target)) return -1; @@ -212,7 +207,6 @@ static int nrf51_flash_erase(struct target_s *target, uint32_t addr, size_t len) static int nrf51_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, size_t len) { - ADIv5_AP_t *ap = adiv5_target_ap(target); uint32_t offset = dest % 4; uint32_t words = (offset + len + 3) / 4; uint32_t data[2 + words]; @@ -225,10 +219,10 @@ static int nrf51_flash_write(struct target_s *target, uint32_t dest, memcpy((uint8_t *)&data[2] + offset, src, len); /* Enable write */ - adiv5_ap_mem_write(ap, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_WEN); + target_mem_write32(target, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_WEN); /* Poll for NVMC_READY */ - while(adiv5_ap_mem_read(ap, NRF51_NVMC_READY) == 0) + while (target_mem_read32(target, NRF51_NVMC_READY) == 0) if(target_check_error(target)) return -1; @@ -244,30 +238,28 @@ static int nrf51_flash_write(struct target_s *target, uint32_t dest, while(!target_halt_wait(target)); /* Return to read-only */ - adiv5_ap_mem_write(ap, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_REN); + target_mem_write32(target, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_REN); return 0; } static bool nrf51_cmd_erase_all(target *t) { - ADIv5_AP_t *ap = adiv5_target_ap(t); - gdb_out("erase..\n"); /* Enable erase */ - adiv5_ap_mem_write(ap, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_EEN); + target_mem_write32(t, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_EEN); /* Poll for NVMC_READY */ - while(adiv5_ap_mem_read(ap, NRF51_NVMC_READY) == 0) + while (target_mem_read32(t, NRF51_NVMC_READY) == 0) if(target_check_error(t)) return false; /* Erase all */ - adiv5_ap_mem_write(ap, NRF51_NVMC_ERASEALL, 1); + target_mem_write32(t, NRF51_NVMC_ERASEALL, 1); /* Poll for NVMC_READY */ - while(adiv5_ap_mem_read(ap, NRF51_NVMC_READY) == 0) + while (target_mem_read32(t, NRF51_NVMC_READY) == 0) if(target_check_error(t)) return false; @@ -276,28 +268,22 @@ static bool nrf51_cmd_erase_all(target *t) static bool nrf51_cmd_read_hwid(target *t) { - ADIv5_AP_t *ap = adiv5_target_ap(t); - - uint32_t hwid = adiv5_ap_mem_read(ap, NRF51_FICR_CONFIGID) & 0xFFFF; + uint32_t hwid = target_mem_read32(t, NRF51_FICR_CONFIGID) & 0xFFFF; gdb_outf("Hardware ID: 0x%04X\n", hwid); return true; } static bool nrf51_cmd_read_fwid(target *t) { - ADIv5_AP_t *ap = adiv5_target_ap(t); - - uint32_t fwid = (adiv5_ap_mem_read(ap, NRF51_FICR_CONFIGID) >> 16) & 0xFFFF; + uint32_t fwid = (target_mem_read32(t, NRF51_FICR_CONFIGID) >> 16) & 0xFFFF; gdb_outf("Firmware ID: 0x%04X\n", fwid); return true; } static bool nrf51_cmd_read_deviceid(target *t) { - ADIv5_AP_t *ap = adiv5_target_ap(t); - - uint32_t deviceid_low = adiv5_ap_mem_read(ap, NRF51_FICR_DEVICEID_LOW); - uint32_t deviceid_high = adiv5_ap_mem_read(ap, NRF51_FICR_DEVICEID_HIGH); + uint32_t deviceid_low = target_mem_read32(t, NRF51_FICR_DEVICEID_LOW); + uint32_t deviceid_high = target_mem_read32(t, NRF51_FICR_DEVICEID_HIGH); gdb_outf("Device ID: 0x%08X%08X\n", deviceid_high, deviceid_low); @@ -305,11 +291,9 @@ static bool nrf51_cmd_read_deviceid(target *t) } static bool nrf51_cmd_read_deviceaddr(target *t) { - ADIv5_AP_t *ap = adiv5_target_ap(t); - - uint32_t addr_type = adiv5_ap_mem_read(ap, NRF51_FICR_DEVICEADDRTYPE); - uint32_t addr_low = adiv5_ap_mem_read(ap, NRF51_FICR_DEVICEADDR_LOW); - uint32_t addr_high = adiv5_ap_mem_read(ap, NRF51_FICR_DEVICEADDR_HIGH) & 0xFFFF; + uint32_t addr_type = target_mem_read32(t, NRF51_FICR_DEVICEADDRTYPE); + uint32_t addr_low = target_mem_read32(t, NRF51_FICR_DEVICEADDR_LOW); + uint32_t addr_high = target_mem_read32(t, NRF51_FICR_DEVICEADDR_HIGH) & 0xFFFF; if ((addr_type & 1) == 0) { gdb_outf("Publicly Listed Address: 0x%04X%08X\n", addr_high, addr_low); diff --git a/src/sam3x.c b/src/sam3x.c index 211fc92..b9e59a0 100644 --- a/src/sam3x.c +++ b/src/sam3x.c @@ -148,9 +148,7 @@ static const char sam4s_xml_memory_map[] = "" bool sam3x_probe(struct target_s *target) { - ADIv5_AP_t *ap = adiv5_target_ap(target); - - target->idcode = adiv5_ap_mem_read(ap, SAM3X_CHIPID_CIDR); + target->idcode = target_mem_read32(target, SAM3X_CHIPID_CIDR); /* FIXME: Check for all variants with similar flash interface */ switch (target->idcode & (CHIPID_CIDR_ARCH_MASK | CHIPID_CIDR_EPROC_MASK)) { @@ -165,7 +163,7 @@ bool sam3x_probe(struct target_s *target) return true; } - target->idcode = adiv5_ap_mem_read(ap, SAM3N_CHIPID_CIDR); + target->idcode = target_mem_read32(target, SAM3N_CHIPID_CIDR); switch (target->idcode & (CHIPID_CIDR_ARCH_MASK | CHIPID_CIDR_EPROC_MASK)) { case CHIPID_CIDR_ARCH_SAM3NxA | CHIPID_CIDR_EPROC_CM3: case CHIPID_CIDR_ARCH_SAM3NxB | CHIPID_CIDR_EPROC_CM3: @@ -177,21 +175,21 @@ bool sam3x_probe(struct target_s *target) target_add_commands(target, sam3x_cmd_list, "SAM3N"); return true; } - - target->idcode = adiv5_ap_mem_read(ap, SAM3S_CHIPID_CIDR); - switch (target->idcode & (CHIPID_CIDR_ARCH_MASK | CHIPID_CIDR_EPROC_MASK)) { - case CHIPID_CIDR_ARCH_SAM3SxA | CHIPID_CIDR_EPROC_CM3: - case CHIPID_CIDR_ARCH_SAM3SxB | CHIPID_CIDR_EPROC_CM3: - case CHIPID_CIDR_ARCH_SAM3SxC | CHIPID_CIDR_EPROC_CM3: - target->driver = "Atmel SAM3S"; - target->xml_mem_map = sam3n_xml_memory_map; - target->flash_erase = sam3x_flash_erase; - target->flash_write = sam3x_flash_write; - target_add_commands(target, sam3x_cmd_list, "SAM3S"); - return true; - } - - target->idcode = adiv5_ap_mem_read(ap, SAM4S_CHIPID_CIDR); + + target->idcode = target_mem_read32(target, SAM3S_CHIPID_CIDR); + switch (target->idcode & (CHIPID_CIDR_ARCH_MASK | CHIPID_CIDR_EPROC_MASK)) { + case CHIPID_CIDR_ARCH_SAM3SxA | CHIPID_CIDR_EPROC_CM3: + case CHIPID_CIDR_ARCH_SAM3SxB | CHIPID_CIDR_EPROC_CM3: + case CHIPID_CIDR_ARCH_SAM3SxC | CHIPID_CIDR_EPROC_CM3: + target->driver = "Atmel SAM3S"; + target->xml_mem_map = sam3n_xml_memory_map; + target->flash_erase = sam3x_flash_erase; + target->flash_write = sam3x_flash_write; + target_add_commands(target, sam3x_cmd_list, "SAM3S"); + return true; + } + + target->idcode = target_mem_read32(target, SAM4S_CHIPID_CIDR); switch (target->idcode & (CHIPID_CIDR_ARCH_MASK | CHIPID_CIDR_EPROC_MASK)) { case CHIPID_CIDR_ARCH_SAM4SxA | CHIPID_CIDR_EPROC_CM4: case CHIPID_CIDR_ARCH_SAM4SxB | CHIPID_CIDR_EPROC_CM4: @@ -210,18 +208,16 @@ bool sam3x_probe(struct target_s *target) static int sam3x_flash_cmd(struct target_s *target, uint32_t base, uint8_t cmd, uint16_t arg) { - ADIv5_AP_t *ap = adiv5_target_ap(target); - DEBUG("%s: base = 0x%08x cmd = 0x%02X, arg = 0x%06X\n", __func__, base, cmd, arg); - adiv5_ap_mem_write(ap, EEFC_FCR(base), - EEFC_FCR_FKEY | cmd | ((uint32_t)arg << 8)); + target_mem_write32(target, EEFC_FCR(base), + EEFC_FCR_FKEY | cmd | ((uint32_t)arg << 8)); - while(!(adiv5_ap_mem_read(ap, EEFC_FSR(base)) & EEFC_FSR_FRDY)) + while (!(target_mem_read32(target, EEFC_FSR(base)) & EEFC_FSR_FRDY)) if(target_check_error(target)) return -1; - uint32_t sr = adiv5_ap_mem_read(ap, EEFC_FSR(base)); + uint32_t sr = target_mem_read32(target, EEFC_FSR(base)); return sr & EEFC_FSR_ERROR; } @@ -394,11 +390,10 @@ static int sam3x_flash_write(struct target_s *target, uint32_t dest, static bool sam3x_cmd_gpnvm_get(target *t) { - ADIv5_AP_t *ap = adiv5_target_ap(t); uint32_t base = sam3x_flash_base(t, 0, NULL); sam3x_flash_cmd(t, base, EEFC_FCR_FCMD_GGPB, 0); - gdb_outf("GPNVM: 0x%08X\n", adiv5_ap_mem_read(ap, EEFC_FRR(base))); + gdb_outf("GPNVM: 0x%08X\n", target_mem_read32(t, EEFC_FRR(base))); return true; } diff --git a/src/samd.c b/src/samd.c index 2719763..68f5bc4 100644 --- a/src/samd.c +++ b/src/samd.c @@ -167,13 +167,12 @@ static const char samd_xml_memory_map[] = "" */ uint64_t samd_read_pid(struct target_s *target) { - ADIv5_AP_t *ap = adiv5_target_ap(target); uint64_t pid = 0; uint8_t i, j; /* Five PID registers to read LSB first */ for (i = 0, j = 0; i < 5; i++, j += 8) - pid |= (adiv5_ap_mem_read(ap, SAMD_DSU_PID(i)) & 0xFF) << j; + pid |= (target_mem_read32(target, SAMD_DSU_PID(i)) & 0xFF) << j; return pid; } @@ -182,13 +181,12 @@ uint64_t samd_read_pid(struct target_s *target) */ uint32_t samd_read_cid(struct target_s *target) { - ADIv5_AP_t *ap = adiv5_target_ap(target); uint64_t cid = 0; uint8_t i, j; /* Four CID registers to read LSB first */ for (i = 0, j = 0; i < 4; i++, j += 8) - cid |= (adiv5_ap_mem_read(ap, SAMD_DSU_CID(i)) & 0xFF) << j; + cid |= (target_mem_read32(target, SAMD_DSU_CID(i)) & 0xFF) << j; return cid; } @@ -200,8 +198,6 @@ uint32_t samd_read_cid(struct target_s *target) static void samd_reset(struct target_s *target) { - ADIv5_AP_t *ap = adiv5_target_ap(target); - /** * SRST is not asserted here as it appears to reset the adiv5 * logic, meaning that subsequent adiv5_* calls PLATFORM_FATAL_ERROR. @@ -219,28 +215,28 @@ samd_reset(struct target_s *target) */ /* Read DHCSR here to clear S_RESET_ST bit before reset */ - adiv5_ap_mem_read(ap, CORTEXM_DHCSR); + target_mem_read32(target, CORTEXM_DHCSR); /* Request system reset from NVIC: SRST doesn't work correctly */ /* This could be VECTRESET: 0x05FA0001 (reset only core) * or SYSRESETREQ: 0x05FA0004 (system reset) */ - adiv5_ap_mem_write(ap, CORTEXM_AIRCR, + target_mem_write32(target, CORTEXM_AIRCR, CORTEXM_AIRCR_VECTKEY | CORTEXM_AIRCR_SYSRESETREQ); /* Exit extended reset */ - if (adiv5_ap_mem_read(ap, SAMD_DSU_CTRLSTAT) & + if (target_mem_read32(target, SAMD_DSU_CTRLSTAT) & SAMD_STATUSA_CRSTEXT) { /* Write bit to clear from extended reset */ - adiv5_ap_mem_write(ap, SAMD_DSU_CTRLSTAT, + target_mem_write32(target, SAMD_DSU_CTRLSTAT, SAMD_STATUSA_CRSTEXT); } /* Poll for release from reset */ - while(adiv5_ap_mem_read(ap, CORTEXM_DHCSR) & CORTEXM_DHCSR_S_RESET_ST); + while (target_mem_read32(target, CORTEXM_DHCSR) & CORTEXM_DHCSR_S_RESET_ST); /* Reset DFSR flags */ - adiv5_ap_mem_write(ap, CORTEXM_DFSR, CORTEXM_DFSR_RESETALL); + target_mem_write32(target, CORTEXM_DFSR, CORTEXM_DFSR_RESETALL); /* Clear any target errors */ target_check_error(target); @@ -255,16 +251,15 @@ samd_reset(struct target_s *target) static void samd20_revB_detach(struct target_s *target) { - ADIv5_AP_t *ap = adiv5_target_ap(target); cortexm_detach(target); /* ---- Additional ---- */ /* Exit extended reset */ - if (adiv5_ap_mem_read(ap, SAMD_DSU_CTRLSTAT) & + if (target_mem_read32(target, SAMD_DSU_CTRLSTAT) & SAMD_STATUSA_CRSTEXT) { /* Write bit to clear from extended reset */ - adiv5_ap_mem_write(ap, SAMD_DSU_CTRLSTAT, - SAMD_STATUSA_CRSTEXT); + target_mem_write32(target, SAMD_DSU_CTRLSTAT, + SAMD_STATUSA_CRSTEXT); } } @@ -277,16 +272,15 @@ samd20_revB_detach(struct target_s *target) static void samd20_revB_halt_resume(struct target_s *target, bool step) { - ADIv5_AP_t *ap = adiv5_target_ap(target); cortexm_halt_resume(target, step); /* ---- Additional ---- */ /* Exit extended reset */ - if (adiv5_ap_mem_read(ap, SAMD_DSU_CTRLSTAT) & + if (target_mem_read32(target, SAMD_DSU_CTRLSTAT) & SAMD_STATUSA_CRSTEXT) { /* Write bit to clear from extended reset */ - adiv5_ap_mem_write(ap, SAMD_DSU_CTRLSTAT, - SAMD_STATUSA_CRSTEXT); + target_mem_write32(target, SAMD_DSU_CTRLSTAT, + SAMD_STATUSA_CRSTEXT); } } @@ -376,7 +370,6 @@ struct samd_descr samd_parse_device_id(uint32_t did) char variant_string[40]; bool samd_probe(struct target_s *target) { - ADIv5_AP_t *ap = adiv5_target_ap(target); uint32_t cid = samd_read_cid(target); uint32_t pid = samd_read_pid(target); @@ -385,12 +378,13 @@ bool samd_probe(struct target_s *target) (pid & SAMD_PID_MASK) == SAMD_PID_CONST_VALUE) { /* Read the Device ID */ - uint32_t did = adiv5_ap_mem_read(ap, SAMD_DSU_DID); + uint32_t did = target_mem_read32(target, SAMD_DSU_DID); /* If the Device ID matches */ if ((did & SAMD_DID_MASK) == SAMD_DID_CONST_VALUE) { - uint32_t ctrlstat = adiv5_ap_mem_read(ap, SAMD_DSU_CTRLSTAT); + uint32_t ctrlstat = target_mem_read32(target, + SAMD_DSU_CTRLSTAT); struct samd_descr samd = samd_parse_device_id(did); /* Protected? */ @@ -442,11 +436,11 @@ bool samd_probe(struct target_s *target) if (!connect_assert_srst) { /* We'll have to release the target from * extended reset to make attach possible */ - if (adiv5_ap_mem_read(ap, SAMD_DSU_CTRLSTAT) & + if (target_mem_read32(target, SAMD_DSU_CTRLSTAT) & SAMD_STATUSA_CRSTEXT) { /* Write bit to clear from extended reset */ - adiv5_ap_mem_write(ap, SAMD_DSU_CTRLSTAT, + target_mem_write32(target, SAMD_DSU_CTRLSTAT, SAMD_STATUSA_CRSTEXT); } } @@ -463,17 +457,15 @@ bool samd_probe(struct target_s *target) */ static void samd_lock_current_address(struct target_s *target) { - ADIv5_AP_t *ap = adiv5_target_ap(target); - /* Issue the unlock command */ - adiv5_ap_mem_write(ap, SAMD_NVMC_CTRLA, SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_LOCK); + target_mem_write32(target, SAMD_NVMC_CTRLA, + SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_LOCK); } static void samd_unlock_current_address(struct target_s *target) { - ADIv5_AP_t *ap = adiv5_target_ap(target); - /* Issue the unlock command */ - adiv5_ap_mem_write(ap, SAMD_NVMC_CTRLA, SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_UNLOCK); + target_mem_write32(target, SAMD_NVMC_CTRLA, + SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_UNLOCK); } /** @@ -481,23 +473,22 @@ static void samd_unlock_current_address(struct target_s *target) */ static int samd_flash_erase(struct target_s *target, uint32_t addr, size_t len) { - ADIv5_AP_t *ap = adiv5_target_ap(target); - addr &= ~(SAMD_ROW_SIZE - 1); len &= ~(SAMD_ROW_SIZE - 1); while (len) { /* Write address of first word in row to erase it */ /* Must be shifted right for 16-bit address, see Datasheet §20.8.8 Address */ - adiv5_ap_mem_write(ap, SAMD_NVMC_ADDRESS, addr >> 1); + target_mem_write32(target, SAMD_NVMC_ADDRESS, addr >> 1); /* Unlock */ samd_unlock_current_address(target); /* Issue the erase command */ - adiv5_ap_mem_write(ap, SAMD_NVMC_CTRLA, SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_ERASEROW); + target_mem_write32(target, SAMD_NVMC_CTRLA, + SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_ERASEROW); /* Poll for NVM Ready */ - while ((adiv5_ap_mem_read(ap, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0) + while ((target_mem_read32(target, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0) if(target_check_error(target)) return -1; @@ -518,7 +509,6 @@ static int samd_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, size_t len) { ADIv5_AP_t *ap = adiv5_target_ap(target); - /* Find the size of our 32-bit data buffer */ uint32_t offset = dest % 4; uint32_t words = (offset + len + 3) / 4; @@ -560,11 +550,11 @@ static int samd_flash_write(struct target_s *target, uint32_t dest, samd_unlock_current_address(target); /* Issue the write page command */ - adiv5_ap_mem_write(ap, SAMD_NVMC_CTRLA, + target_mem_write32(target, SAMD_NVMC_CTRLA, SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_WRITEPAGE); } else { /* Write first word to set address */ - adiv5_ap_mem_write(ap, addr, data[i]); addr += 4; i++; + target_mem_write32(target, addr, data[i]); addr += 4; i++; /* Unlock */ samd_unlock_current_address(target); @@ -583,7 +573,7 @@ static int samd_flash_write(struct target_s *target, uint32_t dest, } /* Poll for NVM Ready */ - while ((adiv5_ap_mem_read(ap, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0) + while ((target_mem_read32(target, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0) if(target_check_error(target)) return -1; @@ -599,18 +589,16 @@ static int samd_flash_write(struct target_s *target, uint32_t dest, */ static bool samd_cmd_erase_all(target *t) { - ADIv5_AP_t *ap = adiv5_target_ap(t); - /* Clear the DSU status bits */ - adiv5_ap_mem_write(ap, SAMD_DSU_CTRLSTAT, + target_mem_write32(t, SAMD_DSU_CTRLSTAT, (SAMD_STATUSA_DONE | SAMD_STATUSA_PERR | SAMD_STATUSA_FAIL)); /* Erase all */ - adiv5_ap_mem_write(ap, SAMD_DSU_CTRLSTAT, SAMD_CTRL_CHIP_ERASE); + target_mem_write32(t, SAMD_DSU_CTRLSTAT, SAMD_CTRL_CHIP_ERASE); /* Poll for DSU Ready */ uint32_t status; - while (((status = adiv5_ap_mem_read(ap, SAMD_DSU_CTRLSTAT)) & + while (((status = target_mem_read32(t, SAMD_DSU_CTRLSTAT)) & (SAMD_STATUSA_DONE | SAMD_STATUSA_PERR | SAMD_STATUSA_FAIL)) == 0) if(target_check_error(t)) return false; @@ -641,20 +629,19 @@ static bool samd_cmd_erase_all(target *t) */ static bool samd_set_flashlock(target *t, uint16_t value) { - ADIv5_AP_t *ap = adiv5_target_ap(t); - - uint32_t high = adiv5_ap_mem_read(ap, SAMD_NVM_USER_ROW_HIGH); - uint32_t low = adiv5_ap_mem_read(ap, SAMD_NVM_USER_ROW_LOW); + uint32_t high = target_mem_read32(t, SAMD_NVM_USER_ROW_HIGH); + uint32_t low = target_mem_read32(t, SAMD_NVM_USER_ROW_LOW); /* Write address of a word in the row to erase it */ /* Must be shifted right for 16-bit address, see Datasheet §20.8.8 Address */ - adiv5_ap_mem_write(ap, SAMD_NVMC_ADDRESS, SAMD_NVM_USER_ROW_LOW >> 1); + target_mem_write32(t, SAMD_NVMC_ADDRESS, SAMD_NVM_USER_ROW_LOW >> 1); /* Issue the erase command */ - adiv5_ap_mem_write(ap, SAMD_NVMC_CTRLA, SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_ERASEAUXROW); + target_mem_write32(t, SAMD_NVMC_CTRLA, + SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_ERASEAUXROW); /* Poll for NVM Ready */ - while ((adiv5_ap_mem_read(ap, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0) + while ((target_mem_read32(t, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0) if(target_check_error(t)) return -1; @@ -662,12 +649,12 @@ static bool samd_set_flashlock(target *t, uint16_t value) high = (high & 0x0000FFFF) | ((value << 16) & 0xFFFF0000); /* Write back */ - adiv5_ap_mem_write(ap, SAMD_NVM_USER_ROW_LOW, low); - adiv5_ap_mem_write(ap, SAMD_NVM_USER_ROW_HIGH, high); + target_mem_write32(t, SAMD_NVM_USER_ROW_LOW, low); + target_mem_write32(t, SAMD_NVM_USER_ROW_HIGH, high); /* Issue the page write command */ - adiv5_ap_mem_write(ap, SAMD_NVMC_CTRLA, - SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_WRITEAUXPAGE); + target_mem_write32(t, SAMD_NVMC_CTRLA, + SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_WRITEAUXPAGE); return true; } @@ -681,11 +668,9 @@ static bool samd_cmd_unlock_flash(target *t) } static bool samd_cmd_read_userrow(target *t) { - ADIv5_AP_t *ap = adiv5_target_ap(t); - gdb_outf("User Row: 0x%08x%08x\n", - adiv5_ap_mem_read(ap, SAMD_NVM_USER_ROW_HIGH), - adiv5_ap_mem_read(ap, SAMD_NVM_USER_ROW_LOW)); + target_mem_read32(t, SAMD_NVM_USER_ROW_HIGH), + target_mem_read32(t, SAMD_NVM_USER_ROW_LOW)); return true; } @@ -694,12 +679,10 @@ static bool samd_cmd_read_userrow(target *t) */ static bool samd_cmd_serial(target *t) { - ADIv5_AP_t *ap = adiv5_target_ap(t); - gdb_outf("Serial Number: 0x"); for (uint32_t i = 0; i < 4; i++) { - gdb_outf("%08x", adiv5_ap_mem_read(ap, SAMD_NVM_SERIAL(i))); + gdb_outf("%08x", target_mem_read32(t, SAMD_NVM_SERIAL(i))); } gdb_outf("\n"); @@ -711,10 +694,8 @@ static bool samd_cmd_serial(target *t) */ static uint32_t samd_flash_size(target *t) { - ADIv5_AP_t *ap = adiv5_target_ap(t); - /* Read the Device ID */ - uint32_t did = adiv5_ap_mem_read(ap, SAMD_DSU_DID); + uint32_t did = target_mem_read32(t, SAMD_DSU_DID); /* Mask off the device select bits */ uint8_t devsel = did & SAMD_DID_DEVSEL_MASK; @@ -727,21 +708,19 @@ static uint32_t samd_flash_size(target *t) */ static bool samd_cmd_mbist(target *t) { - ADIv5_AP_t *ap = adiv5_target_ap(t); - /* Write the memory parameters to the DSU */ - adiv5_ap_mem_write(ap, SAMD_DSU_ADDRESS, 0); - adiv5_ap_mem_write(ap, SAMD_DSU_LENGTH, samd_flash_size(t)); + target_mem_write32(t, SAMD_DSU_ADDRESS, 0); + target_mem_write32(t, SAMD_DSU_LENGTH, samd_flash_size(t)); /* Clear the fail bit */ - adiv5_ap_mem_write(ap, SAMD_DSU_CTRLSTAT, SAMD_STATUSA_FAIL); + target_mem_write32(t, SAMD_DSU_CTRLSTAT, SAMD_STATUSA_FAIL); /* Write the MBIST command */ - adiv5_ap_mem_write(ap, SAMD_DSU_CTRLSTAT, SAMD_CTRL_MBIST); + target_mem_write32(t, SAMD_DSU_CTRLSTAT, SAMD_CTRL_MBIST); /* Poll for DSU Ready */ uint32_t status; - while (((status = adiv5_ap_mem_read(ap, SAMD_DSU_CTRLSTAT)) & + while (((status = target_mem_read32(t, SAMD_DSU_CTRLSTAT)) & (SAMD_STATUSA_DONE | SAMD_STATUSA_PERR | SAMD_STATUSA_FAIL)) == 0) if(target_check_error(t)) return false; @@ -755,7 +734,7 @@ static bool samd_cmd_mbist(target *t) /* Test the fail bit in Status A */ if (status & SAMD_STATUSA_FAIL) { gdb_outf("MBIST Fail @ 0x%08x\n", - adiv5_ap_mem_read(ap, SAMD_DSU_ADDRESS)); + target_mem_read32(t, SAMD_DSU_ADDRESS)); } else { gdb_outf("MBIST Passed!\n"); } @@ -767,13 +746,12 @@ static bool samd_cmd_mbist(target *t) */ static bool samd_cmd_ssb(target *t) { - ADIv5_AP_t *ap = adiv5_target_ap(t); - /* Issue the ssb command */ - adiv5_ap_mem_write(ap, SAMD_NVMC_CTRLA, SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_SSB); + target_mem_write32(t, SAMD_NVMC_CTRLA, + SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_SSB); /* Poll for NVM Ready */ - while ((adiv5_ap_mem_read(ap, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0) + while ((target_mem_read32(t, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0) if(target_check_error(t)) return -1; diff --git a/src/stm32f1.c b/src/stm32f1.c index ca55fad..a746d5d 100644 --- a/src/stm32f1.c +++ b/src/stm32f1.c @@ -158,8 +158,7 @@ static const uint16_t stm32f1_flash_write_stub[] = { bool stm32f1_probe(struct target_s *target) { - - target->idcode = adiv5_ap_mem_read(adiv5_target_ap(target), DBGMCU_IDCODE) & 0xfff; + target->idcode = target_mem_read32(target, DBGMCU_IDCODE) & 0xfff; switch(target->idcode) { case 0x410: /* Medium density */ case 0x412: /* Low denisty */ @@ -189,7 +188,7 @@ bool stm32f1_probe(struct target_s *target) return true; } - target->idcode = adiv5_ap_mem_read(adiv5_target_ap(target), DBGMCU_IDCODE_F0) & 0xfff; + target->idcode = target_mem_read32(target, DBGMCU_IDCODE_F0) & 0xfff; switch(target->idcode) { case 0x444: /* STM32F03 RM0091 Rev.7 */ case 0x445: /* STM32F04 RM0091 Rev.7 */ @@ -223,33 +222,32 @@ bool stm32f1_probe(struct target_s *target) return false; } -static void stm32f1_flash_unlock(ADIv5_AP_t *ap) +static void stm32f1_flash_unlock(target *t) { - adiv5_ap_mem_write(ap, FLASH_KEYR, KEY1); - adiv5_ap_mem_write(ap, FLASH_KEYR, KEY2); + target_mem_write32(t, FLASH_KEYR, KEY1); + target_mem_write32(t, FLASH_KEYR, KEY2); } static int stm32f1_flash_erase(struct target_s *target, uint32_t addr, size_t len, uint32_t pagesize) { - ADIv5_AP_t *ap = adiv5_target_ap(target); uint16_t sr; addr &= ~(pagesize - 1); len = (len + pagesize - 1) & ~(pagesize - 1); - stm32f1_flash_unlock(ap); + stm32f1_flash_unlock(target); while(len) { /* Flash page erase instruction */ - adiv5_ap_mem_write(ap, FLASH_CR, FLASH_CR_PER); + target_mem_write32(target, FLASH_CR, FLASH_CR_PER); /* write address to FMA */ - adiv5_ap_mem_write(ap, FLASH_AR, addr); + target_mem_write32(target, FLASH_AR, addr); /* Flash page erase start instruction */ - adiv5_ap_mem_write(ap, FLASH_CR, FLASH_CR_STRT | FLASH_CR_PER); + target_mem_write32(target, FLASH_CR, FLASH_CR_STRT | FLASH_CR_PER); /* Read FLASH_SR to poll for BSY bit */ - while(adiv5_ap_mem_read(ap, FLASH_SR) & FLASH_SR_BSY) + while (target_mem_read32(target, FLASH_SR) & FLASH_SR_BSY) if(target_check_error(target)) return -1; @@ -258,7 +256,7 @@ static int stm32f1_flash_erase(struct target_s *target, uint32_t addr, } /* Check for error */ - sr = adiv5_ap_mem_read(ap, FLASH_SR); + sr = target_mem_read32(target, FLASH_SR); if ((sr & SR_ERROR_MASK) || !(sr & SR_EOP)) return -1; @@ -278,7 +276,6 @@ static int stm32md_flash_erase(struct target_s *target, uint32_t addr, size_t le static int stm32f1_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, size_t len) { - ADIv5_AP_t *ap = adiv5_target_ap(target); uint32_t offset = dest % 4; uint32_t words = (offset + len + 3) / 4; if (words > 256) @@ -304,7 +301,7 @@ static int stm32f1_flash_write(struct target_s *target, uint32_t dest, while(!target_halt_wait(target)); /* Check for error */ - if (adiv5_ap_mem_read(ap, FLASH_SR) & SR_ERROR_MASK) + if (target_mem_read32(target, FLASH_SR) & SR_ERROR_MASK) return -1; return 0; @@ -312,21 +309,19 @@ static int stm32f1_flash_write(struct target_s *target, uint32_t dest, static bool stm32f1_cmd_erase_mass(target *t) { - ADIv5_AP_t *ap = adiv5_target_ap(t); - - stm32f1_flash_unlock(ap); + stm32f1_flash_unlock(t); /* Flash mass erase start instruction */ - adiv5_ap_mem_write(ap, FLASH_CR, FLASH_CR_MER); - adiv5_ap_mem_write(ap, FLASH_CR, FLASH_CR_STRT | FLASH_CR_MER); + target_mem_write32(t, FLASH_CR, FLASH_CR_MER); + target_mem_write32(t, FLASH_CR, FLASH_CR_STRT | FLASH_CR_MER); /* Read FLASH_SR to poll for BSY bit */ - while(adiv5_ap_mem_read(ap, FLASH_SR) & FLASH_SR_BSY) + while (target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY) if(target_check_error(t)) return false; /* Check for error */ - uint16_t sr = adiv5_ap_mem_read(ap, FLASH_SR); + uint16_t sr = target_mem_read32(t, FLASH_SR); if ((sr & SR_ERROR_MASK) || !(sr & SR_EOP)) return false; @@ -335,14 +330,12 @@ static bool stm32f1_cmd_erase_mass(target *t) static bool stm32f1_option_erase(target *t) { - ADIv5_AP_t *ap = adiv5_target_ap(t); - /* Erase option bytes instruction */ - adiv5_ap_mem_write(ap, FLASH_CR, FLASH_CR_OPTER | FLASH_CR_OPTWRE); - adiv5_ap_mem_write(ap, FLASH_CR, - FLASH_CR_STRT | FLASH_CR_OPTER | FLASH_CR_OPTWRE); + target_mem_write32(t, FLASH_CR, FLASH_CR_OPTER | FLASH_CR_OPTWRE); + target_mem_write32(t, FLASH_CR, + FLASH_CR_STRT | FLASH_CR_OPTER | FLASH_CR_OPTWRE); /* Read FLASH_SR to poll for BSY bit */ - while(adiv5_ap_mem_read(ap, FLASH_SR) & FLASH_SR_BSY) + while (target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY) if(target_check_error(t)) return false; return true; @@ -350,15 +343,13 @@ static bool stm32f1_option_erase(target *t) static bool stm32f1_option_write_erased(target *t, uint32_t addr, uint16_t value) { - ADIv5_AP_t *ap = adiv5_target_ap(t); - if (value == 0xffff) return true; /* Erase option bytes instruction */ - adiv5_ap_mem_write(ap, FLASH_CR, FLASH_CR_OPTPG | FLASH_CR_OPTWRE); - adiv5_ap_mem_write_halfword(ap, addr, value); + target_mem_write32(t, FLASH_CR, FLASH_CR_OPTPG | FLASH_CR_OPTWRE); + target_mem_write16(t, addr, value); /* Read FLASH_SR to poll for BSY bit */ - while(adiv5_ap_mem_read(ap, FLASH_SR) & FLASH_SR_BSY) + while (target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY) if(target_check_error(t)) return false; return true; @@ -366,7 +357,6 @@ static bool stm32f1_option_write_erased(target *t, uint32_t addr, uint16_t value static bool stm32f1_option_write(target *t, uint32_t addr, uint16_t value) { - ADIv5_AP_t *ap = adiv5_target_ap(t); uint16_t opt_val[8]; int i, index; @@ -375,7 +365,7 @@ static bool stm32f1_option_write(target *t, uint32_t addr, uint16_t value) return false; /* Retrieve old values */ for (i = 0; i < 16; i = i +4) { - uint32_t val = adiv5_ap_mem_read(ap, FLASH_OBP_RDP + i); + uint32_t val = target_mem_read32(t, FLASH_OBP_RDP + i); opt_val[i/2] = val & 0xffff; opt_val[i/2 +1] = val >> 16; } @@ -398,7 +388,6 @@ static bool stm32f1_cmd_option(target *t, int argc, char *argv[]) { uint32_t addr, val; uint32_t flash_obp_rdp_key; - ADIv5_AP_t *ap = adiv5_target_ap(t); uint32_t rdprt; switch(t->idcode) { @@ -409,10 +398,10 @@ static bool stm32f1_cmd_option(target *t, int argc, char *argv[]) break; default: flash_obp_rdp_key = FLASH_OBP_RDP_KEY; } - rdprt = (adiv5_ap_mem_read(ap, FLASH_OBR) & FLASH_OBR_RDPRT); - stm32f1_flash_unlock(ap); - adiv5_ap_mem_write(ap, FLASH_OPTKEYR, KEY1); - adiv5_ap_mem_write(ap, FLASH_OPTKEYR, KEY2); + rdprt = target_mem_read32(t, FLASH_OBR) & FLASH_OBR_RDPRT; + stm32f1_flash_unlock(t); + target_mem_write32(t, FLASH_OPTKEYR, KEY1); + target_mem_write32(t, FLASH_OPTKEYR, KEY2); if ((argc == 2) && !strcmp(argv[1], "erase")) { stm32f1_option_erase(t); @@ -432,7 +421,7 @@ static bool stm32f1_cmd_option(target *t, int argc, char *argv[]) if (0 && flash_obp_rdp_key == FLASH_OBP_RDP_KEY_F3) { /* Reload option bytes on F0 and F3*/ - val = adiv5_ap_mem_read(ap, FLASH_CR); + val = target_mem_read32(t, FLASH_CR); val |= FLASH_CR_OBL_LAUNCH; stm32f1_option_write(t, FLASH_CR, val); val &= ~FLASH_CR_OBL_LAUNCH; @@ -441,7 +430,7 @@ static bool stm32f1_cmd_option(target *t, int argc, char *argv[]) for (int i = 0; i < 0xf; i += 4) { addr = 0x1ffff800 + i; - val = adiv5_ap_mem_read(ap, addr); + val = target_mem_read32(t, addr); gdb_outf("0x%08X: 0x%04X\n", addr, val & 0xFFFF); gdb_outf("0x%08X: 0x%04X\n", addr + 2, val >> 16); } diff --git a/src/stm32f4.c b/src/stm32f4.c index 58d1328..2a8bc21 100644 --- a/src/stm32f4.c +++ b/src/stm32f4.c @@ -162,7 +162,7 @@ bool stm32f4_probe(struct target_s *target) { uint32_t idcode; - idcode = adiv5_ap_mem_read(adiv5_target_ap(target), DBGMCU_IDCODE); + idcode = target_mem_read32(target, DBGMCU_IDCODE); switch(idcode & 0xFFF) { case 0x411: /* Documented to be 0x413! This is what I read... */ case 0x413: /* F407VGT6 */ @@ -180,25 +180,24 @@ bool stm32f4_probe(struct target_s *target) return false; } -static void stm32f4_flash_unlock(ADIv5_AP_t *ap) +static void stm32f4_flash_unlock(target *t) { - if (adiv5_ap_mem_read(ap, FLASH_CR) & FLASH_CR_LOCK) { + if (target_mem_read32(t, FLASH_CR) & FLASH_CR_LOCK) { /* Enable FPEC controller access */ - adiv5_ap_mem_write(ap, FLASH_KEYR, KEY1); - adiv5_ap_mem_write(ap, FLASH_KEYR, KEY2); + target_mem_write32(t, FLASH_KEYR, KEY1); + target_mem_write32(t, FLASH_KEYR, KEY2); } } static int stm32f4_flash_erase(struct target_s *target, uint32_t addr, size_t len) { - ADIv5_AP_t *ap = adiv5_target_ap(target); uint16_t sr; uint32_t cr; uint32_t pagesize; addr &= 0x07FFC000; - stm32f4_flash_unlock(ap); + stm32f4_flash_unlock(target); while(len) { if (addr < 0x10000) { /* Sector 0..3 */ @@ -215,12 +214,12 @@ static int stm32f4_flash_erase(struct target_s *target, uint32_t addr, size_t le } cr |= FLASH_CR_EOPIE | FLASH_CR_ERRIE | FLASH_CR_SER; /* Flash page erase instruction */ - adiv5_ap_mem_write(ap, FLASH_CR, cr); + target_mem_write32(target, FLASH_CR, cr); /* write address to FMA */ - adiv5_ap_mem_write(ap, FLASH_CR, cr | FLASH_CR_STRT); + target_mem_write32(target, FLASH_CR, cr | FLASH_CR_STRT); /* Read FLASH_SR to poll for BSY bit */ - while(adiv5_ap_mem_read(ap, FLASH_SR) & FLASH_SR_BSY) + while(target_mem_read32(target, FLASH_SR) & FLASH_SR_BSY) if(target_check_error(target)) return -1; @@ -229,7 +228,7 @@ static int stm32f4_flash_erase(struct target_s *target, uint32_t addr, size_t le } /* Check for error */ - sr = adiv5_ap_mem_read(ap, FLASH_SR); + sr = target_mem_read32(target, FLASH_SR); if(sr & SR_ERROR_MASK) return -1; @@ -239,7 +238,6 @@ static int stm32f4_flash_erase(struct target_s *target, uint32_t addr, size_t le static int stm32f4_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, size_t len) { - ADIv5_AP_t *ap = adiv5_target_ap(target); uint32_t offset = dest % 4; uint32_t words = (offset + len + 3) / 4; uint32_t data[2 + words]; @@ -264,7 +262,7 @@ static int stm32f4_flash_write(struct target_s *target, uint32_t dest, while(!target_halt_wait(target)); /* Check for error */ - sr = adiv5_ap_mem_read(ap, FLASH_SR); + sr = target_mem_read32(target, FLASH_SR); if(sr & SR_ERROR_MASK) return -1; @@ -276,17 +274,15 @@ static bool stm32f4_cmd_erase_mass(target *t) const char spinner[] = "|/-\\"; int spinindex = 0; - ADIv5_AP_t *ap = adiv5_target_ap(t); - gdb_out("Erasing flash... This may take a few seconds. "); - stm32f4_flash_unlock(ap); + stm32f4_flash_unlock(t); /* Flash mass erase start instruction */ - adiv5_ap_mem_write(ap, FLASH_CR, FLASH_CR_MER); - adiv5_ap_mem_write(ap, FLASH_CR, FLASH_CR_STRT | FLASH_CR_MER); + target_mem_write32(t, FLASH_CR, FLASH_CR_MER); + target_mem_write32(t, FLASH_CR, FLASH_CR_STRT | FLASH_CR_MER); /* Read FLASH_SR to poll for BSY bit */ - while(adiv5_ap_mem_read(ap, FLASH_SR) & FLASH_SR_BSY) { + while (target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY) { gdb_outf("\b%c", spinner[spinindex++ % 4]); if(target_check_error(t)) { gdb_out("\n"); @@ -296,7 +292,7 @@ static bool stm32f4_cmd_erase_mass(target *t) gdb_out("\n"); /* Check for error */ - uint16_t sr = adiv5_ap_mem_read(ap, FLASH_SR); + uint16_t sr = target_mem_read32(t, FLASH_SR); if ((sr & SR_ERROR_MASK) || !(sr & SR_EOP)) return false; @@ -305,23 +301,21 @@ static bool stm32f4_cmd_erase_mass(target *t) static bool stm32f4_option_write(target *t, uint32_t value) { - ADIv5_AP_t *ap = adiv5_target_ap(t); - - adiv5_ap_mem_write(ap, FLASH_OPTKEYR, OPTKEY1); - adiv5_ap_mem_write(ap, FLASH_OPTKEYR, OPTKEY2); + target_mem_write32(t, FLASH_OPTKEYR, OPTKEY1); + target_mem_write32(t, FLASH_OPTKEYR, OPTKEY2); value &= ~FLASH_OPTCR_RESERVED; - while(adiv5_ap_mem_read(ap, FLASH_SR) & FLASH_SR_BSY) + while (target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY) if(target_check_error(t)) return -1; /* WRITE option bytes instruction */ - adiv5_ap_mem_write(ap, FLASH_OPTCR, value); - adiv5_ap_mem_write(ap, FLASH_OPTCR, value | FLASH_OPTCR_OPTSTRT); + target_mem_write32(t, FLASH_OPTCR, value); + target_mem_write32(t, FLASH_OPTCR, value | FLASH_OPTCR_OPTSTRT); /* Read FLASH_SR to poll for BSY bit */ - while(adiv5_ap_mem_read(ap, FLASH_SR) & FLASH_SR_BSY) + while(target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY) if(target_check_error(t)) return false; - adiv5_ap_mem_write(ap, FLASH_OPTCR, value | FLASH_OPTCR_OPTLOCK); + target_mem_write32(t, FLASH_OPTCR, value | FLASH_OPTCR_OPTLOCK); return true; } @@ -329,8 +323,6 @@ static bool stm32f4_cmd_option(target *t, int argc, char *argv[]) { uint32_t addr, val; - ADIv5_AP_t *ap = adiv5_target_ap(t); - if ((argc == 2) && !strcmp(argv[1], "erase")) { stm32f4_option_write(t, 0x0fffaaed); } @@ -344,7 +336,7 @@ static bool stm32f4_cmd_option(target *t, int argc, char *argv[]) for (int i = 0; i < 0xf; i += 8) { addr = 0x1fffC000 + i; - val = adiv5_ap_mem_read(ap, addr); + val = target_mem_read32(t, addr); gdb_outf("0x%08X: 0x%04X\n", addr, val & 0xFFFF); } return true; diff --git a/src/stm32l0.c b/src/stm32l0.c index 028f2a1..28088a8 100644 --- a/src/stm32l0.c +++ b/src/stm32l0.c @@ -72,13 +72,13 @@ to regain control of the target after the option byte reload. stm32l0_option_write(t, 0x1ff80000, 0xffff0000); - adiv5_ap_mem_write(ap, STM32L0_NVM_PECR, STM32L0_NVM_PECR_OBL_LAUNCH); + target_mem_write32(target, STM32L0_NVM_PECR, STM32L0_NVM_PECR_OBL_LAUNCH); stm32l0_option_write(t, 0x1ff80000, 0xff5500aa); - adiv5_ap_mem_write(ap, STM32L0_NVM_PECR, STM32L0_NVM_PECR_OBL_LAUNCH); + target_mem_write32(target, STM32L0_NVM_PECR, STM32L0_NVM_PECR_OBL_LAUNCH); uint32_t sr; do { - sr = adiv5_ap_mem_read(ap, STM32L0_NVM_SR); + sr = target_mem_read32(target, STM32L0_NVM_SR); } while (sr & STM32L0_NVM_SR_BSY); o Errors. We probably should clear SR errors immediately after @@ -288,7 +288,7 @@ bool stm32l0_probe(struct target_s* target) #if defined(CONFIG_STM32L1) - idcode = adiv5_ap_mem_read(adiv5_target_ap(target), + idcode = target_mem_read32(target, STM32L1_DBGMCU_IDCODE_PHYS) & 0xfff; switch (idcode) { case 0x416: /* CAT. 1 device */ @@ -306,7 +306,7 @@ bool stm32l0_probe(struct target_s* target) } #endif - idcode = adiv5_ap_mem_read(adiv5_target_ap(target), + idcode = target_mem_read32(target, STM32L0_DBGMCU_IDCODE_PHYS) & 0xfff; switch (idcode) { default: @@ -327,42 +327,42 @@ bool stm32l0_probe(struct target_s* target) /** Lock the NVM control registers preventing writes or erases. */ -static void stm32lx_nvm_lock(ADIv5_AP_t* ap, uint32_t nvm) +static void stm32lx_nvm_lock(target *t, uint32_t nvm) { - adiv5_ap_mem_write(ap, STM32Lx_NVM_PECR(nvm), STM32Lx_NVM_PECR_PELOCK); + target_mem_write32(t, STM32Lx_NVM_PECR(nvm), STM32Lx_NVM_PECR_PELOCK); } /** Unlock the NVM control registers for modifying program or data flash. Returns true if the unlock succeeds. */ -static bool stm32lx_nvm_prog_data_unlock(ADIv5_AP_t* ap, uint32_t nvm) +static bool stm32lx_nvm_prog_data_unlock(target* t, uint32_t nvm) { /* Always lock first because that's the only way to know that the unlock can succeed on the STM32L0's. */ - adiv5_ap_mem_write(ap, STM32Lx_NVM_PECR(nvm), STM32Lx_NVM_PECR_PELOCK); - adiv5_ap_mem_write(ap, STM32Lx_NVM_PEKEYR(nvm), STM32Lx_NVM_PEKEY1); - adiv5_ap_mem_write(ap, STM32Lx_NVM_PEKEYR(nvm), STM32Lx_NVM_PEKEY2); - adiv5_ap_mem_write(ap, STM32Lx_NVM_PRGKEYR(nvm), STM32Lx_NVM_PRGKEY1); - adiv5_ap_mem_write(ap, STM32Lx_NVM_PRGKEYR(nvm), STM32Lx_NVM_PRGKEY2); + target_mem_write32(t, STM32Lx_NVM_PECR(nvm), STM32Lx_NVM_PECR_PELOCK); + target_mem_write32(t, STM32Lx_NVM_PEKEYR(nvm), STM32Lx_NVM_PEKEY1); + target_mem_write32(t, STM32Lx_NVM_PEKEYR(nvm), STM32Lx_NVM_PEKEY2); + target_mem_write32(t, STM32Lx_NVM_PRGKEYR(nvm), STM32Lx_NVM_PRGKEY1); + target_mem_write32(t, STM32Lx_NVM_PRGKEYR(nvm), STM32Lx_NVM_PRGKEY2); - return !(adiv5_ap_mem_read(ap, STM32Lx_NVM_PECR(nvm)) + return !(target_mem_read32(t, STM32Lx_NVM_PECR(nvm)) & STM32Lx_NVM_PECR_PRGLOCK); } /** Unlock the NVM control registers for modifying option bytes. Returns true if the unlock succeeds. */ -static bool stm32lx_nvm_opt_unlock(ADIv5_AP_t* ap, uint32_t nvm) +static bool stm32lx_nvm_opt_unlock(target *t, uint32_t nvm) { /* Always lock first because that's the only way to know that the unlock can succeed on the STM32L0's. */ - adiv5_ap_mem_write(ap, STM32Lx_NVM_PECR(nvm), STM32Lx_NVM_PECR_PELOCK); - adiv5_ap_mem_write(ap, STM32Lx_NVM_PEKEYR(nvm), STM32Lx_NVM_PEKEY1); - adiv5_ap_mem_write(ap, STM32Lx_NVM_PEKEYR(nvm), STM32Lx_NVM_PEKEY2); - adiv5_ap_mem_write(ap, STM32Lx_NVM_OPTKEYR(nvm), STM32Lx_NVM_OPTKEY1); - adiv5_ap_mem_write(ap, STM32Lx_NVM_OPTKEYR(nvm), STM32Lx_NVM_OPTKEY2); + target_mem_write32(t, STM32Lx_NVM_PECR(nvm), STM32Lx_NVM_PECR_PELOCK); + target_mem_write32(t, STM32Lx_NVM_PEKEYR(nvm), STM32Lx_NVM_PEKEY1); + target_mem_write32(t, STM32Lx_NVM_PEKEYR(nvm), STM32Lx_NVM_PEKEY2); + target_mem_write32(t, STM32Lx_NVM_OPTKEYR(nvm), STM32Lx_NVM_OPTKEY1); + target_mem_write32(t, STM32Lx_NVM_OPTKEYR(nvm), STM32Lx_NVM_OPTKEY2); - return !(adiv5_ap_mem_read(ap, STM32Lx_NVM_PECR(nvm)) + return !(target_mem_read32(t, STM32Lx_NVM_PECR(nvm)) & STM32Lx_NVM_PECR_OPTLOCK); } @@ -400,8 +400,7 @@ static int stm32lx_nvm_prog_erase_stubbed(struct target_s* target, while (!target_halt_wait(target)) ; { - ADIv5_AP_t* ap = adiv5_target_ap(target); - if (adiv5_ap_mem_read(ap, STM32Lx_NVM_SR(nvm)) + if (target_mem_read32(target, STM32Lx_NVM_SR(nvm)) & STM32Lx_NVM_SR_ERR_M) return -1; } @@ -477,8 +476,7 @@ static int stm32lx_nvm_prog_write_stubbed(struct target_s* target, while (!target_halt_wait(target)) ; - if (adiv5_ap_mem_read(adiv5_target_ap(target), - STM32Lx_NVM_SR(nvm)) + if (target_mem_read32(target, STM32Lx_NVM_SR(nvm)) & STM32Lx_NVM_SR_ERR_M) return -1; } @@ -557,7 +555,6 @@ static int stm32lx_nvm_write(struct target_s* target, static int stm32lx_nvm_prog_erase(struct target_s* target, uint32_t addr, size_t len) { - ADIv5_AP_t* ap = adiv5_target_ap(target); const size_t page_size = stm32lx_nvm_prog_page_size(target); const uint32_t nvm = stm32lx_nvm_phys(target); @@ -565,15 +562,15 @@ static int stm32lx_nvm_prog_erase(struct target_s* target, len += (addr & 3); addr &= ~3; - if (!stm32lx_nvm_prog_data_unlock(ap, nvm)) + if (!stm32lx_nvm_prog_data_unlock(target, nvm)) return -1; /* Flash page erase instruction */ - adiv5_ap_mem_write(ap, STM32Lx_NVM_PECR(nvm), + target_mem_write32(target, STM32Lx_NVM_PECR(nvm), STM32Lx_NVM_PECR_ERASE | STM32Lx_NVM_PECR_PROG); { - uint32_t pecr = adiv5_ap_mem_read(ap, STM32Lx_NVM_PECR(nvm)); + uint32_t pecr = target_mem_read32(target, STM32Lx_NVM_PECR(nvm)); if ((pecr & (STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE)) != (STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE)) return -1; @@ -581,22 +578,22 @@ static int stm32lx_nvm_prog_erase(struct target_s* target, /* Clear errors. Note that this only works when we wait for the NVM block to complete the last operation. */ - adiv5_ap_mem_write(ap, STM32Lx_NVM_SR(nvm), STM32Lx_NVM_SR_ERR_M); + target_mem_write32(target, STM32Lx_NVM_SR(nvm), STM32Lx_NVM_SR_ERR_M); while (len > 0) { /* Write first word of page to 0 */ - adiv5_ap_mem_write(ap, addr, 0); + target_mem_write32(target, addr, 0); len -= page_size; addr += page_size; } /* Disable further programming by locking PECR */ - stm32lx_nvm_lock(ap, nvm); + stm32lx_nvm_lock(target, nvm); /* Wait for completion or an error */ while (1) { - uint32_t sr = adiv5_ap_mem_read(ap, STM32Lx_NVM_SR(nvm)); + uint32_t sr = target_mem_read32(target, STM32Lx_NVM_SR(nvm)); if (target_check_error(target)) return -1; if (sr & STM32Lx_NVM_SR_BSY) @@ -618,7 +615,6 @@ static int stm32lx_nvm_prog_write(struct target_s* target, const uint8_t* source_8, size_t size) { - ADIv5_AP_t* ap = adiv5_target_ap(target); const uint32_t nvm = stm32lx_nvm_phys(target); const bool is_stm32l1 = stm32lx_is_stm32l1(target); @@ -629,7 +625,7 @@ static int stm32lx_nvm_prog_write(struct target_s* target, if ((destination & 3) || (size & 3)) return -1; - if (!stm32lx_nvm_prog_data_unlock(ap, nvm)) + if (!stm32lx_nvm_prog_data_unlock(target, nvm)) return -1; const size_t half_page_size = stm32lx_nvm_prog_page_size(target)/2; @@ -639,7 +635,7 @@ static int stm32lx_nvm_prog_write(struct target_s* target, /* Wait for BSY to clear because we cannot write the PECR until the previous operation completes on STM32Lxxx. */ - while (adiv5_ap_mem_read(ap, STM32Lx_NVM_SR(nvm)) + while (target_mem_read32(target, STM32Lx_NVM_SR(nvm)) & STM32Lx_NVM_SR_BSY) if (target_check_error(target)) { return -1; @@ -649,7 +645,7 @@ static int stm32lx_nvm_prog_write(struct target_s* target, // than a half page to write if (size < half_page_size || (destination & (half_page_size - 1))) { - adiv5_ap_mem_write(ap, STM32Lx_NVM_PECR(nvm), + target_mem_write32(target, STM32Lx_NVM_PECR(nvm), is_stm32l1 ? 0 : STM32Lx_NVM_PECR_PROG); @@ -666,7 +662,7 @@ static int stm32lx_nvm_prog_write(struct target_s* target, } // Or we are writing a half-page(s) else { - adiv5_ap_mem_write(ap, STM32Lx_NVM_PECR(nvm), + target_mem_write32(target, STM32Lx_NVM_PECR(nvm), STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_FPRG); @@ -679,11 +675,11 @@ static int stm32lx_nvm_prog_write(struct target_s* target, } /* Disable further programming by locking PECR */ - stm32lx_nvm_lock(ap, nvm); + stm32lx_nvm_lock(target, nvm); /* Wait for completion or an error */ while (1) { - uint32_t sr = adiv5_ap_mem_read(ap, STM32Lx_NVM_SR(nvm)); + uint32_t sr = target_mem_read32(target, STM32Lx_NVM_SR(nvm)); if (target_check_error(target)) { return -1; } @@ -706,7 +702,6 @@ static int stm32lx_nvm_prog_write(struct target_s* target, static int stm32lx_nvm_data_erase(struct target_s* target, uint32_t addr, size_t len) { - ADIv5_AP_t* ap = adiv5_target_ap(target); const size_t page_size = stm32lx_nvm_data_page_size(target); const uint32_t nvm = stm32lx_nvm_phys(target); @@ -714,15 +709,15 @@ static int stm32lx_nvm_data_erase(struct target_s* target, len += (addr & 3); addr &= ~3; - if (!stm32lx_nvm_prog_data_unlock(ap, nvm)) + if (!stm32lx_nvm_prog_data_unlock(target, nvm)) return -1; /* Flash data erase instruction */ - adiv5_ap_mem_write(ap, STM32Lx_NVM_PECR(nvm), + target_mem_write32(target, STM32Lx_NVM_PECR(nvm), STM32Lx_NVM_PECR_ERASE | STM32Lx_NVM_PECR_DATA); { - uint32_t pecr = adiv5_ap_mem_read(ap, STM32Lx_NVM_PECR(nvm)); + uint32_t pecr = target_mem_read32(target, STM32Lx_NVM_PECR(nvm)); if ((pecr & (STM32Lx_NVM_PECR_ERASE | STM32Lx_NVM_PECR_DATA)) != (STM32Lx_NVM_PECR_ERASE | STM32Lx_NVM_PECR_DATA)) return -1; @@ -730,18 +725,18 @@ static int stm32lx_nvm_data_erase(struct target_s* target, while (len > 0) { /* Write first word of page to 0 */ - adiv5_ap_mem_write(ap, addr, 0); + target_mem_write32(target, addr, 0); len -= page_size; addr += page_size; } /* Disable further programming by locking PECR */ - stm32lx_nvm_lock(ap, nvm); + stm32lx_nvm_lock(target, nvm); /* Wait for completion or an error */ while (1) { - uint32_t sr = adiv5_ap_mem_read(ap, STM32Lx_NVM_SR(nvm)); + uint32_t sr = target_mem_read32(target, STM32Lx_NVM_SR(nvm)); if (target_check_error(target)) return -1; if (sr & STM32Lx_NVM_SR_BSY) @@ -764,22 +759,21 @@ static int stm32lx_nvm_data_write(struct target_s* target, const uint8_t* source_8, size_t size) { - ADIv5_AP_t* ap = adiv5_target_ap(target); const uint32_t nvm = stm32lx_nvm_phys(target); const bool is_stm32l1 = stm32lx_is_stm32l1(target); uint32_t* source = (uint32_t*) source_8; - if (!stm32lx_nvm_prog_data_unlock(ap, nvm)) + if (!stm32lx_nvm_prog_data_unlock(target, nvm)) return -1; - adiv5_ap_mem_write(ap, STM32Lx_NVM_PECR(nvm), + target_mem_write32(target, STM32Lx_NVM_PECR(nvm), is_stm32l1 ? 0 : STM32Lx_NVM_PECR_DATA); while (size) { size -= 4; uint32_t v = *source++; - adiv5_ap_mem_write(ap, destination, v); + target_mem_write32(target, destination, v); destination += 4; if (target_check_error(target)) @@ -787,11 +781,11 @@ static int stm32lx_nvm_data_write(struct target_s* target, } /* Disable further programming by locking PECR */ - stm32lx_nvm_lock(ap, nvm); + stm32lx_nvm_lock(target, nvm); /* Wait for completion or an error */ while (1) { - uint32_t sr = adiv5_ap_mem_read(ap, STM32Lx_NVM_SR(nvm)); + uint32_t sr = target_mem_read32(target, STM32Lx_NVM_SR(nvm)); if (target_check_error(target)) return -1; if (sr & STM32Lx_NVM_SR_BSY) @@ -813,16 +807,15 @@ static int stm32lx_nvm_data_write(struct target_s* target, The return value is true if the write succeeded. */ static bool stm32lx_option_write(target *t, uint32_t address, uint32_t value) { - ADIv5_AP_t* ap = adiv5_target_ap(t); const uint32_t nvm = stm32lx_nvm_phys(t); /* Erase and program option in one go. */ - adiv5_ap_mem_write(ap, STM32Lx_NVM_PECR(nvm), STM32Lx_NVM_PECR_FIX); - adiv5_ap_mem_write(ap, address, value); + target_mem_write32(t, STM32Lx_NVM_PECR(nvm), STM32Lx_NVM_PECR_FIX); + target_mem_write32(t, address, value); uint32_t sr; do { - sr = adiv5_ap_mem_read(ap, STM32Lx_NVM_SR(nvm)); + sr = target_mem_read32(t, STM32Lx_NVM_SR(nvm)); } while (sr & STM32Lx_NVM_SR_BSY); return !(sr & STM32Lx_NVM_SR_ERR_M); @@ -839,29 +832,28 @@ static bool stm32lx_option_write(target *t, uint32_t address, uint32_t value) static bool stm32lx_eeprom_write(target *t, uint32_t address, size_t cb, uint32_t value) { - ADIv5_AP_t* ap = adiv5_target_ap(t); const uint32_t nvm = stm32lx_nvm_phys(t); const bool is_stm32l1 = stm32lx_is_stm32l1(t); /* Clear errors. */ - adiv5_ap_mem_write(ap, STM32Lx_NVM_SR(nvm), STM32Lx_NVM_SR_ERR_M); + target_mem_write32(t, STM32Lx_NVM_SR(nvm), STM32Lx_NVM_SR_ERR_M); /* Erase and program option in one go. */ - adiv5_ap_mem_write(ap, STM32Lx_NVM_PECR(nvm), + target_mem_write32(t, STM32Lx_NVM_PECR(nvm), (is_stm32l1 ? 0 : STM32Lx_NVM_PECR_DATA) | STM32Lx_NVM_PECR_FIX); if (cb == 4) - adiv5_ap_mem_write(ap, address, value); + target_mem_write32(t, address, value); else if (cb == 2) - adiv5_ap_mem_write_halfword(ap, address, value); + target_mem_write16(t, address, value); else if (cb == 1) - adiv5_ap_mem_write_byte(ap, address, value); + target_mem_write8(t, address, value); else return false; uint32_t sr; do { - sr = adiv5_ap_mem_read(ap, STM32Lx_NVM_SR(nvm)); + sr = target_mem_read32(t, STM32Lx_NVM_SR(nvm)); } while (sr & STM32Lx_NVM_SR_BSY); return !(sr & STM32Lx_NVM_SR_ERR_M); @@ -888,11 +880,10 @@ static bool stm32lx_cmd_stubs(target* t, static bool stm32lx_cmd_option(target* t, int argc, char** argv) { - ADIv5_AP_t* ap = adiv5_target_ap(t); const uint32_t nvm = stm32lx_nvm_phys(t); const size_t opt_size = stm32lx_nvm_option_size(t); - if (!stm32lx_nvm_opt_unlock(ap, nvm)) { + if (!stm32lx_nvm_opt_unlock(t, nvm)) { gdb_out("unable to unlock NVM option bytes\n"); return true; } @@ -900,7 +891,7 @@ static bool stm32lx_cmd_option(target* t, int argc, char** argv) size_t cb = strlen(argv[1]); if (argc == 2 && !strncasecmp(argv[1], "obl_launch", cb)) { - adiv5_ap_mem_write(ap, STM32Lx_NVM_PECR(nvm), + target_mem_write32(t, STM32Lx_NVM_PECR(nvm), STM32Lx_NVM_PECR_OBL_LAUNCH); } else if (argc == 4 && !strncasecmp(argv[1], "raw", cb)) { @@ -934,7 +925,7 @@ static bool stm32lx_cmd_option(target* t, int argc, char** argv) /* Report the current option values */ for(unsigned i = 0; i < opt_size; i += sizeof(uint32_t)) { uint32_t addr = STM32Lx_NVM_OPT_PHYS + i; - uint32_t val = adiv5_ap_mem_read(ap, addr); + uint32_t val = target_mem_read32(t, addr); gdb_outf("0x%08x: 0x%04x 0x%04x %s\n", addr, val & 0xffff, (val >> 16) & 0xffff, ((val & 0xffff) == ((~val >> 16) & 0xffff)) @@ -942,7 +933,7 @@ static bool stm32lx_cmd_option(target* t, int argc, char** argv) } if (stm32lx_is_stm32l1(t)) { - uint32_t optr = adiv5_ap_mem_read(ap, STM32Lx_NVM_OPTR(nvm)); + uint32_t optr = target_mem_read32(t, STM32Lx_NVM_OPTR(nvm)); uint8_t rdprot = (optr >> STM32L1_NVM_OPTR_RDPROT_S) & STM32L1_NVM_OPTR_RDPROT_M; if (rdprot == STM32L1_NVM_OPTR_RDPROT_0) @@ -964,7 +955,7 @@ static bool stm32lx_cmd_option(target* t, int argc, char** argv) (optr & STM32L1_NVM_OPTR_nBFB2) ? 1 : 0); } else { - uint32_t optr = adiv5_ap_mem_read(ap, STM32Lx_NVM_OPTR(nvm)); + uint32_t optr = target_mem_read32(t, STM32Lx_NVM_OPTR(nvm)); uint8_t rdprot = (optr >> STM32L0_NVM_OPTR_RDPROT_S) & STM32L0_NVM_OPTR_RDPROT_M; if (rdprot == STM32L0_NVM_OPTR_RDPROT_0) @@ -997,17 +988,16 @@ usage: STM32Lx_NVM_OPT_PHYS + opt_size - sizeof(uint32_t)); done: - stm32lx_nvm_lock(ap, nvm); + stm32lx_nvm_lock(t, nvm); return true; } static bool stm32lx_cmd_eeprom(target* t, int argc, char** argv) { - ADIv5_AP_t* ap = adiv5_target_ap(t); const uint32_t nvm = stm32lx_nvm_phys(t); - if (!stm32lx_nvm_prog_data_unlock(ap, nvm)) { + if (!stm32lx_nvm_prog_data_unlock(t, nvm)) { gdb_out("unable to unlock EEPROM\n"); return true; } @@ -1061,6 +1051,6 @@ usage: + stm32lx_nvm_eeprom_size(t)); done: - stm32lx_nvm_lock(ap, nvm); + stm32lx_nvm_lock(t, nvm); return true; } diff --git a/src/stm32l1.c b/src/stm32l1.c index c72cccd..8e63347 100644 --- a/src/stm32l1.c +++ b/src/stm32l1.c @@ -87,7 +87,7 @@ bool stm32l1_probe(struct target_s *target) { uint32_t idcode; - idcode = adiv5_ap_mem_read(adiv5_target_ap(target), STM32L1_DBGMCU_IDCODE); + idcode = target_mem_read32(target, STM32L1_DBGMCU_IDCODE); switch(idcode & 0xFFF) { case 0x416: /* CAT. 1 device */ case 0x429: /* CAT. 2 device */ @@ -105,45 +105,44 @@ bool stm32l1_probe(struct target_s *target) return false; } -static void stm32l1_flash_unlock(ADIv5_AP_t *ap) +static void stm32l1_flash_unlock(target *t) { - adiv5_ap_mem_write(ap, STM32L1_FLASH_PEKEYR, STM32L1_PEKEY1); - adiv5_ap_mem_write(ap, STM32L1_FLASH_PEKEYR, STM32L1_PEKEY2); - adiv5_ap_mem_write(ap, STM32L1_FLASH_PRGKEYR, STM32L1_PRGKEY1); - adiv5_ap_mem_write(ap, STM32L1_FLASH_PRGKEYR, STM32L1_PRGKEY2); + target_mem_write32(t, STM32L1_FLASH_PEKEYR, STM32L1_PEKEY1); + target_mem_write32(t, STM32L1_FLASH_PEKEYR, STM32L1_PEKEY2); + target_mem_write32(t, STM32L1_FLASH_PRGKEYR, STM32L1_PRGKEY1); + target_mem_write32(t, STM32L1_FLASH_PRGKEYR, STM32L1_PRGKEY2); } static int stm32l1_flash_erase(struct target_s *target, uint32_t addr, size_t len) { - ADIv5_AP_t *ap = adiv5_target_ap(target); uint16_t sr; addr &= ~255; len &= ~255; - stm32l1_flash_unlock(ap); + stm32l1_flash_unlock(target); /* Flash page erase instruction */ - adiv5_ap_mem_write(ap, STM32L1_FLASH_PECR, STM32L1_FLASH_PECR_ERASE | STM32L1_FLASH_PECR_PROG); + target_mem_write32(target, STM32L1_FLASH_PECR, STM32L1_FLASH_PECR_ERASE | STM32L1_FLASH_PECR_PROG); /* Read FLASH_SR to poll for BSY bit */ - while(adiv5_ap_mem_read(ap, STM32L1_FLASH_SR) & STM32L1_FLASH_SR_BSY) + while(target_mem_read32(target, STM32L1_FLASH_SR) & STM32L1_FLASH_SR_BSY) if(target_check_error(target)) return -1; while(len) { /* Write first word of page to 0 */ - adiv5_ap_mem_write(ap, addr, 0); + target_mem_write32(target, addr, 0); len -= 256; addr += 256; } /* Disable programming mode */ - adiv5_ap_mem_write(ap, STM32L1_FLASH_PECR, 0); + target_mem_write32(target, STM32L1_FLASH_PECR, 0); /* Check for error */ - sr = adiv5_ap_mem_read(ap, STM32L1_FLASH_SR); + sr = target_mem_read32(target, STM32L1_FLASH_SR); if ((sr & STM32L1_FLASH_SR_ERROR_MASK) || !(sr & STM32L1_FLASH_SR_EOP)) return -1; @@ -153,7 +152,6 @@ static int stm32l1_flash_erase(struct target_s *target, uint32_t addr, size_t le static int stm32l1_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, size_t len) { - ADIv5_AP_t *ap = adiv5_target_ap(target); uint16_t sr; /* Handle non word-aligned start */ @@ -164,7 +162,7 @@ static int stm32l1_flash_write(struct target_s *target, uint32_t dest, wlen = len; memcpy((uint8_t *)&data + (dest & 3), src, wlen); - adiv5_ap_mem_write(ap, dest & ~3, data); + target_mem_write32(target, dest & ~3, data); src += wlen; dest += wlen; len -= wlen; @@ -185,10 +183,10 @@ static int stm32l1_flash_write(struct target_s *target, uint32_t dest, /* Write half-pages */ if(len > 128) { /* Enable half page mode */ - adiv5_ap_mem_write(ap, STM32L1_FLASH_PECR, STM32L1_FLASH_PECR_FPRG | STM32L1_FLASH_PECR_PROG); + target_mem_write32(target, STM32L1_FLASH_PECR, STM32L1_FLASH_PECR_FPRG | STM32L1_FLASH_PECR_PROG); /* Read FLASH_SR to poll for BSY bit */ - while(adiv5_ap_mem_read(ap, STM32L1_FLASH_SR) & STM32L1_FLASH_SR_BSY) + while(target_mem_read32(target, STM32L1_FLASH_SR) & STM32L1_FLASH_SR_BSY) if(target_check_error(target)) return -1; @@ -198,10 +196,10 @@ static int stm32l1_flash_write(struct target_s *target, uint32_t dest, len -= len & ~127; /* Disable half page mode */ - adiv5_ap_mem_write(ap, STM32L1_FLASH_PECR, 0); + target_mem_write32(target, STM32L1_FLASH_PECR, 0); /* Read FLASH_SR to poll for BSY bit */ - while(adiv5_ap_mem_read(ap, STM32L1_FLASH_SR) & STM32L1_FLASH_SR_BSY) + while(target_mem_read32(target, STM32L1_FLASH_SR) & STM32L1_FLASH_SR_BSY) if(target_check_error(target)) return -1; } @@ -219,11 +217,11 @@ static int stm32l1_flash_write(struct target_s *target, uint32_t dest, uint32_t data = 0; memcpy((uint8_t *)&data, src, len); - adiv5_ap_mem_write(ap, dest, data); + target_mem_write32(target, dest, data); } /* Check for error */ - sr = adiv5_ap_mem_read(ap, STM32L1_FLASH_SR); + sr = target_mem_read32(target, STM32L1_FLASH_SR); if ((sr & STM32L1_FLASH_SR_ERROR_MASK) || !(sr & STM32L1_FLASH_SR_EOP)) return -1; -- cgit v1.2.3 From c3f798438a65b284adec281e7ddb4e8268ff4f4b Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sun, 15 Mar 2015 17:12:31 -0700 Subject: Remove abstraction of adiv5_dp_write. Both implementations were identical. --- src/adiv5.c | 5 +++++ src/adiv5_jtagdp.c | 7 ------- src/adiv5_swdp.c | 9 +-------- src/include/adiv5.h | 7 +------ 4 files changed, 7 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/adiv5.c b/src/adiv5.c index 2179ca6..f2421ce 100644 --- a/src/adiv5.c +++ b/src/adiv5.c @@ -70,6 +70,11 @@ void adiv5_ap_unref(ADIv5_AP_t *ap) } } +void adiv5_dp_write(ADIv5_DP_t *dp, uint16_t addr, uint32_t value) +{ + dp->low_access(dp, ADIV5_LOW_WRITE, addr, value); +} + void adiv5_dp_init(ADIv5_DP_t *dp) { uint32_t ctrlstat; diff --git a/src/adiv5_jtagdp.c b/src/adiv5_jtagdp.c index eb60caa..5049e3c 100644 --- a/src/adiv5_jtagdp.c +++ b/src/adiv5_jtagdp.c @@ -36,7 +36,6 @@ #define IR_DPACC 0xA #define IR_APACC 0xB -static void adiv5_jtagdp_write(ADIv5_DP_t *dp, uint16_t addr, uint32_t value); static uint32_t adiv5_jtagdp_read(ADIv5_DP_t *dp, uint16_t addr); static uint32_t adiv5_jtagdp_error(ADIv5_DP_t *dp); @@ -52,7 +51,6 @@ void adiv5_jtag_dp_handler(jtag_dev_t *dev) dp->dev = dev; dp->idcode = dev->idcode; - dp->dp_write = adiv5_jtagdp_write; dp->dp_read = adiv5_jtagdp_read; dp->error = adiv5_jtagdp_error; dp->low_access = adiv5_jtagdp_low_access; @@ -60,11 +58,6 @@ void adiv5_jtag_dp_handler(jtag_dev_t *dev) adiv5_dp_init(dp); } -static void adiv5_jtagdp_write(ADIv5_DP_t *dp, uint16_t addr, uint32_t value) -{ - adiv5_jtagdp_low_access(dp, ADIV5_LOW_WRITE, addr, value); -} - static uint32_t adiv5_jtagdp_read(ADIv5_DP_t *dp, uint16_t addr) { adiv5_jtagdp_low_access(dp, ADIV5_LOW_READ, addr, 0); diff --git a/src/adiv5_swdp.c b/src/adiv5_swdp.c index 3e775cc..9ac791a 100644 --- a/src/adiv5_swdp.c +++ b/src/adiv5_swdp.c @@ -33,7 +33,6 @@ #define SWDP_ACK_WAIT 0x02 #define SWDP_ACK_FAULT 0x04 -static void adiv5_swdp_write(ADIv5_DP_t *dp, uint16_t addr, uint32_t value); static uint32_t adiv5_swdp_read(ADIv5_DP_t *dp, uint16_t addr); static uint32_t adiv5_swdp_error(ADIv5_DP_t *dp); @@ -64,7 +63,6 @@ int adiv5_swdp_scan(void) return -1; } - dp->dp_write = adiv5_swdp_write; dp->dp_read = adiv5_swdp_read; dp->error = adiv5_swdp_error; dp->low_access = adiv5_swdp_low_access; @@ -78,11 +76,6 @@ int adiv5_swdp_scan(void) return target_list?1:0; } -static void adiv5_swdp_write(ADIv5_DP_t *dp, uint16_t addr, uint32_t value) -{ - adiv5_swdp_low_access(dp, ADIV5_LOW_WRITE, addr, value); -} - static uint32_t adiv5_swdp_read(ADIv5_DP_t *dp, uint16_t addr) { if (addr & ADIV5_APnDP) { @@ -111,7 +104,7 @@ static uint32_t adiv5_swdp_error(ADIv5_DP_t *dp) if(err & ADIV5_DP_CTRLSTAT_WDATAERR) clr |= ADIV5_DP_ABORT_WDERRCLR; - adiv5_swdp_write(dp, ADIV5_DP_ABORT, clr); + adiv5_dp_write(dp, ADIV5_DP_ABORT, clr); dp->fault = 0; return err; diff --git a/src/include/adiv5.h b/src/include/adiv5.h index 4bc3905..6896f6d 100644 --- a/src/include/adiv5.h +++ b/src/include/adiv5.h @@ -109,7 +109,6 @@ typedef struct ADIv5_DP_s { bool allow_timeout; - void (*dp_write)(struct ADIv5_DP_s *dp, uint16_t addr, uint32_t value); uint32_t (*dp_read)(struct ADIv5_DP_s *dp, uint16_t addr); uint32_t (*error)(struct ADIv5_DP_s *dp); @@ -123,11 +122,6 @@ typedef struct ADIv5_DP_s { }; } ADIv5_DP_t; -static inline void adiv5_dp_write(ADIv5_DP_t *dp, uint16_t addr, uint32_t value) -{ - dp->dp_write(dp, addr, value); -} - static inline uint32_t adiv5_dp_read(ADIv5_DP_t *dp, uint16_t addr) { return dp->dp_read(dp, addr); @@ -160,6 +154,7 @@ typedef struct ADIv5_AP_s { } ADIv5_AP_t; void adiv5_dp_init(ADIv5_DP_t *dp); +void adiv5_dp_write(ADIv5_DP_t *dp, uint16_t addr, uint32_t value); void adiv5_dp_ref(ADIv5_DP_t *dp); void adiv5_ap_ref(ADIv5_AP_t *ap); -- cgit v1.2.3 From f5f87bf70f968d9aea2eee31e8003a6304041480 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sun, 15 Mar 2015 20:36:58 -0700 Subject: Build for stlink with -Os. --- src/Makefile | 6 ++++-- src/platforms/stlink/Makefile.inc | 1 + 2 files changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 80e86fe..02b5690 100644 --- a/src/Makefile +++ b/src/Makefile @@ -9,8 +9,10 @@ endif BUILDDATE := `date +"%Y%m%d"` -CFLAGS += -Wall -Wextra -Wno-char-subscripts\ - -O2 -std=gnu99 -g3 -DBUILDDATE=\"$(BUILDDATE)\"\ +OPT_FLAGS ?= -O2 + +CFLAGS += -Wall -Wextra -Werror -Wno-char-subscripts\ + $(OPT_FLAGS) -std=gnu99 -g3 -DBUILDDATE=\"$(BUILDDATE)\"\ -I. -Iinclude -Iplatforms/common -I$(PLATFORM_DIR) \ -DVERSION_SUFFIX=\"`../scripts/setlocalversion`\" -MD diff --git a/src/platforms/stlink/Makefile.inc b/src/platforms/stlink/Makefile.inc index 40635cf..689c11e 100644 --- a/src/platforms/stlink/Makefile.inc +++ b/src/platforms/stlink/Makefile.inc @@ -2,6 +2,7 @@ CROSS_COMPILE ?= arm-none-eabi- CC = $(CROSS_COMPILE)gcc OBJCOPY = $(CROSS_COMPILE)objcopy +OPT_FLAGS = -Os CFLAGS += -mcpu=cortex-m3 -mthumb \ -DSTM32F1 -DDISCOVERY_STLINK -I../libopencm3/include \ -I platforms/stm32 -- cgit v1.2.3 From 018d9cce806ba96768fccec65bb6570943207c76 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Tue, 17 Mar 2015 21:19:02 -0700 Subject: Check vasprintf return value. --- src/gdb_packet.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/gdb_packet.c b/src/gdb_packet.c index fb3335e..9ce63f2 100644 --- a/src/gdb_packet.c +++ b/src/gdb_packet.c @@ -159,7 +159,8 @@ void gdb_outf(const char *fmt, ...) char *buf; va_start(ap, fmt); - vasprintf(&buf, fmt, ap); + if (vasprintf(&buf, fmt, ap) < 0) + return; gdb_out(buf); free(buf); va_end(ap); -- cgit v1.2.3 From 0bf7778759c8f23e60011e403343d977e51f58a9 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Tue, 17 Mar 2015 10:31:48 -0700 Subject: samd: Remove low level ADIv5 calls an favour of target_mem_write. --- src/samd.c | 31 +++++++------------------------ 1 file changed, 7 insertions(+), 24 deletions(-) (limited to 'src') diff --git a/src/samd.c b/src/samd.c index 68f5bc4..6ab8140 100644 --- a/src/samd.c +++ b/src/samd.c @@ -508,7 +508,6 @@ static int samd_flash_erase(struct target_s *target, uint32_t addr, size_t len) static int samd_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, size_t len) { - ADIv5_AP_t *ap = adiv5_target_ap(target); /* Find the size of our 32-bit data buffer */ uint32_t offset = dest % 4; uint32_t words = (offset + len + 3) / 4; @@ -534,42 +533,26 @@ static int samd_flash_write(struct target_s *target, uint32_t dest, end_of_this_page = page + (SAMD_PAGE_SIZE - 4); if (addr > page || (page == last_page && end < end_of_this_page)) { - /* Setup write */ - adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw | - ADIV5_AP_CSW_SIZE_WORD | ADIV5_AP_CSW_ADDRINC_SINGLE); - adiv5_ap_write(ap, ADIV5_AP_TAR, addr); - adiv5_dp_write(ap->dp, ADIV5_DP_SELECT, - ((uint32_t)ap->apsel << 24)|(ADIV5_AP_DRW & 0xF0)); - /* Partial, manual page write */ - for (; addr <= MINIMUM(end, end_of_this_page); addr += 4, i++) { - adiv5_dp_write(ap->dp, ADIV5_AP_DRW, data[i]); - } + target_mem_write(target, addr, &data[i], + MINIMUM(end, end_of_this_page)); /* Unlock */ samd_unlock_current_address(target); /* Issue the write page command */ target_mem_write32(target, SAMD_NVMC_CTRLA, - SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_WRITEPAGE); + SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_WRITEPAGE); } else { /* Write first word to set address */ - target_mem_write32(target, addr, data[i]); addr += 4; i++; + target_mem_write32(target, addr, data[i]); + addr += 4; i++; /* Unlock */ samd_unlock_current_address(target); - /* Set up write */ - adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw | - ADIV5_AP_CSW_SIZE_WORD | ADIV5_AP_CSW_ADDRINC_SINGLE); - adiv5_ap_write(ap, ADIV5_AP_TAR, addr); - adiv5_dp_write(ap->dp, ADIV5_DP_SELECT, - ((uint32_t)ap->apsel << 24)|(ADIV5_AP_DRW & 0xF0)); - - /* Full, automatic page write */ - for (; addr < page + SAMD_PAGE_SIZE; addr += 4, i++) { - adiv5_dp_write(ap->dp, ADIV5_AP_DRW, data[i]); - } + target_mem_write(target, addr, &data[i], + MINIMUM(end, end_of_this_page)); } /* Poll for NVM Ready */ -- cgit v1.2.3 From 1366c32f89b419d8002fc79a90915bde70bf495c Mon Sep 17 00:00:00 2001 From: Richard Meadows Date: Tue, 17 Mar 2015 22:49:01 +0000 Subject: samd: Simplified samd_flash_write further by always using manual writes. Tested on all three devices as listed at the top of samd.c --- src/samd.c | 38 +++++++++++++++----------------------- 1 file changed, 15 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/samd.c b/src/samd.c index 6ab8140..a37a739 100644 --- a/src/samd.c +++ b/src/samd.c @@ -526,34 +526,26 @@ static int samd_flash_write(struct target_s *target, uint32_t dest, uint32_t first_page = dest & ~(SAMD_PAGE_SIZE - 1); /* The start address of the last page involved in the write */ uint32_t last_page = (dest + len - 1) & ~(SAMD_PAGE_SIZE - 1); - uint32_t end_of_this_page; - + uint32_t next_page; + uint32_t length; for (uint32_t page = first_page; page <= last_page; page += SAMD_PAGE_SIZE) { - end_of_this_page = page + (SAMD_PAGE_SIZE - 4); - - if (addr > page || (page == last_page && end < end_of_this_page)) { - /* Partial, manual page write */ - target_mem_write(target, addr, &data[i], - MINIMUM(end, end_of_this_page)); + next_page = page + SAMD_PAGE_SIZE; + length = MINIMUM(end + 4, next_page) - addr; - /* Unlock */ - samd_unlock_current_address(target); + /* Write within a single page. This may be part or all of the page */ + target_mem_write(target, addr, &data[i], length); + addr += length; i += (length >> 2); - /* Issue the write page command */ - target_mem_write32(target, SAMD_NVMC_CTRLA, - SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_WRITEPAGE); - } else { - /* Write first word to set address */ - target_mem_write32(target, addr, data[i]); - addr += 4; i++; + /* If MANW=0 (default) we may have triggered an automatic + * write. Ignore this */ - /* Unlock */ - samd_unlock_current_address(target); + /* Unlock */ + samd_unlock_current_address(target); - target_mem_write(target, addr, &data[i], - MINIMUM(end, end_of_this_page)); - } + /* Issue the write page command */ + target_mem_write32(target, SAMD_NVMC_CTRLA, + SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_WRITEPAGE); /* Poll for NVM Ready */ while ((target_mem_read32(target, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0) @@ -572,7 +564,7 @@ static int samd_flash_write(struct target_s *target, uint32_t dest, */ static bool samd_cmd_erase_all(target *t) { - /* Clear the DSU status bits */ + /* Clear the DSU status bits */ target_mem_write32(t, SAMD_DSU_CTRLSTAT, (SAMD_STATUSA_DONE | SAMD_STATUSA_PERR | SAMD_STATUSA_FAIL)); -- cgit v1.2.3 From 5c337c9aa7274f64b78849e350ef0d6c859437c5 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Tue, 17 Mar 2015 20:54:41 -0700 Subject: Whitespace. --- src/samd.c | 70 ++++++++++++++++++++++++++++++++++---------------------------- 1 file changed, 39 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/samd.c b/src/samd.c index a37a739..c257fe2 100644 --- a/src/samd.c +++ b/src/samd.c @@ -59,7 +59,7 @@ const struct command_s samd_cmd_list[] = { {"user_row", (cmd_handler)samd_cmd_read_userrow, "Prints user row from flash"}, {"serial", (cmd_handler)samd_cmd_serial, "Prints serial number"}, {"mbist", (cmd_handler)samd_cmd_mbist, "Runs the built-in memory test"}, - {"set_security_bit", (cmd_handler)samd_cmd_ssb, "Sets the Security Bit"}, + {"set_security_bit", (cmd_handler)samd_cmd_ssb, "Sets the Security Bit"}, {NULL, NULL, NULL} }; @@ -222,14 +222,14 @@ samd_reset(struct target_s *target) * or SYSRESETREQ: 0x05FA0004 (system reset) */ target_mem_write32(target, CORTEXM_AIRCR, - CORTEXM_AIRCR_VECTKEY | CORTEXM_AIRCR_SYSRESETREQ); + CORTEXM_AIRCR_VECTKEY | CORTEXM_AIRCR_SYSRESETREQ); /* Exit extended reset */ if (target_mem_read32(target, SAMD_DSU_CTRLSTAT) & SAMD_STATUSA_CRSTEXT) { /* Write bit to clear from extended reset */ target_mem_write32(target, SAMD_DSU_CTRLSTAT, - SAMD_STATUSA_CRSTEXT); + SAMD_STATUSA_CRSTEXT); } /* Poll for release from reset */ @@ -301,10 +301,10 @@ samd_protected_attach(struct target_s *target) * regain access to the chip. */ - /* Patch back in the normal cortexm attach for next time */ - target->attach = cortexm_attach; + /* Patch back in the normal cortexm attach for next time */ + target->attach = cortexm_attach; - /* Allow attach this time */ + /* Allow attach this time */ return true; } @@ -387,11 +387,11 @@ bool samd_probe(struct target_s *target) SAMD_DSU_CTRLSTAT); struct samd_descr samd = samd_parse_device_id(did); - /* Protected? */ - int protected = (ctrlstat & SAMD_STATUSB_PROT); + /* Protected? */ + int protected = (ctrlstat & SAMD_STATUSB_PROT); /* Part String */ - if (protected) { + if (protected) { sprintf(variant_string, "Atmel SAMD%d%c%dA%s (rev %c) (PROT=1)", samd.series, samd.pin, samd.mem, @@ -401,7 +401,7 @@ bool samd_probe(struct target_s *target) "Atmel SAMD%d%c%dA%s (rev %c)", samd.series, samd.pin, samd.mem, samd.package, samd.revision); - } + } /* Setup Target */ target->driver = variant_string; @@ -489,7 +489,7 @@ static int samd_flash_erase(struct target_s *target, uint32_t addr, size_t len) SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_ERASEROW); /* Poll for NVM Ready */ while ((target_mem_read32(target, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0) - if(target_check_error(target)) + if (target_check_error(target)) return -1; /* Lock */ @@ -534,22 +534,22 @@ static int samd_flash_write(struct target_s *target, uint32_t dest, length = MINIMUM(end + 4, next_page) - addr; /* Write within a single page. This may be part or all of the page */ - target_mem_write(target, addr, &data[i], length); - addr += length; i += (length >> 2); + target_mem_write(target, addr, &data[i], length); + addr += length; i += (length >> 2); - /* If MANW=0 (default) we may have triggered an automatic - * write. Ignore this */ + /* If MANW=0 (default) we may have triggered an automatic + * write. Ignore this */ - /* Unlock */ - samd_unlock_current_address(target); + /* Unlock */ + samd_unlock_current_address(target); - /* Issue the write page command */ - target_mem_write32(target, SAMD_NVMC_CTRLA, - SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_WRITEPAGE); + /* Issue the write page command */ + target_mem_write32(target, SAMD_NVMC_CTRLA, + SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_WRITEPAGE); /* Poll for NVM Ready */ while ((target_mem_read32(target, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0) - if(target_check_error(target)) + if (target_check_error(target)) return -1; /* Lock */ @@ -564,9 +564,10 @@ static int samd_flash_write(struct target_s *target, uint32_t dest, */ static bool samd_cmd_erase_all(target *t) { - /* Clear the DSU status bits */ + /* Clear the DSU status bits */ target_mem_write32(t, SAMD_DSU_CTRLSTAT, - (SAMD_STATUSA_DONE | SAMD_STATUSA_PERR | SAMD_STATUSA_FAIL)); + SAMD_STATUSA_DONE | SAMD_STATUSA_PERR | + SAMD_STATUSA_FAIL); /* Erase all */ target_mem_write32(t, SAMD_DSU_CTRLSTAT, SAMD_CTRL_CHIP_ERASE); @@ -575,7 +576,7 @@ static bool samd_cmd_erase_all(target *t) uint32_t status; while (((status = target_mem_read32(t, SAMD_DSU_CTRLSTAT)) & (SAMD_STATUSA_DONE | SAMD_STATUSA_PERR | SAMD_STATUSA_FAIL)) == 0) - if(target_check_error(t)) + if (target_check_error(t)) return false; /* Test the protection error bit in Status A */ @@ -617,7 +618,7 @@ static bool samd_set_flashlock(target *t, uint16_t value) /* Poll for NVM Ready */ while ((target_mem_read32(t, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0) - if(target_check_error(t)) + if (target_check_error(t)) return -1; /* Modify the high byte of the user row */ @@ -631,16 +632,19 @@ static bool samd_set_flashlock(target *t, uint16_t value) target_mem_write32(t, SAMD_NVMC_CTRLA, SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_WRITEAUXPAGE); - return true; + return true; } + static bool samd_cmd_lock_flash(target *t) { return samd_set_flashlock(t, 0x0000); } + static bool samd_cmd_unlock_flash(target *t) { return samd_set_flashlock(t, 0xFFFF); } + static bool samd_cmd_read_userrow(target *t) { gdb_outf("User Row: 0x%08x%08x\n", @@ -649,6 +653,7 @@ static bool samd_cmd_read_userrow(target *t) return true; } + /** * Reads the 128-bit serial number from the NVM */ @@ -664,6 +669,7 @@ static bool samd_cmd_serial(target *t) return true; } + /** * Returns the size (in bytes) of the current SAM D20's flash memory. */ @@ -678,6 +684,7 @@ static uint32_t samd_flash_size(target *t) /* Shift the maximum flash size (256KB) down as appropriate */ return (0x40000 >> (devsel % 5)); } + /** * Runs the Memory Built In Self Test (MBIST) */ @@ -697,7 +704,7 @@ static bool samd_cmd_mbist(target *t) uint32_t status; while (((status = target_mem_read32(t, SAMD_DSU_CTRLSTAT)) & (SAMD_STATUSA_DONE | SAMD_STATUSA_PERR | SAMD_STATUSA_FAIL)) == 0) - if(target_check_error(t)) + if (target_check_error(t)) return false; /* Test the protection error bit in Status A */ @@ -709,7 +716,7 @@ static bool samd_cmd_mbist(target *t) /* Test the fail bit in Status A */ if (status & SAMD_STATUSA_FAIL) { gdb_outf("MBIST Fail @ 0x%08x\n", - target_mem_read32(t, SAMD_DSU_ADDRESS)); + target_mem_read32(t, SAMD_DSU_ADDRESS)); } else { gdb_outf("MBIST Passed!\n"); } @@ -725,9 +732,9 @@ static bool samd_cmd_ssb(target *t) target_mem_write32(t, SAMD_NVMC_CTRLA, SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_SSB); - /* Poll for NVM Ready */ - while ((target_mem_read32(t, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0) - if(target_check_error(t)) + /* Poll for NVM Ready */ + while ((target_mem_read32(t, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0) + if (target_check_error(t)) return -1; gdb_outf("Set the security bit! " @@ -735,3 +742,4 @@ static bool samd_cmd_ssb(target *t) return true; } + -- cgit v1.2.3 From 1de685198c2dc7792bb5808989afb268203d1ded Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Tue, 17 Mar 2015 20:56:21 -0700 Subject: Flatten samd_probe. --- src/samd.c | 144 ++++++++++++++++++++++++++++++------------------------------- 1 file changed, 71 insertions(+), 73 deletions(-) (limited to 'src') diff --git a/src/samd.c b/src/samd.c index c257fe2..e12bcc9 100644 --- a/src/samd.c +++ b/src/samd.c @@ -374,82 +374,80 @@ bool samd_probe(struct target_s *target) uint32_t pid = samd_read_pid(target); /* Check the ARM Coresight Component and Perhiperal IDs */ - if (cid == SAMD_CID_VALUE && - (pid & SAMD_PID_MASK) == SAMD_PID_CONST_VALUE) { - - /* Read the Device ID */ - uint32_t did = target_mem_read32(target, SAMD_DSU_DID); - - /* If the Device ID matches */ - if ((did & SAMD_DID_MASK) == SAMD_DID_CONST_VALUE) { - - uint32_t ctrlstat = target_mem_read32(target, - SAMD_DSU_CTRLSTAT); - struct samd_descr samd = samd_parse_device_id(did); - - /* Protected? */ - int protected = (ctrlstat & SAMD_STATUSB_PROT); - - /* Part String */ - if (protected) { - sprintf(variant_string, - "Atmel SAMD%d%c%dA%s (rev %c) (PROT=1)", - samd.series, samd.pin, samd.mem, - samd.package, samd.revision); - } else { - sprintf(variant_string, - "Atmel SAMD%d%c%dA%s (rev %c)", - samd.series, samd.pin, samd.mem, - samd.package, samd.revision); - } - - /* Setup Target */ - target->driver = variant_string; - target->reset = samd_reset; - - if (samd.series == 20 && samd.revision == 'B') { - /** - * These functions check for and - * extended reset. Appears to be - * related to Errata 35.4.1 ref 12015 - */ - target->detach = samd20_revB_detach; - target->halt_resume = samd20_revB_halt_resume; - } - if (protected) { - /** - * Overload the default cortexm attach - * for when the samd is protected. - * This function allows users to - * attach on a temporary basis so they - * can rescue the device. - */ - target->attach = samd_protected_attach; - } - - target->xml_mem_map = samd_xml_memory_map; - target->flash_erase = samd_flash_erase; - target->flash_write = samd_flash_write; - target_add_commands(target, samd_cmd_list, "SAMD"); - - /* If we're not in reset here */ - if (!connect_assert_srst) { - /* We'll have to release the target from - * extended reset to make attach possible */ - if (target_mem_read32(target, SAMD_DSU_CTRLSTAT) & - SAMD_STATUSA_CRSTEXT) { - - /* Write bit to clear from extended reset */ - target_mem_write32(target, SAMD_DSU_CTRLSTAT, - SAMD_STATUSA_CRSTEXT); - } - } - - return true; + if ((cid != SAMD_CID_VALUE) || + ((pid & SAMD_PID_MASK) != SAMD_PID_CONST_VALUE)) + return false; + + /* Read the Device ID */ + uint32_t did = target_mem_read32(target, SAMD_DSU_DID); + + /* If the Device ID matches */ + if ((did & SAMD_DID_MASK) != SAMD_DID_CONST_VALUE) + return false; + + uint32_t ctrlstat = target_mem_read32(target, + SAMD_DSU_CTRLSTAT); + struct samd_descr samd = samd_parse_device_id(did); + + /* Protected? */ + bool protected = (ctrlstat & SAMD_STATUSB_PROT); + + /* Part String */ + if (protected) { + sprintf(variant_string, + "Atmel SAMD%d%c%dA%s (rev %c) (PROT=1)", + samd.series, samd.pin, samd.mem, + samd.package, samd.revision); + } else { + sprintf(variant_string, + "Atmel SAMD%d%c%dA%s (rev %c)", + samd.series, samd.pin, samd.mem, + samd.package, samd.revision); + } + + /* Setup Target */ + target->driver = variant_string; + target->reset = samd_reset; + + if (samd.series == 20 && samd.revision == 'B') { + /** + * These functions check for and + * extended reset. Appears to be + * related to Errata 35.4.1 ref 12015 + */ + target->detach = samd20_revB_detach; + target->halt_resume = samd20_revB_halt_resume; + } + if (protected) { + /** + * Overload the default cortexm attach + * for when the samd is protected. + * This function allows users to + * attach on a temporary basis so they + * can rescue the device. + */ + target->attach = samd_protected_attach; + } + + target->xml_mem_map = samd_xml_memory_map; + target->flash_erase = samd_flash_erase; + target->flash_write = samd_flash_write; + target_add_commands(target, samd_cmd_list, "SAMD"); + + /* If we're not in reset here */ + if (!connect_assert_srst) { + /* We'll have to release the target from + * extended reset to make attach possible */ + if (target_mem_read32(target, SAMD_DSU_CTRLSTAT) & + SAMD_STATUSA_CRSTEXT) { + + /* Write bit to clear from extended reset */ + target_mem_write32(target, SAMD_DSU_CTRLSTAT, + SAMD_STATUSA_CRSTEXT); } } - return false; + return true; } /** -- cgit v1.2.3 From e380ced5171dc3c9098005924f61051a43b79428 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sun, 8 Mar 2015 11:51:59 -0700 Subject: Change STM32F1 driver to use generated stub. --- flashstub/stm32.stub | 1 + src/stm32f1.c | 35 +---------------------------------- 2 files changed, 2 insertions(+), 34 deletions(-) create mode 100644 flashstub/stm32.stub (limited to 'src') diff --git a/flashstub/stm32.stub b/flashstub/stm32.stub new file mode 100644 index 0000000..755f445 --- /dev/null +++ b/flashstub/stm32.stub @@ -0,0 +1 @@ +0x4809, 0x490A, 0x467A, 0x322C, 0x4B09, 0x2501, 0x2B00, 0xD00A, 0x6105, 0x8814, 0x800C, 0x68C4, 0x2601, 0x4234, 0xD1FB, 0x3B02, 0x3102, 0x3202, 0xE7F2, 0xBE00, 0x2000, 0x4002, 0x0000, 0x0000, 0x000C, 0x0000, 0xAAAA, 0xAAAA, 0xBBBB, 0xBBBB, 0xCCCC, 0xCCCC, \ No newline at end of file diff --git a/src/stm32f1.c b/src/stm32f1.c index a746d5d..0e87c21 100644 --- a/src/stm32f1.c +++ b/src/stm32f1.c @@ -120,40 +120,7 @@ static const char stm32hd_xml_memory_map[] = "" #define DBGMCU_IDCODE_F0 0x40015800 static const uint16_t stm32f1_flash_write_stub[] = { -// _start: - 0x4809, // ldr r0, [pc, #36] // _flashbase - 0x490a, // ldr r1, [pc, #40] // _addr - 0x467a, // mov r2, pc - 0x322c, // adds r2, #44 - 0x4b09, // ldr r3, [pc, #36] // _size - 0x2501, // movs r5, #1 -// _next: - 0x2b00, // cmp r3, #0 - 0xd00a, // beq _done - 0x6105, // str r5, [r0, #16] - 0x8814, // ldrh r4, [r2] - 0x800c, // strh r4, [r1] -// _wait: - 0x68c4, // ldr r4, [r0, #12] - 0x2601, // movs r6, #1 - 0x4234, // tst r4, r6 - 0xd1fb, // bne _wait - - 0x3b02, // subs r3, #2 - 0x3102, // adds r1, #2 - 0x3202, // adds r2, #2 - 0xe7f2, // b _next -// _done: - 0xbe00, // bkpt -// .org 0x28 -// _flashbase: - 0x2000, 0x4002, // .word 0x40022000 (FPEC_BASE) -// _addr: -// 0x0000, 0x0000, -// _size: -// 0x0000, 0x0000, -// _data: -// ... +#include "../flashstub/stm32.stub" }; bool stm32f1_probe(struct target_s *target) -- cgit v1.2.3 From c2462a6788c119edd9995fa46f1316a9c0431e0b Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sun, 8 Mar 2015 12:55:59 -0700 Subject: Add cortexm generic stub call, and use in stm32f1 driver. --- src/cortexm.c | 30 +++++++++++++++++++++++++++++- src/include/cortexm.h | 3 +++ src/stm32f1.c | 13 +++++-------- 3 files changed, 37 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/cortexm.c b/src/cortexm.c index 4bfb4d9..0327edc 100644 --- a/src/cortexm.c +++ b/src/cortexm.c @@ -603,6 +603,35 @@ static int cortexm_fault_unwind(struct target_s *target) return 0; } +int cortexm_run_stub(struct target_s *target, uint32_t loadaddr, + const uint16_t *stub, uint32_t stublen, + uint32_t r0, uint32_t r1, uint32_t r2, uint32_t r3) +{ + uint32_t regs[target->regs_size / 4]; + + memset(regs, 0, sizeof(regs)); + regs[0] = r0; + regs[1] = r1; + regs[2] = r2; + regs[3] = r3; + regs[15] = loadaddr; + regs[16] = 0x1000000; + regs[19] = 0; + + target_mem_write(target, loadaddr, stub, stublen); + cortexm_regs_write(target, regs); + + if (target_check_error(target)) + return -1; + + /* Execute the stub */ + cortexm_halt_resume(target, 0); + while (!cortexm_halt_wait(target)) + ; + + return 0; +} + /* The following routines implement hardware breakpoints. * The Flash Patch and Breakpoint (FPB) system is used. */ @@ -648,7 +677,6 @@ cortexm_clear_hw_bp(struct target_s *target, uint32_t addr) return 0; } - /* The following routines implement hardware watchpoints. * The Data Watch and Trace (DWT) system is used. */ diff --git a/src/include/cortexm.h b/src/include/cortexm.h index 1fd77e6..8f4d45d 100644 --- a/src/include/cortexm.h +++ b/src/include/cortexm.h @@ -146,6 +146,9 @@ bool cortexm_attach(struct target_s *target); void cortexm_detach(struct target_s *target); void cortexm_halt_resume(struct target_s *target, bool step); +int cortexm_run_stub(struct target_s *target, uint32_t loadaddr, + const uint16_t *stub, uint32_t stublen, + uint32_t r0, uint32_t r1, uint32_t r2, uint32_t r3); #endif diff --git a/src/stm32f1.c b/src/stm32f1.c index 0e87c21..daba1b0 100644 --- a/src/stm32f1.c +++ b/src/stm32f1.c @@ -32,9 +32,12 @@ #include "general.h" #include "adiv5.h" #include "target.h" +#include "cortexm.h" #include "command.h" #include "gdb_packet.h" +#define SRAM_BASE 0x20000000 + static bool stm32f1_cmd_erase_mass(target *t); static bool stm32f1_cmd_option(target *t, int argc, char *argv[]); @@ -257,15 +260,9 @@ static int stm32f1_flash_write(struct target_s *target, uint32_t dest, memcpy((uint8_t *)&data[2] + offset, src, len); /* Write stub and data to target ram and set PC */ - target_mem_write(target, 0x20000000, stm32f1_flash_write_stub, 0x2C); target_mem_write(target, 0x2000002C, data, sizeof(data)); - target_pc_write(target, 0x20000000); - if(target_check_error(target)) - return -1; - - /* Execute the stub */ - target_halt_resume(target, 0); - while(!target_halt_wait(target)); + cortexm_run_stub(target, SRAM_BASE, stm32f1_flash_write_stub, 0x2C, + 0, 0, 0, 0); /* Check for error */ if (target_mem_read32(target, FLASH_SR) & SR_ERROR_MASK) -- cgit v1.2.3 From 437aedda11a112407af7b3f7884090023944faef Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sun, 8 Mar 2015 13:35:07 -0700 Subject: Rewrote stm32f1 stub in C and call with parameters in registers. --- flashstub/Makefile | 6 +++++- flashstub/stm32.s | 43 ------------------------------------------- flashstub/stm32.stub | 1 - flashstub/stm32f1.c | 34 ++++++++++++++++++++++++++++++++++ flashstub/stm32f1.stub | 1 + src/include/general.h | 2 ++ src/stm32f1.c | 27 ++++++++++++--------------- 7 files changed, 54 insertions(+), 60 deletions(-) delete mode 100644 flashstub/stm32.s delete mode 100644 flashstub/stm32.stub create mode 100644 flashstub/stm32f1.c create mode 100644 flashstub/stm32f1.stub (limited to 'src') diff --git a/flashstub/Makefile b/flashstub/Makefile index cb6f693..eeb1803 100644 --- a/flashstub/Makefile +++ b/flashstub/Makefile @@ -11,7 +11,11 @@ endif CFLAGS=-mcpu=cortex-m3 -mthumb -I../libopencm3/include ASFLAGS=-mcpu=cortex-m3 -mthumb -all: lmi.stub stm32.stub stm32f4.stub nrf51.stub +all: lmi.stub stm32f4.stub nrf51.stub stm32f1.stub + +stm32f1.o: stm32f1.c + $(Q)echo " CC $<" + $(Q)$(CC) $(CFLAGS) -DSTM32F1 -o $@ -c $< %.o: %.s $(Q)echo " AS $<" diff --git a/flashstub/stm32.s b/flashstub/stm32.s deleted file mode 100644 index 8a9cb54..0000000 --- a/flashstub/stm32.s +++ /dev/null @@ -1,43 +0,0 @@ -.global _start - -_start: - ldr r0, _flashbase - ldr r1, _addr - mov r2, pc - add r2, #(_data - . - 2) - ldr r3, _size - mov r5, #1 -_next: - cmp r3, #0 - beq _done - @ Write PG command to FLASH_CR - str r5, [r0, #0x10] - @ Write data to flash (half-word) - ldrh r4, [r2] - strh r4, [r1] - -_wait: @ Wait for BSY bit to clear - ldr r4, [r0, #0x0C] - mov r6, #1 - tst r4, r6 - bne _wait - - sub r3, #2 - add r1, #2 - add r2, #2 - b _next -_done: - bkpt - -@.align 4 -.org 0x28 -_flashbase: - .word 0x40022000 -_addr: - .word 0 -_size: - .word 12 -_data: - .word 0xAAAAAAAA - .word 0xBBBBBBBB - .word 0xCCCCCCCC diff --git a/flashstub/stm32.stub b/flashstub/stm32.stub deleted file mode 100644 index 755f445..0000000 --- a/flashstub/stm32.stub +++ /dev/null @@ -1 +0,0 @@ -0x4809, 0x490A, 0x467A, 0x322C, 0x4B09, 0x2501, 0x2B00, 0xD00A, 0x6105, 0x8814, 0x800C, 0x68C4, 0x2601, 0x4234, 0xD1FB, 0x3B02, 0x3102, 0x3202, 0xE7F2, 0xBE00, 0x2000, 0x4002, 0x0000, 0x0000, 0x000C, 0x0000, 0xAAAA, 0xAAAA, 0xBBBB, 0xBBBB, 0xCCCC, 0xCCCC, \ No newline at end of file diff --git a/flashstub/stm32f1.c b/flashstub/stm32f1.c new file mode 100644 index 0000000..8370114 --- /dev/null +++ b/flashstub/stm32f1.c @@ -0,0 +1,34 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2015 Black Sphere Technologies Ltd. + * Written by Gareth McMullin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * 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, see . + */ +#include "libopencm3/stm32/flash.h" + +void __attribute__((naked)) +stm32f1_flash_write_stub(uint16_t *dest, uint16_t *src, uint32_t size) +{ + while (size) { + FLASH_CR = FLASH_CR_PG; + *dest++ = *src++; + size -= 2; + while (FLASH_SR & FLASH_SR_BSY) + ; + } + asm("bkpt"); +} + diff --git a/flashstub/stm32f1.stub b/flashstub/stm32f1.stub new file mode 100644 index 0000000..97d2a5e --- /dev/null +++ b/flashstub/stm32f1.stub @@ -0,0 +1 @@ +0x4613, 0xE010, 0x4A09, 0x2401, 0x6014, 0x4602, 0x1C90, 0x460C, 0x1CA1, 0x8824, 0x8014, 0x3B02, 0xBF00, 0x4A05, 0x6812, 0xF002, 0x0201, 0x2A00, 0xD1F9, 0x2B00, 0xD1EC, 0xBE00, 0x2010, 0x4002, 0x200C, 0x4002, \ No newline at end of file diff --git a/src/include/general.h b/src/include/general.h index 2cb4bd9..cf8c1e6 100644 --- a/src/include/general.h +++ b/src/include/general.h @@ -38,5 +38,7 @@ #define DEBUG printf #endif +#define ALIGN(x, n) (((x) + (n) - 1) & ~((n) - 1)) + #endif diff --git a/src/stm32f1.c b/src/stm32f1.c index daba1b0..96faf1f 100644 --- a/src/stm32f1.c +++ b/src/stm32f1.c @@ -36,8 +36,6 @@ #include "command.h" #include "gdb_packet.h" -#define SRAM_BASE 0x20000000 - static bool stm32f1_cmd_erase_mass(target *t); static bool stm32f1_cmd_option(target *t, int argc, char *argv[]); @@ -123,9 +121,12 @@ static const char stm32hd_xml_memory_map[] = "" #define DBGMCU_IDCODE_F0 0x40015800 static const uint16_t stm32f1_flash_write_stub[] = { -#include "../flashstub/stm32.stub" +#include "../flashstub/stm32f1.stub" }; +#define SRAM_BASE 0x20000000 +#define STUB_BUFFER_BASE ALIGN(SRAM_BASE + sizeof(stm32f1_flash_write_stub), 4) + bool stm32f1_probe(struct target_s *target) { target->idcode = target_mem_read32(target, DBGMCU_IDCODE) & 0xfff; @@ -247,22 +248,18 @@ static int stm32f1_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, size_t len) { uint32_t offset = dest % 4; - uint32_t words = (offset + len + 3) / 4; - if (words > 256) - return -1; - uint32_t data[2 + words]; + uint8_t data[ALIGN(offset + len, 4)]; /* Construct data buffer used by stub */ - data[0] = dest - offset; - data[1] = words * 4; /* length must always be a multiple of 4 */ - data[2] = 0xFFFFFFFF; /* pad partial words with all 1s to avoid */ - data[words + 1] = 0xFFFFFFFF; /* damaging overlapping areas */ - memcpy((uint8_t *)&data[2] + offset, src, len); + /* pad partial words with all 1s to avoid damaging overlapping areas */ + memset(data, 0xff, sizeof(data)); + memcpy((uint8_t *)data + offset, src, len); /* Write stub and data to target ram and set PC */ - target_mem_write(target, 0x2000002C, data, sizeof(data)); - cortexm_run_stub(target, SRAM_BASE, stm32f1_flash_write_stub, 0x2C, - 0, 0, 0, 0); + target_mem_write(target, STUB_BUFFER_BASE, data, sizeof(data)); + cortexm_run_stub(target, SRAM_BASE, stm32f1_flash_write_stub, + sizeof(stm32f1_flash_write_stub), + dest - offset, STUB_BUFFER_BASE, sizeof(data), 0); /* Check for error */ if (target_mem_read32(target, FLASH_SR) & SR_ERROR_MASK) -- cgit v1.2.3 From 8ddb186b35267e90832deb2db4b0c58f77de4b87 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sun, 8 Mar 2015 15:02:38 -0700 Subject: Allow stub to return an error code. --- flashstub/stm32f1.c | 9 ++++++++- flashstub/stm32f1.stub | 2 +- flashstub/stub.h | 30 ++++++++++++++++++++++++++++++ src/cortexm.c | 9 ++++++++- src/stm32f1.c | 15 +++++---------- 5 files changed, 52 insertions(+), 13 deletions(-) create mode 100644 flashstub/stub.h (limited to 'src') diff --git a/flashstub/stm32f1.c b/flashstub/stm32f1.c index 8370114..2268eee 100644 --- a/flashstub/stm32f1.c +++ b/flashstub/stm32f1.c @@ -18,6 +18,9 @@ * along with this program. If not, see . */ #include "libopencm3/stm32/flash.h" +#include "stub.h" + +#define SR_ERROR_MASK 0x14 void __attribute__((naked)) stm32f1_flash_write_stub(uint16_t *dest, uint16_t *src, uint32_t size) @@ -29,6 +32,10 @@ stm32f1_flash_write_stub(uint16_t *dest, uint16_t *src, uint32_t size) while (FLASH_SR & FLASH_SR_BSY) ; } - asm("bkpt"); + + if (FLASH_SR & SR_ERROR_MASK) + stub_exit(1); + + stub_exit(0); } diff --git a/flashstub/stm32f1.stub b/flashstub/stm32f1.stub index 97d2a5e..428dbb0 100644 --- a/flashstub/stm32f1.stub +++ b/flashstub/stm32f1.stub @@ -1 +1 @@ -0x4613, 0xE010, 0x4A09, 0x2401, 0x6014, 0x4602, 0x1C90, 0x460C, 0x1CA1, 0x8824, 0x8014, 0x3B02, 0xBF00, 0x4A05, 0x6812, 0xF002, 0x0201, 0x2A00, 0xD1F9, 0x2B00, 0xD1EC, 0xBE00, 0x2010, 0x4002, 0x200C, 0x4002, \ No newline at end of file +0x4613, 0xE010, 0x4A0D, 0x2401, 0x6014, 0x4602, 0x1C90, 0x460C, 0x1CA1, 0x8824, 0x8014, 0x3B02, 0xBF00, 0x4A09, 0x6812, 0xF002, 0x0201, 0x2A00, 0xD1F9, 0x2B00, 0xD1EC, 0x4B05, 0x681B, 0xF003, 0x0314, 0x2B00, 0xD000, 0xBE01, 0xBE00, 0xBF00, 0x2010, 0x4002, 0x200C, 0x4002, \ No newline at end of file diff --git a/flashstub/stub.h b/flashstub/stub.h new file mode 100644 index 0000000..d279cf3 --- /dev/null +++ b/flashstub/stub.h @@ -0,0 +1,30 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2015 Black Sphere Technologies Ltd. + * Written by Gareth McMullin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * 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, see . + */ +#ifndef __STUB_H +#define __STUB_H + +static inline __attribute__((always_inline)) +stub_exit(const int code) +{ + asm("bkpt %0"::"i"(code)); +} + +#endif + diff --git a/src/cortexm.c b/src/cortexm.c index 0327edc..a129a3c 100644 --- a/src/cortexm.c +++ b/src/cortexm.c @@ -60,6 +60,7 @@ const struct command_s cortexm_cmd_list[] = { static int cortexm_regs_read(struct target_s *target, void *data); static int cortexm_regs_write(struct target_s *target, const void *data); static int cortexm_pc_write(struct target_s *target, const uint32_t val); +static uint32_t cortexm_pc_read(struct target_s *target); static void cortexm_reset(struct target_s *target); static int cortexm_halt_wait(struct target_s *target); @@ -216,6 +217,7 @@ cortexm_probe(struct target_s *target) target->regs_read = cortexm_regs_read; target->regs_write = cortexm_regs_write; target->pc_write = cortexm_pc_write; + target->pc_read = cortexm_pc_read; target->reset = cortexm_reset; target->halt_request = cortexm_halt_request; @@ -629,7 +631,12 @@ int cortexm_run_stub(struct target_s *target, uint32_t loadaddr, while (!cortexm_halt_wait(target)) ; - return 0; + uint32_t pc = cortexm_pc_read(target); + uint16_t bkpt_instr = target_mem_read16(target, pc); + if (bkpt_instr >> 8 != 0xbe) + return -2; + + return bkpt_instr & 0xff; } /* The following routines implement hardware breakpoints. diff --git a/src/stm32f1.c b/src/stm32f1.c index 96faf1f..8f7a7d7 100644 --- a/src/stm32f1.c +++ b/src/stm32f1.c @@ -256,16 +256,11 @@ static int stm32f1_flash_write(struct target_s *target, uint32_t dest, memcpy((uint8_t *)data + offset, src, len); /* Write stub and data to target ram and set PC */ - target_mem_write(target, STUB_BUFFER_BASE, data, sizeof(data)); - cortexm_run_stub(target, SRAM_BASE, stm32f1_flash_write_stub, - sizeof(stm32f1_flash_write_stub), - dest - offset, STUB_BUFFER_BASE, sizeof(data), 0); - - /* Check for error */ - if (target_mem_read32(target, FLASH_SR) & SR_ERROR_MASK) - return -1; - - return 0; + target_mem_write(target, STUB_BUFFER_BASE, (void*)data, sizeof(data)); + return cortexm_run_stub(target, SRAM_BASE, stm32f1_flash_write_stub, + sizeof(stm32f1_flash_write_stub), + dest - offset, STUB_BUFFER_BASE, sizeof(data), + 0); } static bool stm32f1_cmd_erase_mass(target *t) -- cgit v1.2.3 From acfd258aa7b02ea23a6d26c29c3432bf3e857039 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sun, 8 Mar 2015 22:43:12 -0700 Subject: Rewrite STM32F4 stub in C and use new interface. --- flashstub/Makefile | 6 +++- flashstub/stm32f4.c | 40 ++++++++++++++++++++++++++ flashstub/stm32f4.s | 44 ---------------------------- flashstub/stm32f4.stub | 1 + src/stm32f4.c | 78 +++++++++++--------------------------------------- 5 files changed, 62 insertions(+), 107 deletions(-) create mode 100644 flashstub/stm32f4.c delete mode 100644 flashstub/stm32f4.s create mode 100644 flashstub/stm32f4.stub (limited to 'src') diff --git a/flashstub/Makefile b/flashstub/Makefile index eeb1803..c955ca8 100644 --- a/flashstub/Makefile +++ b/flashstub/Makefile @@ -8,7 +8,7 @@ ifneq ($(V), 1) Q = @ endif -CFLAGS=-mcpu=cortex-m3 -mthumb -I../libopencm3/include +CFLAGS=-Os -std=gnu99 -mcpu=cortex-m3 -mthumb -I../libopencm3/include ASFLAGS=-mcpu=cortex-m3 -mthumb all: lmi.stub stm32f4.stub nrf51.stub stm32f1.stub @@ -17,6 +17,10 @@ stm32f1.o: stm32f1.c $(Q)echo " CC $<" $(Q)$(CC) $(CFLAGS) -DSTM32F1 -o $@ -c $< +stm32f4.o: stm32f4.c + $(Q)echo " CC $<" + $(Q)$(CC) $(CFLAGS) -DSTM32F4 -o $@ -c $< + %.o: %.s $(Q)echo " AS $<" $(Q)$(AS) $(ASFLAGS) -o $@ $< diff --git a/flashstub/stm32f4.c b/flashstub/stm32f4.c new file mode 100644 index 0000000..6732897 --- /dev/null +++ b/flashstub/stm32f4.c @@ -0,0 +1,40 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2015 Black Sphere Technologies Ltd. + * Written by Gareth McMullin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * 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, see . + */ +#include "libopencm3/stm32/flash.h" +#include "stub.h" + +#define SR_ERROR_MASK 0xF2 + +void __attribute__((naked)) +stm32f4_flash_write_stub(uint32_t *dest, uint32_t *src, uint32_t size) +{ + for (int i = 0; i < size; i += 4) { + FLASH_CR = FLASH_CR_PROGRAM_X32 | FLASH_CR_PG; + *dest++ = *src++; + while (FLASH_SR & FLASH_SR_BSY) + ; + } + + if (FLASH_SR & SR_ERROR_MASK) + stub_exit(1); + + stub_exit(0); +} + diff --git a/flashstub/stm32f4.s b/flashstub/stm32f4.s deleted file mode 100644 index fa3fda0..0000000 --- a/flashstub/stm32f4.s +++ /dev/null @@ -1,44 +0,0 @@ -.global _start - -_start: - ldr r0, _flashbase - ldr r1, _addr - mov r2, pc - add r2, #(_data - . - 2) - ldr r3, _size - ldr r5, _cr -_next: - cbz r3, _done - @ Write PG command to FLASH_CR - str r5, [r0, #0x10] - @ Write data to flash (word) - ldr r4, [r2] - str r4, [r1] - -_wait: @ Wait for BSY bit to clear - ldrh r4, [r0, #0x0E] - mov r6, #1 - tst r4, r6 - bne _wait - - sub r3, #4 - add r1, #4 - add r2, #4 - b _next -_done: - bkpt - -@.align 4 -.org 0x28 -_cr: - .word 0x00000201 -_flashbase: - .word 0x40023C00 -_addr: - .word 0x0800bf78 -_size: - .word 8 -_data: - .word 0xAAAAAAAA - .word 0xBBBBBBBB - .word 0xCCCCCCCC diff --git a/flashstub/stm32f4.stub b/flashstub/stm32f4.stub new file mode 100644 index 0000000..25b5d9a --- /dev/null +++ b/flashstub/stm32f4.stub @@ -0,0 +1 @@ +0x2300, 0x4293, 0x4C09, 0xD20B, 0x4D09, 0xF240, 0x2601, 0x602E, 0x58CD, 0x50C5, 0x6825, 0xF415, 0x3F80, 0xD1FB, 0x3304, 0xE7F0, 0x6823, 0xF013, 0x0FF2, 0xD000, 0xBE01, 0xBE00, 0x3C0C, 0x4002, 0x3C10, 0x4002, \ No newline at end of file diff --git a/src/stm32f4.c b/src/stm32f4.c index 2a8bc21..fe844ca 100644 --- a/src/stm32f4.c +++ b/src/stm32f4.c @@ -33,6 +33,7 @@ #include "general.h" #include "adiv5.h" #include "target.h" +#include "cortexm.h" #include "command.h" #include "gdb_packet.h" @@ -120,44 +121,12 @@ static const char stm32f4_xml_memory_map[] = "" /* This routine is uses word access. Only usable on target voltage >2.7V */ static const uint16_t stm32f4_flash_write_stub[] = { -// _start: - 0x480a, // ldr r0, [pc, #40] // _flashbase - 0x490b, // ldr r1, [pc, #44] // _addr - 0x467a, // mov r2, pc - 0x3230, // adds r2, #48 - 0x4b0a, // ldr r3, [pc, #36] // _size - 0x4d07, // ldr r5, [pc, #28] // _cr -// _next: - 0xb153, // cbz r3, _done - 0x6105, // str r5, [r0, #16] - 0x6814, // ldr r4, [r2] - 0x600c, // str r4, [r1] -// _wait: - 0x89c4, // ldrb r4, [r0, #14] - 0x2601, // movs r6, #1 - 0x4234, // tst r4, r6 - 0xd1fb, // bne _wait - - 0x3b04, // subs r3, #4 - 0x3104, // adds r1, #4 - 0x3204, // adds r2, #4 - 0xe7f3, // b _next -// _done: - 0xbe00, // bkpt - 0x0000, -// .org 0x28 -//_cr: - 0x0201, 0x0000, //.word 0x00000201 (Value to write to FLASH_CR) */ -// _flashbase: - 0x3c00, 0x4002, // .word 0x40023c00 (FPEC_BASE) -// _addr: -// 0x0000, 0x0000, -// _size: -// 0x0000, 0x0000, -// _data: -// ... +#include "../flashstub/stm32f4.stub" }; +#define SRAM_BASE 0x20000000 +#define STUB_BUFFER_BASE ALIGN(SRAM_BASE + sizeof(stm32f4_flash_write_stub), 4) + bool stm32f4_probe(struct target_s *target) { uint32_t idcode; @@ -239,34 +208,19 @@ static int stm32f4_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, size_t len) { uint32_t offset = dest % 4; - uint32_t words = (offset + len + 3) / 4; - uint32_t data[2 + words]; - uint16_t sr; + uint8_t data[ALIGN(offset + len, 4)]; /* Construct data buffer used by stub */ - data[0] = dest - offset; - data[1] = words * 4; /* length must always be a multiple of 4 */ - data[2] = 0xFFFFFFFF; /* pad partial words with all 1s to avoid */ - data[words + 1] = 0xFFFFFFFF; /* damaging overlapping areas */ - memcpy((uint8_t *)&data[2] + offset, src, len); - - /* Write stub and data to target ram and set PC */ - target_mem_write(target, 0x20000000, stm32f4_flash_write_stub, 0x30); - target_mem_write(target, 0x20000030, data, sizeof(data)); - target_pc_write(target, 0x20000000); - if(target_check_error(target)) - return -1; - - /* Execute the stub */ - target_halt_resume(target, 0); - while(!target_halt_wait(target)); - - /* Check for error */ - sr = target_mem_read32(target, FLASH_SR); - if(sr & SR_ERROR_MASK) - return -1; - - return 0; + /* pad partial words with all 1s to avoid damaging overlapping areas */ + memset(data, 0xff, sizeof(data)); + memcpy((uint8_t *)data + offset, src, len); + + /* Write buffer to target ram call stub */ + target_mem_write(target, STUB_BUFFER_BASE, data, sizeof(data)); + return cortexm_run_stub(target, SRAM_BASE, stm32f4_flash_write_stub, + sizeof(stm32f4_flash_write_stub), + dest - offset, STUB_BUFFER_BASE, sizeof(data), + 0); } static bool stm32f4_cmd_erase_mass(target *t) -- cgit v1.2.3 From a497127a8d16387ce9b9b01969ca5632b95d8e07 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sun, 22 Mar 2015 12:21:03 -0700 Subject: Move MIN macro to general.h --- src/adiv5.c | 2 -- src/include/general.h | 2 ++ src/samd.c | 5 +---- 3 files changed, 3 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/adiv5.c b/src/adiv5.c index f2421ce..88aac31 100644 --- a/src/adiv5.c +++ b/src/adiv5.c @@ -173,8 +173,6 @@ enum align { }; #define ALIGNOF(x) (((x) & 3) == 0 ? ALIGN_WORD : \ (((x) & 1) == 0 ? ALIGN_HALFWORD : ALIGN_BYTE)) -#undef MIN -#define MIN(x, y) (((x) < (y)) ? (x) : (y)) /* Program the CSW and TAR for sequencial access at a given width */ static void ap_mem_access_setup(ADIv5_AP_t *ap, uint32_t addr, enum align align) diff --git a/src/include/general.h b/src/include/general.h index cf8c1e6..c82c750 100644 --- a/src/include/general.h +++ b/src/include/general.h @@ -39,6 +39,8 @@ #endif #define ALIGN(x, n) (((x) + (n) - 1) & ~((n) - 1)) +#undef MIN +#define MIN(x, y) (((x) < (y)) ? (x) : (y)) #endif diff --git a/src/samd.c b/src/samd.c index e12bcc9..a996610 100644 --- a/src/samd.c +++ b/src/samd.c @@ -159,9 +159,6 @@ static const char samd_xml_memory_map[] = "" /* Component ID */ #define SAMD_CID_VALUE 0xB105100D -/* Utility */ -#define MINIMUM(a,b) ((a < b) ? a : b) - /** * Reads the SAM D20 Peripheral ID */ @@ -529,7 +526,7 @@ static int samd_flash_write(struct target_s *target, uint32_t dest, for (uint32_t page = first_page; page <= last_page; page += SAMD_PAGE_SIZE) { next_page = page + SAMD_PAGE_SIZE; - length = MINIMUM(end + 4, next_page) - addr; + length = MIN(end + 4, next_page) - addr; /* Write within a single page. This may be part or all of the page */ target_mem_write(target, addr, &data[i], length); -- cgit v1.2.3 From fa046601a54ddf2137048f11594ed7d72ede995a Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sat, 28 Feb 2015 20:50:10 -0800 Subject: Add exception handling mechanism and raise exception on low-level comms failure. --- src/Makefile | 1 + src/adiv5_jtagdp.c | 7 ++-- src/adiv5_swdp.c | 9 +++-- src/exception.c | 39 ++++++++++++++++++++++ src/include/exception.h | 74 +++++++++++++++++++++++++++++++++++++++++ src/platforms/native/platform.h | 1 + 6 files changed, 122 insertions(+), 9 deletions(-) create mode 100644 src/exception.c create mode 100644 src/include/exception.h (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 02b5690..73fb8e9 100644 --- a/src/Makefile +++ b/src/Makefile @@ -24,6 +24,7 @@ SRC = \ command.c \ cortexm.c \ crc32.c \ + exception.c \ gdb_if.c \ gdb_main.c \ gdb_packet.c \ diff --git a/src/adiv5_jtagdp.c b/src/adiv5_jtagdp.c index 5049e3c..bb478d1 100644 --- a/src/adiv5_jtagdp.c +++ b/src/adiv5_jtagdp.c @@ -23,6 +23,7 @@ */ #include "general.h" +#include "exception.h" #include "adiv5.h" #include "jtag_scan.h" #include "jtagtap.h" @@ -93,10 +94,8 @@ static uint32_t adiv5_jtagdp_low_access(ADIv5_DP_t *dp, uint8_t RnW, if (dp->allow_timeout && (ack == JTAGDP_ACK_WAIT)) return 0; - if((ack != JTAGDP_ACK_OK)) { - /* Fatal error if invalid ACK response */ - PLATFORM_FATAL_ERROR(1); - } + if((ack != JTAGDP_ACK_OK)) + raise_exception(EXCEPTION_ERROR, "JTAG-DP invalid ACK"); return (uint32_t)(response >> 3); } diff --git a/src/adiv5_swdp.c b/src/adiv5_swdp.c index 9ac791a..d5193ac 100644 --- a/src/adiv5_swdp.c +++ b/src/adiv5_swdp.c @@ -23,6 +23,7 @@ */ #include "general.h" +#include "exception.h" #include "adiv5.h" #include "swdptap.h" #include "jtagtap.h" @@ -143,14 +144,12 @@ static uint32_t adiv5_swdp_low_access(ADIv5_DP_t *dp, uint8_t RnW, return 0; } - if(ack != SWDP_ACK_OK) { - /* Fatal error if invalid ACK response */ - PLATFORM_FATAL_ERROR(1); - } + if(ack != SWDP_ACK_OK) + raise_exception(EXCEPTION_ERROR, "SWDP invalid ACK"); if(RnW) { if(swdptap_seq_in_parity(&response, 32)) /* Give up on parity error */ - PLATFORM_FATAL_ERROR(1); + raise_exception(EXCEPTION_ERROR, "SWDP Parity error"); } else { swdptap_seq_out_parity(value, 32); } diff --git a/src/exception.c b/src/exception.c new file mode 100644 index 0000000..33e3869 --- /dev/null +++ b/src/exception.c @@ -0,0 +1,39 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2015 Black Sphere Technologies Ltd. + * Written by Gareth McMullin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * 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, see . + */ + +#include "general.h" +#include "exception.h" + +struct exception *innermost_exception; + +void raise_exception(uint32_t type, const char *msg) +{ + struct exception *e; + for (e = innermost_exception; e; e = e->outer) { + if (e->mask & type) { + e->type = type; + e->msg = msg; + innermost_exception = e->outer; + longjmp(e->jmpbuf, type); + } + } + PLATFORM_FATAL_ERROR(type); +} + diff --git a/src/include/exception.h b/src/include/exception.h new file mode 100644 index 0000000..180398d --- /dev/null +++ b/src/include/exception.h @@ -0,0 +1,74 @@ +/* + * This file is part of the Black Magic Debug project. + * + * Copyright (C) 2015 Black Sphere Technologies Ltd. + * Written by Gareth McMullin + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * 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, see . + */ + +/* Exception handling to escape deep nesting. + * Used for the case of communicaiton failure and timeouts. + */ + +/* Example usage: + * + * volatile struct exception e; + * TRY_CATCH (e, EXCEPTION_TIMEOUT) { + * ... + * raise_exception(EXCEPTION_TIMEOUT, "Timeout occurred"); + * ... + * } + * if (e.type == EXCEPTION_TIMEOUT) { + * printf("timeout: %s\n", e.msg); + * } + */ + +/* Limitations: + * Can't use break, return, goto, etc from inside the TRY_CATCH block. + */ + +#ifndef __EXCEPTION_H +#define __EXCEPTION_H + +#include +#include + +#define EXCEPTION_ERROR 0x01 +#define EXCEPTION_TIMEOUT 0x02 +#define EXCEPTION_ALL -1 + +struct exception { + uint32_t type; + const char *msg; + /* private */ + uint32_t mask; + jmp_buf jmpbuf; + struct exception *outer; +}; + +extern struct exception *innermost_exception; + +#define TRY_CATCH(e, type_mask) \ + (e).type = 0; \ + (e).mask = (type_mask); \ + (e).outer = innermost_exception; \ + innermost_exception = (void*)&(e); \ + if (setjmp(innermost_exception->jmpbuf) == 0) \ + for (;innermost_exception == &(e); innermost_exception = (e).outer) + +void raise_exception(uint32_t type, const char *msg); + +#endif + diff --git a/src/platforms/native/platform.h b/src/platforms/native/platform.h index ae9bcef..3b1769b 100644 --- a/src/platforms/native/platform.h +++ b/src/platforms/native/platform.h @@ -153,6 +153,7 @@ extern jmp_buf fatal_error_jmpbuf; #define SET_IDLE_STATE(state) {gpio_set_val(LED_PORT, LED_IDLE_RUN, state);} #define SET_ERROR_STATE(state) {gpio_set_val(LED_PORT, LED_ERROR, state);} +#include "target.h" #define PLATFORM_SET_FATAL_ERROR_RECOVERY() {setjmp(fatal_error_jmpbuf);} #define PLATFORM_FATAL_ERROR(error) do { \ if(running_status) gdb_putpacketz("X1D"); \ -- cgit v1.2.3 From d6225eec763bd49ef3cb8edac5138df9e524a073 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sat, 28 Feb 2015 20:53:25 -0800 Subject: Raise timeout exception when target is in WFI. Ignore the exception when polling for halt, and report the exception to the user if halting the target fails. Remove old allow_timeout flag in DP struct that's no longer needed.--- src/adiv5_jtagdp.c | 4 ++-- src/adiv5_swdp.c | 4 ++-- src/cortexm.c | 29 +++++++++++++++++++---------- src/include/adiv5.h | 4 ---- 4 files changed, 23 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/adiv5_jtagdp.c b/src/adiv5_jtagdp.c index bb478d1..a460113 100644 --- a/src/adiv5_jtagdp.c +++ b/src/adiv5_jtagdp.c @@ -91,8 +91,8 @@ static uint32_t adiv5_jtagdp_low_access(ADIv5_DP_t *dp, uint8_t RnW, ack = response & 0x07; } while(--tries && (ack == JTAGDP_ACK_WAIT)); - if (dp->allow_timeout && (ack == JTAGDP_ACK_WAIT)) - return 0; + if (ack == JTAGDP_ACK_WAIT) + raise_exception(EXCEPTION_TIMEOUT, "JTAG-DP ACK timeout"); if((ack != JTAGDP_ACK_OK)) raise_exception(EXCEPTION_ERROR, "JTAG-DP invalid ACK"); diff --git a/src/adiv5_swdp.c b/src/adiv5_swdp.c index d5193ac..1a6b158 100644 --- a/src/adiv5_swdp.c +++ b/src/adiv5_swdp.c @@ -136,8 +136,8 @@ static uint32_t adiv5_swdp_low_access(ADIv5_DP_t *dp, uint8_t RnW, ack = swdptap_seq_in(3); } while(--tries && ack == SWDP_ACK_WAIT); - if (dp->allow_timeout && (ack == SWDP_ACK_WAIT)) - return 0; + if (ack == SWDP_ACK_WAIT) + raise_exception(EXCEPTION_TIMEOUT, "SWDP ACK timeout"); if(ack == SWDP_ACK_FAULT) { dp->fault = 1; diff --git a/src/cortexm.c b/src/cortexm.c index a129a3c..f20f282 100644 --- a/src/cortexm.c +++ b/src/cortexm.c @@ -29,6 +29,7 @@ * There are way too many magic numbers used here. */ #include "general.h" +#include "exception.h" #include "jtagtap.h" #include "jtag_scan.h" #include "adiv5.h" @@ -467,12 +468,15 @@ cortexm_reset(struct target_s *target) static void cortexm_halt_request(struct target_s *target) { - ADIv5_AP_t *ap = adiv5_target_ap(target); - - ap->dp->allow_timeout = false; - target_mem_write32(target, CORTEXM_DHCSR, - CORTEXM_DHCSR_DBGKEY | CORTEXM_DHCSR_C_HALT | - CORTEXM_DHCSR_C_DEBUGEN); + volatile struct exception e; + TRY_CATCH (e, EXCEPTION_TIMEOUT) { + target_mem_write32(target, CORTEXM_DHCSR, CORTEXM_DHCSR_DBGKEY | + CORTEXM_DHCSR_C_HALT | + CORTEXM_DHCSR_C_DEBUGEN); + } + if (e.type) { + gdb_out("Timeout sending interrupt, is target in WFI?\n"); + } } static int @@ -480,10 +484,16 @@ cortexm_halt_wait(struct target_s *target) { ADIv5_AP_t *ap = adiv5_target_ap(target); struct cortexm_priv *priv = ap->priv; - if (!(target_mem_read32(target, CORTEXM_DHCSR) & CORTEXM_DHCSR_S_HALT)) - return 0; - ap->dp->allow_timeout = false; + uint32_t dhcsr = 0; + volatile struct exception e; + TRY_CATCH (e, EXCEPTION_TIMEOUT) { + /* If this times out because the target is in WFI then + * the target is still running. */ + dhcsr = target_mem_read32(target, CORTEXM_DHCSR); + } + if (e.type || !(dhcsr & CORTEXM_DHCSR_S_HALT)) + return 0; /* We've halted. Let's find out why. */ uint32_t dfsr = target_mem_read32(target, CORTEXM_DFSR); @@ -543,7 +553,6 @@ void cortexm_halt_resume(struct target_s *target, bool step) } target_mem_write32(target, CORTEXM_DHCSR, dhcsr); - ap->dp->allow_timeout = true; } static int cortexm_fault_unwind(struct target_s *target) diff --git a/src/include/adiv5.h b/src/include/adiv5.h index 6896f6d..12d3bf4 100644 --- a/src/include/adiv5.h +++ b/src/include/adiv5.h @@ -107,12 +107,8 @@ typedef struct ADIv5_DP_s { uint32_t idcode; - bool allow_timeout; - uint32_t (*dp_read)(struct ADIv5_DP_s *dp, uint16_t addr); - uint32_t (*error)(struct ADIv5_DP_s *dp); - uint32_t (*low_access)(struct ADIv5_DP_s *dp, uint8_t RnW, uint16_t addr, uint32_t value); -- cgit v1.2.3 From d0a03f55a6e66907f73d046adb6f211da2544d29 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sat, 28 Feb 2015 20:56:03 -0800 Subject: Handle timeout exceptions during scans and report to the user. --- src/command.c | 36 ++++++++++++++++++++++++++++++------ 1 file changed, 30 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/command.c b/src/command.c index f271085..2c2a198 100644 --- a/src/command.c +++ b/src/command.c @@ -23,6 +23,7 @@ */ #include "general.h" +#include "exception.h" #include "command.h" #include "gdb_packet.h" #include "jtag_scan.h" @@ -138,19 +139,30 @@ bool cmd_help(target *t) static bool cmd_jtag_scan(target *t, int argc, char **argv) { (void)t; - uint8_t *irlens = NULL; + uint8_t irlens[argc]; gdb_outf("Target voltage: %s\n", platform_target_voltage()); if (argc > 1) { /* Accept a list of IR lengths on command line */ - irlens = alloca(argc); for (int i = 1; i < argc; i++) irlens[i-1] = atoi(argv[i]); irlens[argc-1] = 0; } - int devs = jtag_scan(irlens); + int devs = -1; + volatile struct exception e; + TRY_CATCH (e, EXCEPTION_ALL) { + devs = jtag_scan(argc > 1 ? irlens : NULL); + } + switch (e.type) { + case EXCEPTION_TIMEOUT: + gdb_outf("Timeout during scan. Is target stuck in WFI?\n"); + break; + case EXCEPTION_ERROR: + gdb_outf("Exception: %s\n", e.msg); + break; + } if(devs < 0) { gdb_out("JTAG device scan failed!\n"); @@ -174,13 +186,25 @@ bool cmd_swdp_scan(void) { gdb_outf("Target voltage: %s\n", platform_target_voltage()); - if(adiv5_swdp_scan() < 0) { + int devs = -1; + volatile struct exception e; + TRY_CATCH (e, EXCEPTION_ALL) { + devs = adiv5_swdp_scan(); + } + switch (e.type) { + case EXCEPTION_TIMEOUT: + gdb_outf("Timeout during scan. Is target stuck in WFI?\n"); + break; + case EXCEPTION_ERROR: + gdb_outf("Exception: %s\n", e.msg); + break; + } + + if(devs < 0) { gdb_out("SW-DP scan failed!\n"); return false; } - //gdb_outf("SW-DP detected IDCODE: 0x%08X\n", adiv5_dp_list->idcode); - cmd_targets(NULL); return true; -- cgit v1.2.3 From 83b83ca48f71639d14673d1deb544bf39a7332be Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Mon, 2 Mar 2015 23:10:15 -0800 Subject: Use controlled timeout on SW/JTAG DP transactions. --- src/adiv5_jtagdp.c | 4 ++-- src/adiv5_swdp.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/adiv5_jtagdp.c b/src/adiv5_jtagdp.c index a460113..d97bc99 100644 --- a/src/adiv5_jtagdp.c +++ b/src/adiv5_jtagdp.c @@ -85,11 +85,11 @@ static uint32_t adiv5_jtagdp_low_access(ADIv5_DP_t *dp, uint8_t RnW, jtag_dev_write_ir(dp->dev, APnDP ? IR_APACC : IR_DPACC); - int tries = 1000; + platform_timeout_set(2000); do { jtag_dev_shift_dr(dp->dev, (uint8_t*)&response, (uint8_t*)&request, 35); ack = response & 0x07; - } while(--tries && (ack == JTAGDP_ACK_WAIT)); + } while(!platform_timeout_is_expired() && (ack == JTAGDP_ACK_WAIT)); if (ack == JTAGDP_ACK_WAIT) raise_exception(EXCEPTION_TIMEOUT, "JTAG-DP ACK timeout"); diff --git a/src/adiv5_swdp.c b/src/adiv5_swdp.c index 1a6b158..b53fcb5 100644 --- a/src/adiv5_swdp.c +++ b/src/adiv5_swdp.c @@ -130,11 +130,11 @@ static uint32_t adiv5_swdp_low_access(ADIv5_DP_t *dp, uint8_t RnW, if((addr == 4) || (addr == 8)) request ^= 0x20; - size_t tries = 1000; + platform_timeout_set(2000); do { swdptap_seq_out(request, 8); ack = swdptap_seq_in(3); - } while(--tries && ack == SWDP_ACK_WAIT); + } while (!platform_timeout_is_expired() && ack == SWDP_ACK_WAIT); if (ack == SWDP_ACK_WAIT) raise_exception(EXCEPTION_TIMEOUT, "SWDP ACK timeout"); -- cgit v1.2.3 From 9a8dbdeff7b9bac70719ddb51a6f83a1266a2d44 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Mon, 2 Mar 2015 23:27:42 -0800 Subject: Fix errors when building for non-native platforms. --- src/platforms/f4discovery/platform.h | 1 + src/platforms/launchpad-icdi/platform.c | 14 ++++++++++++-- src/platforms/launchpad-icdi/platform.h | 2 ++ src/platforms/libftdi/platform.c | 19 +++++++++++++++++++ src/platforms/stlink/platform.h | 1 + src/platforms/swlink/platform.h | 1 + 6 files changed, 36 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/platforms/f4discovery/platform.h b/src/platforms/f4discovery/platform.h index 3c5c582..68027ee 100644 --- a/src/platforms/f4discovery/platform.h +++ b/src/platforms/f4discovery/platform.h @@ -28,6 +28,7 @@ #include "gpio.h" #include "morse.h" #include "timing.h" +#include "target.h" #include diff --git a/src/platforms/launchpad-icdi/platform.c b/src/platforms/launchpad-icdi/platform.c index e689f0c..1a3598a 100644 --- a/src/platforms/launchpad-icdi/platform.c +++ b/src/platforms/launchpad-icdi/platform.c @@ -86,10 +86,20 @@ platform_init(void) cdcacm_init(); } +void platform_timeout_set(uint32_t ms) +{ + timeout_counter = ms / 10; +} + +bool platform_timeout_is_expired(void) +{ + return timeout_counter == 0; +} + void platform_delay(uint32_t delay) { - timeout_counter = delay * 10; - while(timeout_counter); + platform_timeout_set(delay); + while (platform_timeout_is_expired()); } const char *platform_target_voltage(void) diff --git a/src/platforms/launchpad-icdi/platform.h b/src/platforms/launchpad-icdi/platform.h index eb3ac6e..ddc2035 100644 --- a/src/platforms/launchpad-icdi/platform.h +++ b/src/platforms/launchpad-icdi/platform.h @@ -18,6 +18,8 @@ #define __PLATFORM_H #include "gdb_packet.h" +#include "target.h" +#include "morse.h" #include diff --git a/src/platforms/libftdi/platform.c b/src/platforms/libftdi/platform.c index 634090d..3062698 100644 --- a/src/platforms/libftdi/platform.c +++ b/src/platforms/libftdi/platform.c @@ -21,6 +21,7 @@ #include "gdb_if.h" #include +#include struct ftdi_context *ftdic; @@ -258,3 +259,21 @@ void platform_delay(uint32_t delay) usleep(delay * 100000); } +static uint32_t timeout_time; +static uint32_t time_ms(void) +{ + struct timeval tv; + gettimeofday(&tv, NULL); + return (tv.tv_sec * 1000) + (tv.tv_usec / 1000); +} + +void platform_timeout_set(uint32_t ms) +{ + timeout_time = time_ms() + ms; +} + +bool platform_timeout_is_expired(void) +{ + return time_ms() > timeout_time; +} + diff --git a/src/platforms/stlink/platform.h b/src/platforms/stlink/platform.h index f026db3..549b6d6 100644 --- a/src/platforms/stlink/platform.h +++ b/src/platforms/stlink/platform.h @@ -27,6 +27,7 @@ #include "gdb_packet.h" #include "gpio.h" #include "timing.h" +#include "target.h" #include #include diff --git a/src/platforms/swlink/platform.h b/src/platforms/swlink/platform.h index 27cc299..e82124a 100644 --- a/src/platforms/swlink/platform.h +++ b/src/platforms/swlink/platform.h @@ -27,6 +27,7 @@ #include "gdb_packet.h" #include "gpio.h" #include "timing.h" +#include "target.h" #include -- cgit v1.2.3 From 588bad34ba2386737bec4bf4daf50633b0a8fe98 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sun, 15 Mar 2015 20:47:10 -0700 Subject: Build with -Os for swlink. --- src/platforms/swlink/Makefile.inc | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/platforms/swlink/Makefile.inc b/src/platforms/swlink/Makefile.inc index ca793d4..0ca2a3b 100644 --- a/src/platforms/swlink/Makefile.inc +++ b/src/platforms/swlink/Makefile.inc @@ -2,6 +2,7 @@ CROSS_COMPILE ?= arm-none-eabi- CC = $(CROSS_COMPILE)gcc OBJCOPY = $(CROSS_COMPILE)objcopy +OPT_FLAGS = -Os CFLAGS += -mcpu=cortex-m3 -mthumb \ -DSTM32F1 -DDISCOVERY_SWLINK -I../libopencm3/include \ -I platforms/stm32 -- cgit v1.2.3 From 5ab8564ff67583ac8df977bb6efca047b12e0aed Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sun, 22 Mar 2015 14:05:12 -0700 Subject: Clean up handling of lost targets using new exceptions mechanism. --- src/cortexm.c | 17 +++++++++++++++-- src/exception.c | 2 +- src/gdb_main.c | 6 ++++++ src/main.c | 16 ++++++++++++++-- src/platforms/stm32/timing.c | 1 + 5 files changed, 37 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/cortexm.c b/src/cortexm.c index f20f282..f6a0ea3 100644 --- a/src/cortexm.c +++ b/src/cortexm.c @@ -37,6 +37,7 @@ #include "command.h" #include "gdb_packet.h" #include "cortexm.h" +#include "morse.h" #include @@ -57,6 +58,7 @@ const struct command_s cortexm_cmd_list[] = { #define SIGINT 2 #define SIGTRAP 5 #define SIGSEGV 11 +#define SIGLOST 29 static int cortexm_regs_read(struct target_s *target, void *data); static int cortexm_regs_write(struct target_s *target, const void *data); @@ -487,12 +489,23 @@ cortexm_halt_wait(struct target_s *target) uint32_t dhcsr = 0; volatile struct exception e; - TRY_CATCH (e, EXCEPTION_TIMEOUT) { + TRY_CATCH (e, EXCEPTION_ALL) { /* If this times out because the target is in WFI then * the target is still running. */ dhcsr = target_mem_read32(target, CORTEXM_DHCSR); } - if (e.type || !(dhcsr & CORTEXM_DHCSR_S_HALT)) + switch (e.type) { + case EXCEPTION_ERROR: + /* Oh crap, there's no recovery from this... */ + target_list_free(); + morse("TARGET LOST.", 1); + return SIGLOST; + case EXCEPTION_TIMEOUT: + /* Timeout isn't a problem, target could be in WFI */ + return 0; + } + + if (!(dhcsr & CORTEXM_DHCSR_S_HALT)) return 0; /* We've halted. Let's find out why. */ diff --git a/src/exception.c b/src/exception.c index 33e3869..3d43f99 100644 --- a/src/exception.c +++ b/src/exception.c @@ -34,6 +34,6 @@ void raise_exception(uint32_t type, const char *msg) longjmp(e->jmpbuf, type); } } - PLATFORM_FATAL_ERROR(type); + abort(); } diff --git a/src/gdb_main.c b/src/gdb_main.c index 7bb788b..750dfe2 100644 --- a/src/gdb_main.c +++ b/src/gdb_main.c @@ -158,6 +158,12 @@ gdb_main(void) if (sig < 0) break; + /* Target disappeared */ + if (cur_target == NULL) { + gdb_putpacket_f("X%02X", sig); + break; + } + /* Report reason for halt */ if(target_check_hw_wp(cur_target, &watch_addr)) { /* Watchpoint hit */ diff --git a/src/main.c b/src/main.c index 60db15c..d1b3c86 100644 --- a/src/main.c +++ b/src/main.c @@ -28,6 +28,9 @@ #include "jtagtap.h" #include "jtag_scan.h" #include "target.h" +#include "exception.h" +#include "gdb_packet.h" +#include "morse.h" int main(int argc, char **argv) @@ -39,9 +42,18 @@ main(int argc, char **argv) (void) argv; platform_init(); #endif - PLATFORM_SET_FATAL_ERROR_RECOVERY(); - gdb_main(); + while (true) { + volatile struct exception e; + TRY_CATCH(e, EXCEPTION_ALL) { + gdb_main(); + } + if (e.type == EXCEPTION_ERROR) { + gdb_putpacketz("EFF"); + target_list_free(); + morse("TARGET LOST.", 1); + } + } /* Should never get here */ return 0; diff --git a/src/platforms/stm32/timing.c b/src/platforms/stm32/timing.c index cac22ca..55a217a 100644 --- a/src/platforms/stm32/timing.c +++ b/src/platforms/stm32/timing.c @@ -17,6 +17,7 @@ * along with this program. If not, see . */ #include "general.h" +#include "morse.h" #include #include -- cgit v1.2.3 From 68f54a35457da4c07ec84bd7e0c2823183e8811e Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sun, 22 Mar 2015 14:06:56 -0700 Subject: Remove old platform specific error handling macros. --- src/platforms/f4discovery/platform.h | 15 --------------- src/platforms/launchpad-icdi/platform.c | 1 - src/platforms/launchpad-icdi/platform.h | 17 ----------------- src/platforms/libftdi/platform.h | 3 --- src/platforms/native/platform.c | 2 -- src/platforms/native/platform.h | 17 ----------------- src/platforms/stlink/platform.c | 2 -- src/platforms/stlink/platform.h | 15 --------------- src/platforms/swlink/platform.c | 2 -- src/platforms/swlink/platform.h | 15 --------------- 10 files changed, 89 deletions(-) (limited to 'src') diff --git a/src/platforms/f4discovery/platform.h b/src/platforms/f4discovery/platform.h index 68027ee..92ae046 100644 --- a/src/platforms/f4discovery/platform.h +++ b/src/platforms/f4discovery/platform.h @@ -24,11 +24,8 @@ #ifndef __PLATFORM_H #define __PLATFORM_H -#include "gdb_packet.h" #include "gpio.h" -#include "morse.h" #include "timing.h" -#include "target.h" #include @@ -142,8 +139,6 @@ #define DEBUG(...) -extern jmp_buf fatal_error_jmpbuf; - #define gpio_set_val(port, pin, val) do { \ if(val) \ gpio_set((port), (pin)); \ @@ -155,16 +150,6 @@ extern jmp_buf fatal_error_jmpbuf; #define SET_IDLE_STATE(state) {gpio_set_val(LED_PORT, LED_IDLE_RUN, state);} #define SET_ERROR_STATE(state) {gpio_set_val(LED_PORT, LED_ERROR, state);} -#define PLATFORM_SET_FATAL_ERROR_RECOVERY() {setjmp(fatal_error_jmpbuf);} -#define PLATFORM_FATAL_ERROR(error) { \ - if(running_status) gdb_putpacketz("X1D"); \ - else gdb_putpacketz("EFF"); \ - running_status = 0; \ - target_list_free(); \ - morse("TARGET LOST.", 1); \ - longjmp(fatal_error_jmpbuf, (error)); \ -} - static inline int platform_hwversion(void) { return 0; diff --git a/src/platforms/launchpad-icdi/platform.c b/src/platforms/launchpad-icdi/platform.c index 1a3598a..ff67fa0 100644 --- a/src/platforms/launchpad-icdi/platform.c +++ b/src/platforms/launchpad-icdi/platform.c @@ -33,7 +33,6 @@ extern void trace_tick(void); -jmp_buf fatal_error_jmpbuf; uint8_t running_status; volatile uint32_t timeout_counter; diff --git a/src/platforms/launchpad-icdi/platform.h b/src/platforms/launchpad-icdi/platform.h index ddc2035..c13172f 100644 --- a/src/platforms/launchpad-icdi/platform.h +++ b/src/platforms/launchpad-icdi/platform.h @@ -17,12 +17,6 @@ #ifndef __PLATFORM_H #define __PLATFORM_H -#include "gdb_packet.h" -#include "target.h" -#include "morse.h" - -#include - #include #include @@ -31,7 +25,6 @@ #define DFU_IDENT "Black Magic Firmware Upgrade (Launchpad)" #define DFU_IFACE_STRING "lolwut" -extern jmp_buf fatal_error_jmpbuf; extern uint8_t running_status; extern volatile uint32_t timeout_counter; @@ -108,16 +101,6 @@ extern usbd_driver lm4f_usb_driver; #define SET_IDLE_STATE(state) {} #define SET_ERROR_STATE(state) SET_IDLE_STATE(state) -#define PLATFORM_SET_FATAL_ERROR_RECOVERY() {setjmp(fatal_error_jmpbuf);} -#define PLATFORM_FATAL_ERROR(error) { \ - if( running_status ) gdb_putpacketz("X1D"); \ - else gdb_putpacketz("EFF"); \ - running_status = 0; \ - target_list_free(); \ - morse("TARGET LOST.", 1); \ - longjmp(fatal_error_jmpbuf, (error)); \ -} - #define PLATFORM_HAS_TRACESWO inline static void gpio_set_val(uint32_t port, uint8_t pin, uint8_t val) { diff --git a/src/platforms/libftdi/platform.h b/src/platforms/libftdi/platform.h index 135b2e3..8611674 100644 --- a/src/platforms/libftdi/platform.h +++ b/src/platforms/libftdi/platform.h @@ -36,9 +36,6 @@ #define SET_IDLE_STATE(state) #define SET_ERROR_STATE(state) -#define PLATFORM_FATAL_ERROR(error) abort() -#define PLATFORM_SET_FATAL_ERROR_RECOVERY() - extern struct ftdi_context *ftdic; void platform_buffer_flush(void); diff --git a/src/platforms/native/platform.c b/src/platforms/native/platform.c index ac54b4b..babb498 100644 --- a/src/platforms/native/platform.c +++ b/src/platforms/native/platform.c @@ -35,8 +35,6 @@ #include #include -jmp_buf fatal_error_jmpbuf; - static void adc_init(void); static void setup_vbus_irq(void); diff --git a/src/platforms/native/platform.h b/src/platforms/native/platform.h index 3b1769b..6958585 100644 --- a/src/platforms/native/platform.h +++ b/src/platforms/native/platform.h @@ -24,13 +24,9 @@ #ifndef __PLATFORM_H #define __PLATFORM_H -#include "gdb_packet.h" #include "gpio.h" -#include "morse.h" #include "timing.h" -#include - #define PLATFORM_HAS_TRACESWO #define PLATFORM_HAS_POWER_SWITCH #define BOARD_IDENT "Black Magic Probe" @@ -147,23 +143,10 @@ #define DEBUG(...) -extern jmp_buf fatal_error_jmpbuf; - #define SET_RUN_STATE(state) {running_status = (state);} #define SET_IDLE_STATE(state) {gpio_set_val(LED_PORT, LED_IDLE_RUN, state);} #define SET_ERROR_STATE(state) {gpio_set_val(LED_PORT, LED_ERROR, state);} -#include "target.h" -#define PLATFORM_SET_FATAL_ERROR_RECOVERY() {setjmp(fatal_error_jmpbuf);} -#define PLATFORM_FATAL_ERROR(error) do { \ - if(running_status) gdb_putpacketz("X1D"); \ - else gdb_putpacketz("EFF"); \ - running_status = 0; \ - target_list_free(); \ - morse("TARGET LOST.", 1); \ - longjmp(fatal_error_jmpbuf, (error)); \ -} while (0) - /* Use newlib provided integer only stdio functions */ #define sscanf siscanf #define sprintf siprintf diff --git a/src/platforms/stlink/platform.c b/src/platforms/stlink/platform.c index fb10faa..dd501a4 100644 --- a/src/platforms/stlink/platform.c +++ b/src/platforms/stlink/platform.c @@ -36,8 +36,6 @@ uint8_t running_status; volatile uint32_t timeout_counter; -jmp_buf fatal_error_jmpbuf; - uint16_t led_idle_run; /* Pins PC[14:13] are used to detect hardware revision. Read * 11 for STLink V1 e.g. on VL Discovery, tag as hwversion 0 diff --git a/src/platforms/stlink/platform.h b/src/platforms/stlink/platform.h index 549b6d6..aa02ac0 100644 --- a/src/platforms/stlink/platform.h +++ b/src/platforms/stlink/platform.h @@ -24,17 +24,13 @@ #ifndef __PLATFORM_H #define __PLATFORM_H -#include "gdb_packet.h" #include "gpio.h" #include "timing.h" -#include "target.h" #include #include #include -#include - #define BOARD_IDENT "Black Magic Probe (STLINK), (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" #define BOARD_IDENT_DFU "Black Magic (Upgrade) for STLink/Discovery, (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" #define BOARD_IDENT_UPD "Black Magic (DFU Upgrade) for STLink/Discovery, (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" @@ -131,23 +127,12 @@ #define DEBUG(...) -extern jmp_buf fatal_error_jmpbuf; - extern uint16_t led_idle_run; #define LED_IDLE_RUN led_idle_run #define SET_RUN_STATE(state) {running_status = (state);} #define SET_IDLE_STATE(state) {gpio_set_val(LED_PORT, led_idle_run, state);} #define SET_ERROR_STATE(x) -#define PLATFORM_SET_FATAL_ERROR_RECOVERY() {setjmp(fatal_error_jmpbuf);} -#define PLATFORM_FATAL_ERROR(error) do { \ - if(running_status) gdb_putpacketz("X1D"); \ - else gdb_putpacketz("EFF"); \ - running_status = 0; \ - target_list_free(); \ - longjmp(fatal_error_jmpbuf, (error)); \ -} while (0) - /* Use newlib provided integer only stdio functions */ #define sscanf siscanf #define sprintf siprintf diff --git a/src/platforms/swlink/platform.c b/src/platforms/swlink/platform.c index cbdae0c..02cde19 100644 --- a/src/platforms/swlink/platform.c +++ b/src/platforms/swlink/platform.c @@ -33,8 +33,6 @@ #include #include -jmp_buf fatal_error_jmpbuf; - void platform_init(void) { uint32_t data; diff --git a/src/platforms/swlink/platform.h b/src/platforms/swlink/platform.h index e82124a..2c6fb76 100644 --- a/src/platforms/swlink/platform.h +++ b/src/platforms/swlink/platform.h @@ -24,12 +24,8 @@ #ifndef __PLATFORM_H #define __PLATFORM_H -#include "gdb_packet.h" #include "gpio.h" #include "timing.h" -#include "target.h" - -#include #define BOARD_IDENT "Black Magic Probe (SWLINK), (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" #define BOARD_IDENT_DFU "Black Magic (Upgrade), STM8S Discovery, (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" @@ -126,21 +122,10 @@ #define DEBUG(...) -extern jmp_buf fatal_error_jmpbuf; - #define SET_RUN_STATE(state) {running_status = (state);} #define SET_IDLE_STATE(state) {gpio_set_val(LED_PORT, LED_IDLE_RUN, state);} #define SET_ERROR_STATE(x) -#define PLATFORM_SET_FATAL_ERROR_RECOVERY() {setjmp(fatal_error_jmpbuf);} -#define PLATFORM_FATAL_ERROR(error) { \ - if(running_status) gdb_putpacketz("X1D"); \ - else gdb_putpacketz("EFF"); \ - running_status = 0; \ - target_list_free(); \ - longjmp(fatal_error_jmpbuf, (error)); \ -} - /* Use newlib provided integer only stdio functions */ #define sscanf siscanf #define sprintf siprintf -- cgit v1.2.3 From bda4279028f914bb4d127fea1e3029dbc071b3a0 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Thu, 26 Mar 2015 20:42:47 -0700 Subject: Send error reply and abandon target list on unhandled timeout. --- src/main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/main.c b/src/main.c index d1b3c86..9f37107 100644 --- a/src/main.c +++ b/src/main.c @@ -48,7 +48,7 @@ main(int argc, char **argv) TRY_CATCH(e, EXCEPTION_ALL) { gdb_main(); } - if (e.type == EXCEPTION_ERROR) { + if (e.type) { gdb_putpacketz("EFF"); target_list_free(); morse("TARGET LOST.", 1); -- cgit v1.2.3 From 64c79e1d03339cb21eca6ff4cd95fc3d7093aec5 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sun, 22 Mar 2015 20:45:45 -0700 Subject: Consistently name target var 't' in cortexm. --- src/cortexm.c | 279 +++++++++++++++++++++++++-------------------------- src/include/target.h | 64 ++++++------ 2 files changed, 166 insertions(+), 177 deletions(-) (limited to 'src') diff --git a/src/cortexm.c b/src/cortexm.c index f6a0ea3..78f78df 100644 --- a/src/cortexm.c +++ b/src/cortexm.c @@ -60,23 +60,23 @@ const struct command_s cortexm_cmd_list[] = { #define SIGSEGV 11 #define SIGLOST 29 -static int cortexm_regs_read(struct target_s *target, void *data); -static int cortexm_regs_write(struct target_s *target, const void *data); -static int cortexm_pc_write(struct target_s *target, const uint32_t val); -static uint32_t cortexm_pc_read(struct target_s *target); +static int cortexm_regs_read(target *t, void *data); +static int cortexm_regs_write(target *t, const void *data); +static int cortexm_pc_write(target *t, const uint32_t val); +static uint32_t cortexm_pc_read(target *t); -static void cortexm_reset(struct target_s *target); -static int cortexm_halt_wait(struct target_s *target); -static void cortexm_halt_request(struct target_s *target); -static int cortexm_fault_unwind(struct target_s *target); +static void cortexm_reset(target *t); +static int cortexm_halt_wait(target *t); +static void cortexm_halt_request(target *t); +static int cortexm_fault_unwind(target *t); -static int cortexm_set_hw_bp(struct target_s *target, uint32_t addr); -static int cortexm_clear_hw_bp(struct target_s *target, uint32_t addr); +static int cortexm_set_hw_bp(target *t, uint32_t addr); +static int cortexm_clear_hw_bp(target *t, uint32_t addr); -static int cortexm_set_hw_wp(struct target_s *target, uint8_t type, uint32_t addr, uint8_t len); -static int cortexm_clear_hw_wp(struct target_s *target, uint8_t type, uint32_t addr, uint8_t len); +static int cortexm_set_hw_wp(target *t, uint8_t type, uint32_t addr, uint8_t len); +static int cortexm_clear_hw_wp(target *t, uint8_t type, uint32_t addr, uint8_t len); -static int cortexm_check_hw_wp(struct target_s *target, uint32_t *addr); +static int cortexm_check_hw_wp(target *t, uint32_t *addr); #define CORTEXM_MAX_WATCHPOINTS 4 /* architecture says up to 15, no implementation has > 4 */ #define CORTEXM_MAX_BREAKPOINTS 6 /* architecture says up to 127, no implementation has > 6 */ @@ -207,42 +207,41 @@ static const char tdesc_cortex_mf[] = #define REG_PSP 18 #define REG_SPECIAL 19 -bool -cortexm_probe(struct target_s *target) +bool cortexm_probe(target *t) { - target->driver = cortexm_driver_str; + t->driver = cortexm_driver_str; - target->attach = cortexm_attach; - target->detach = cortexm_detach; + t->attach = cortexm_attach; + t->detach = cortexm_detach; /* Should probe here to make sure it's Cortex-M3 */ - target->tdesc = tdesc_cortex_m; - target->regs_read = cortexm_regs_read; - target->regs_write = cortexm_regs_write; - target->pc_write = cortexm_pc_write; - target->pc_read = cortexm_pc_read; + t->tdesc = tdesc_cortex_m; + t->regs_read = cortexm_regs_read; + t->regs_write = cortexm_regs_write; + t->pc_write = cortexm_pc_write; + t->pc_read = cortexm_pc_read; - target->reset = cortexm_reset; - target->halt_request = cortexm_halt_request; - target->halt_wait = cortexm_halt_wait; - target->halt_resume = cortexm_halt_resume; - target->regs_size = sizeof(regnum_cortex_m); + t->reset = cortexm_reset; + t->halt_request = cortexm_halt_request; + t->halt_wait = cortexm_halt_wait; + t->halt_resume = cortexm_halt_resume; + t->regs_size = sizeof(regnum_cortex_m); - target->hostio_reply = cortexm_hostio_reply; + t->hostio_reply = cortexm_hostio_reply; - target_add_commands(target, cortexm_cmd_list, cortexm_driver_str); + target_add_commands(t, cortexm_cmd_list, cortexm_driver_str); /* Probe for FP extension */ - uint32_t cpacr = target_mem_read32(target, CORTEXM_CPACR); + uint32_t cpacr = target_mem_read32(t, CORTEXM_CPACR); cpacr |= 0x00F00000; /* CP10 = 0b11, CP11 = 0b11 */ - target_mem_write32(target, CORTEXM_CPACR, cpacr); - if (target_mem_read32(target, CORTEXM_CPACR) == cpacr) { - target->target_options |= TOPT_FLAVOUR_V7MF; - target->regs_size += sizeof(regnum_cortex_mf); - target->tdesc = tdesc_cortex_mf; + target_mem_write32(t, CORTEXM_CPACR, cpacr); + if (target_mem_read32(t, CORTEXM_CPACR) == cpacr) { + t->target_options |= TOPT_FLAVOUR_V7MF; + t->regs_size += sizeof(regnum_cortex_mf); + t->tdesc = tdesc_cortex_mf; } - ADIv5_AP_t *ap = adiv5_target_ap(target); + ADIv5_AP_t *ap = adiv5_target_ap(t); struct cortexm_priv *priv = calloc(1, sizeof(*priv)); ap->priv = priv; ap->priv_free = free; @@ -252,7 +251,7 @@ cortexm_probe(struct target_s *target) CORTEXM_DEMCR_VC_CORERESET; #define PROBE(x) \ - do { if ((x)(target)) return true; else target_check_error(target); } while (0) + do { if ((x)(t)) return true; else target_check_error(t); } while (0) PROBE(stm32f1_probe); PROBE(stm32f4_probe); @@ -270,62 +269,62 @@ cortexm_probe(struct target_s *target) return true; } -bool cortexm_attach(struct target_s *target) +bool cortexm_attach(target *t) { - ADIv5_AP_t *ap = adiv5_target_ap(target); + ADIv5_AP_t *ap = adiv5_target_ap(t); struct cortexm_priv *priv = ap->priv; unsigned i; uint32_t r; int tries; /* Clear any pending fault condition */ - target_check_error(target); + target_check_error(t); - target_halt_request(target); + target_halt_request(t); tries = 10; - while(!connect_assert_srst && !target_halt_wait(target) && --tries) + while(!connect_assert_srst && !target_halt_wait(t) && --tries) platform_delay(2); if(!tries) return false; /* Request halt on reset */ - target_mem_write32(target, CORTEXM_DEMCR, priv->demcr); + target_mem_write32(t, CORTEXM_DEMCR, priv->demcr); /* Reset DFSR flags */ - target_mem_write32(target, CORTEXM_DFSR, CORTEXM_DFSR_RESETALL); + target_mem_write32(t, CORTEXM_DFSR, CORTEXM_DFSR_RESETALL); /* size the break/watchpoint units */ priv->hw_breakpoint_max = CORTEXM_MAX_BREAKPOINTS; - r = target_mem_read32(target, CORTEXM_FPB_CTRL); + r = target_mem_read32(t, CORTEXM_FPB_CTRL); if (((r >> 4) & 0xf) < priv->hw_breakpoint_max) /* only look at NUM_COMP1 */ priv->hw_breakpoint_max = (r >> 4) & 0xf; priv->hw_watchpoint_max = CORTEXM_MAX_WATCHPOINTS; - r = target_mem_read32(target, CORTEXM_DWT_CTRL); + r = target_mem_read32(t, CORTEXM_DWT_CTRL); if ((r >> 28) > priv->hw_watchpoint_max) priv->hw_watchpoint_max = r >> 28; /* Clear any stale breakpoints */ for(i = 0; i < priv->hw_breakpoint_max; i++) { - target_mem_write32(target, CORTEXM_FPB_COMP(i), 0); + target_mem_write32(t, CORTEXM_FPB_COMP(i), 0); priv->hw_breakpoint[i] = 0; } /* Clear any stale watchpoints */ for(i = 0; i < priv->hw_watchpoint_max; i++) { - target_mem_write32(target, CORTEXM_DWT_FUNC(i), 0); + target_mem_write32(t, CORTEXM_DWT_FUNC(i), 0); priv->hw_watchpoint[i].type = 0; } /* Flash Patch Control Register: set ENABLE */ - target_mem_write32(target, CORTEXM_FPB_CTRL, + target_mem_write32(t, CORTEXM_FPB_CTRL, CORTEXM_FPB_CTRL_KEY | CORTEXM_FPB_CTRL_ENABLE); - target->set_hw_bp = cortexm_set_hw_bp; - target->clear_hw_bp = cortexm_clear_hw_bp; + t->set_hw_bp = cortexm_set_hw_bp; + t->clear_hw_bp = cortexm_clear_hw_bp; /* Data Watchpoint and Trace */ - target->set_hw_wp = cortexm_set_hw_wp; - target->clear_hw_wp = cortexm_clear_hw_wp; - target->check_hw_wp = cortexm_check_hw_wp; + t->set_hw_wp = cortexm_set_hw_wp; + t->clear_hw_wp = cortexm_clear_hw_wp; + t->check_hw_wp = cortexm_check_hw_wp; if(connect_assert_srst) jtagtap_srst(false); @@ -333,28 +332,27 @@ bool cortexm_attach(struct target_s *target) return true; } -void cortexm_detach(struct target_s *target) +void cortexm_detach(target *t) { - ADIv5_AP_t *ap = adiv5_target_ap(target); + ADIv5_AP_t *ap = adiv5_target_ap(t); struct cortexm_priv *priv = ap->priv; unsigned i; /* Clear any stale breakpoints */ for(i = 0; i < priv->hw_breakpoint_max; i++) - target_mem_write32(target, CORTEXM_FPB_COMP(i), 0); + target_mem_write32(t, CORTEXM_FPB_COMP(i), 0); /* Clear any stale watchpoints */ for(i = 0; i < priv->hw_watchpoint_max; i++) - target_mem_write32(target, CORTEXM_DWT_FUNC(i), 0); + target_mem_write32(t, CORTEXM_DWT_FUNC(i), 0); /* Disable debug */ - target_mem_write32(target, CORTEXM_DHCSR, CORTEXM_DHCSR_DBGKEY); + target_mem_write32(t, CORTEXM_DHCSR, CORTEXM_DHCSR_DBGKEY); } -static int -cortexm_regs_read(struct target_s *target, void *data) +static int cortexm_regs_read(target *t, void *data) { - ADIv5_AP_t *ap = adiv5_target_ap(target); + ADIv5_AP_t *ap = adiv5_target_ap(t); uint32_t *regs = data; unsigned i; @@ -375,7 +373,7 @@ cortexm_regs_read(struct target_s *target, void *data) regnum_cortex_m[i]); *regs++ = adiv5_dp_read(ap->dp, ADIV5_AP_DB(2)); } - if (target->target_options & TOPT_FLAVOUR_V7MF) + if (t->target_options & TOPT_FLAVOUR_V7MF) for(i = 0; i < sizeof(regnum_cortex_mf) / 4; i++) { adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_DB(1), @@ -386,10 +384,9 @@ cortexm_regs_read(struct target_s *target, void *data) return 0; } -static int -cortexm_regs_write(struct target_s *target, const void *data) +static int cortexm_regs_write(target *t, const void *data) { - ADIv5_AP_t *ap = adiv5_target_ap(target); + ADIv5_AP_t *ap = adiv5_target_ap(t); const uint32_t *regs = data; unsigned i; @@ -412,7 +409,7 @@ cortexm_regs_write(struct target_s *target, const void *data) adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_DB(1), 0x10000 | regnum_cortex_m[i]); } - if (target->target_options & TOPT_FLAVOUR_V7MF) + if (t->target_options & TOPT_FLAVOUR_V7MF) for(i = 0; i < sizeof(regnum_cortex_mf) / 4; i++) { adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_DB(2), *regs++); @@ -424,55 +421,51 @@ cortexm_regs_write(struct target_s *target, const void *data) return 0; } -static uint32_t -cortexm_pc_read(struct target_s *target) +static uint32_t cortexm_pc_read(target *t) { - target_mem_write32(target, CORTEXM_DCRSR, 0x0F); - return target_mem_read32(target, CORTEXM_DCRDR); + target_mem_write32(t, CORTEXM_DCRSR, 0x0F); + return target_mem_read32(t, CORTEXM_DCRDR); return 0; } -static int -cortexm_pc_write(struct target_s *target, const uint32_t val) +static int cortexm_pc_write(target *t, const uint32_t val) { - target_mem_write32(target, CORTEXM_DCRDR, val); - target_mem_write32(target, CORTEXM_DCRSR, CORTEXM_DCRSR_REGWnR | 0x0F); + target_mem_write32(t, CORTEXM_DCRDR, val); + target_mem_write32(t, CORTEXM_DCRSR, CORTEXM_DCRSR_REGWnR | 0x0F); return 0; } /* The following three routines implement target halt/resume * using the core debug registers in the NVIC. */ -static void -cortexm_reset(struct target_s *target) +static void cortexm_reset(target *t) { jtagtap_srst(true); jtagtap_srst(false); /* Read DHCSR here to clear S_RESET_ST bit before reset */ - target_mem_read32(target, CORTEXM_DHCSR); + target_mem_read32(t, CORTEXM_DHCSR); /* Request system reset from NVIC: SRST doesn't work correctly */ /* This could be VECTRESET: 0x05FA0001 (reset only core) * or SYSRESETREQ: 0x05FA0004 (system reset) */ - target_mem_write32(target, CORTEXM_AIRCR, + target_mem_write32(t, CORTEXM_AIRCR, CORTEXM_AIRCR_VECTKEY | CORTEXM_AIRCR_SYSRESETREQ); /* Poll for release from reset */ - while (target_mem_read32(target, CORTEXM_DHCSR) & CORTEXM_DHCSR_S_RESET_ST); + while (target_mem_read32(t, CORTEXM_DHCSR) & CORTEXM_DHCSR_S_RESET_ST); /* Reset DFSR flags */ - target_mem_write32(target, CORTEXM_DFSR, CORTEXM_DFSR_RESETALL); + target_mem_write32(t, CORTEXM_DFSR, CORTEXM_DFSR_RESETALL); } -static void -cortexm_halt_request(struct target_s *target) +static void cortexm_halt_request(target *t) { volatile struct exception e; TRY_CATCH (e, EXCEPTION_TIMEOUT) { - target_mem_write32(target, CORTEXM_DHCSR, CORTEXM_DHCSR_DBGKEY | + target_mem_write32(t, CORTEXM_DHCSR, CORTEXM_DHCSR_DBGKEY | CORTEXM_DHCSR_C_HALT | CORTEXM_DHCSR_C_DEBUGEN); } @@ -481,10 +474,9 @@ cortexm_halt_request(struct target_s *target) } } -static int -cortexm_halt_wait(struct target_s *target) +static int cortexm_halt_wait(target *t) { - ADIv5_AP_t *ap = adiv5_target_ap(target); + ADIv5_AP_t *ap = adiv5_target_ap(t); struct cortexm_priv *priv = ap->priv; uint32_t dhcsr = 0; @@ -492,7 +484,7 @@ cortexm_halt_wait(struct target_s *target) TRY_CATCH (e, EXCEPTION_ALL) { /* If this times out because the target is in WFI then * the target is still running. */ - dhcsr = target_mem_read32(target, CORTEXM_DHCSR); + dhcsr = target_mem_read32(t, CORTEXM_DHCSR); } switch (e.type) { case EXCEPTION_ERROR: @@ -509,10 +501,10 @@ cortexm_halt_wait(struct target_s *target) return 0; /* We've halted. Let's find out why. */ - uint32_t dfsr = target_mem_read32(target, CORTEXM_DFSR); - target_mem_write32(target, CORTEXM_DFSR, dfsr); /* write back to reset */ + uint32_t dfsr = target_mem_read32(t, CORTEXM_DFSR); + target_mem_write32(t, CORTEXM_DFSR, dfsr); /* write back to reset */ - if ((dfsr & CORTEXM_DFSR_VCATCH) && cortexm_fault_unwind(target)) + if ((dfsr & CORTEXM_DFSR_VCATCH) && cortexm_fault_unwind(t)) return SIGSEGV; /* Remember if we stopped on a breakpoint */ @@ -520,13 +512,13 @@ cortexm_halt_wait(struct target_s *target) if (priv->on_bkpt) { /* If we've hit a programmed breakpoint, check for semihosting * call. */ - uint32_t pc = cortexm_pc_read(target); + uint32_t pc = cortexm_pc_read(t); uint16_t bkpt_instr; - bkpt_instr = target_mem_read16(target, pc); + bkpt_instr = target_mem_read16(t, pc); if (bkpt_instr == 0xBEAB) { - int n = cortexm_hostio_request(target); + int n = cortexm_hostio_request(t); if (n > 0) { - target_halt_resume(target, priv->stepping); + target_halt_resume(t, priv->stepping); return 0; } else if (n < 0) { return -1; @@ -544,9 +536,9 @@ cortexm_halt_wait(struct target_s *target) } -void cortexm_halt_resume(struct target_s *target, bool step) +void cortexm_halt_resume(target *t, bool step) { - ADIv5_AP_t *ap = adiv5_target_ap(target); + ADIv5_AP_t *ap = adiv5_target_ap(t); struct cortexm_priv *priv = ap->priv; uint32_t dhcsr = CORTEXM_DHCSR_DBGKEY | CORTEXM_DHCSR_C_DEBUGEN; @@ -555,42 +547,42 @@ void cortexm_halt_resume(struct target_s *target, bool step) /* Disable interrupts while single stepping... */ if(step != priv->stepping) { - target_mem_write32(target, CORTEXM_DHCSR, dhcsr | CORTEXM_DHCSR_C_HALT); + target_mem_write32(t, CORTEXM_DHCSR, dhcsr | CORTEXM_DHCSR_C_HALT); priv->stepping = step; } if (priv->on_bkpt) { - uint32_t pc = cortexm_pc_read(target); - if ((target_mem_read16(target, pc) & 0xFF00) == 0xBE00) - cortexm_pc_write(target, pc + 2); + uint32_t pc = cortexm_pc_read(t); + if ((target_mem_read16(t, pc) & 0xFF00) == 0xBE00) + cortexm_pc_write(t, pc + 2); } - target_mem_write32(target, CORTEXM_DHCSR, dhcsr); + target_mem_write32(t, CORTEXM_DHCSR, dhcsr); } -static int cortexm_fault_unwind(struct target_s *target) +static int cortexm_fault_unwind(target *t) { - uint32_t hfsr = target_mem_read32(target, CORTEXM_HFSR); - uint32_t cfsr = target_mem_read32(target, CORTEXM_CFSR); - target_mem_write32(target, CORTEXM_HFSR, hfsr);/* write back to reset */ - target_mem_write32(target, CORTEXM_CFSR, cfsr);/* write back to reset */ + uint32_t hfsr = target_mem_read32(t, CORTEXM_HFSR); + uint32_t cfsr = target_mem_read32(t, CORTEXM_CFSR); + target_mem_write32(t, CORTEXM_HFSR, hfsr);/* write back to reset */ + target_mem_write32(t, CORTEXM_CFSR, cfsr);/* write back to reset */ /* We check for FORCED in the HardFault Status Register or * for a configurable fault to avoid catching core resets */ if((hfsr & CORTEXM_HFSR_FORCED) || cfsr) { /* Unwind exception */ - uint32_t regs[target->regs_size / 4]; + uint32_t regs[t->regs_size / 4]; uint32_t stack[8]; uint32_t retcode, framesize; /* Read registers for post-exception stack pointer */ - target_regs_read(target, regs); + target_regs_read(t, regs); /* save retcode currently in lr */ retcode = regs[REG_LR]; bool spsel = retcode & (1<<2); bool fpca = !(retcode & (1<<4)); /* Read stack for pre-exception registers */ uint32_t sp = spsel ? regs[REG_PSP] : regs[REG_MSP]; - target_mem_read(target, stack, sp, sizeof(stack)); - if (target_check_error(target)) + target_mem_read(t, stack, sp, sizeof(stack)); + if (target_check_error(t)) return 0; regs[REG_LR] = stack[5]; /* restore LR to pre-exception state */ regs[REG_PC] = stack[6]; /* restore PC to pre-exception state */ @@ -616,22 +608,22 @@ static int cortexm_fault_unwind(struct target_s *target) /* Reset exception state to allow resuming from restored * state. */ - target_mem_write32(target, CORTEXM_AIRCR, + target_mem_write32(t, CORTEXM_AIRCR, CORTEXM_AIRCR_VECTKEY | CORTEXM_AIRCR_VECTCLRACTIVE); /* Write pre-exception registers back to core */ - target_regs_write(target, regs); + target_regs_write(t, regs); return 1; } return 0; } -int cortexm_run_stub(struct target_s *target, uint32_t loadaddr, +int cortexm_run_stub(target *t, uint32_t loadaddr, const uint16_t *stub, uint32_t stublen, uint32_t r0, uint32_t r1, uint32_t r2, uint32_t r3) { - uint32_t regs[target->regs_size / 4]; + uint32_t regs[t->regs_size / 4]; memset(regs, 0, sizeof(regs)); regs[0] = r0; @@ -642,19 +634,19 @@ int cortexm_run_stub(struct target_s *target, uint32_t loadaddr, regs[16] = 0x1000000; regs[19] = 0; - target_mem_write(target, loadaddr, stub, stublen); - cortexm_regs_write(target, regs); + target_mem_write(t, loadaddr, stub, stublen); + cortexm_regs_write(t, regs); - if (target_check_error(target)) + if (target_check_error(t)) return -1; /* Execute the stub */ - cortexm_halt_resume(target, 0); - while (!cortexm_halt_wait(target)) + cortexm_halt_resume(t, 0); + while (!cortexm_halt_wait(t)) ; - uint32_t pc = cortexm_pc_read(target); - uint16_t bkpt_instr = target_mem_read16(target, pc); + uint32_t pc = cortexm_pc_read(t); + uint16_t bkpt_instr = target_mem_read16(t, pc); if (bkpt_instr >> 8 != 0xbe) return -2; @@ -664,10 +656,9 @@ int cortexm_run_stub(struct target_s *target, uint32_t loadaddr, /* The following routines implement hardware breakpoints. * The Flash Patch and Breakpoint (FPB) system is used. */ -static int -cortexm_set_hw_bp(struct target_s *target, uint32_t addr) +static int cortexm_set_hw_bp(target *t, uint32_t addr) { - ADIv5_AP_t *ap = adiv5_target_ap(target); + ADIv5_AP_t *ap = adiv5_target_ap(t); struct cortexm_priv *priv = ap->priv; uint32_t val = addr & 0x1FFFFFFC; unsigned i; @@ -682,15 +673,14 @@ cortexm_set_hw_bp(struct target_s *target, uint32_t addr) priv->hw_breakpoint[i] = addr | 1; - target_mem_write32(target, CORTEXM_FPB_COMP(i), val); + target_mem_write32(t, CORTEXM_FPB_COMP(i), val); return 0; } -static int -cortexm_clear_hw_bp(struct target_s *target, uint32_t addr) +static int cortexm_clear_hw_bp(target *t, uint32_t addr) { - ADIv5_AP_t *ap = adiv5_target_ap(target); + ADIv5_AP_t *ap = adiv5_target_ap(t); struct cortexm_priv *priv = ap->priv; unsigned i; @@ -701,7 +691,7 @@ cortexm_clear_hw_bp(struct target_s *target, uint32_t addr) priv->hw_breakpoint[i] = 0; - target_mem_write32(target, CORTEXM_FPB_COMP(i), 0); + target_mem_write32(t, CORTEXM_FPB_COMP(i), 0); return 0; } @@ -710,9 +700,9 @@ cortexm_clear_hw_bp(struct target_s *target, uint32_t addr) * The Data Watch and Trace (DWT) system is used. */ static int -cortexm_set_hw_wp(struct target_s *target, uint8_t type, uint32_t addr, uint8_t len) +cortexm_set_hw_wp(target *t, uint8_t type, uint32_t addr, uint8_t len) { - ADIv5_AP_t *ap = adiv5_target_ap(target); + ADIv5_AP_t *ap = adiv5_target_ap(t); struct cortexm_priv *priv = ap->priv; unsigned i; @@ -734,7 +724,7 @@ cortexm_set_hw_wp(struct target_s *target, uint8_t type, uint32_t addr, uint8_t for(i = 0; i < priv->hw_watchpoint_max; i++) if((priv->hw_watchpoint[i].type == 0) && - ((target_mem_read32(target, CORTEXM_DWT_FUNC(i)) & 0xF) == 0)) + ((target_mem_read32(t, CORTEXM_DWT_FUNC(i)) & 0xF) == 0)) break; if(i == priv->hw_watchpoint_max) return -2; @@ -743,18 +733,18 @@ cortexm_set_hw_wp(struct target_s *target, uint8_t type, uint32_t addr, uint8_t priv->hw_watchpoint[i].addr = addr; priv->hw_watchpoint[i].size = len; - target_mem_write32(target, CORTEXM_DWT_COMP(i), addr); - target_mem_write32(target, CORTEXM_DWT_MASK(i), len); - target_mem_write32(target, CORTEXM_DWT_FUNC(i), type | - ((target->target_options & TOPT_FLAVOUR_V6M) ? 0: CORTEXM_DWT_FUNC_DATAVSIZE_WORD)); + target_mem_write32(t, CORTEXM_DWT_COMP(i), addr); + target_mem_write32(t, CORTEXM_DWT_MASK(i), len); + target_mem_write32(t, CORTEXM_DWT_FUNC(i), type | + ((t->target_options & TOPT_FLAVOUR_V6M) ? 0: CORTEXM_DWT_FUNC_DATAVSIZE_WORD)); return 0; } static int -cortexm_clear_hw_wp(struct target_s *target, uint8_t type, uint32_t addr, uint8_t len) +cortexm_clear_hw_wp(target *t, uint8_t type, uint32_t addr, uint8_t len) { - ADIv5_AP_t *ap = adiv5_target_ap(target); + ADIv5_AP_t *ap = adiv5_target_ap(t); struct cortexm_priv *priv = ap->priv; unsigned i; @@ -783,22 +773,21 @@ cortexm_clear_hw_wp(struct target_s *target, uint8_t type, uint32_t addr, uint8_ priv->hw_watchpoint[i].type = 0; - target_mem_write32(target, CORTEXM_DWT_FUNC(i), 0); + target_mem_write32(t, CORTEXM_DWT_FUNC(i), 0); return 0; } -static int -cortexm_check_hw_wp(struct target_s *target, uint32_t *addr) +static int cortexm_check_hw_wp(target *t, uint32_t *addr) { - ADIv5_AP_t *ap = adiv5_target_ap(target); + ADIv5_AP_t *ap = adiv5_target_ap(t); struct cortexm_priv *priv = ap->priv; unsigned i; for(i = 0; i < priv->hw_watchpoint_max; i++) /* if SET and MATCHED then break */ if(priv->hw_watchpoint[i].type && - (target_mem_read32(target, CORTEXM_DWT_FUNC(i)) & + (target_mem_read32(t, CORTEXM_DWT_FUNC(i)) & CORTEXM_DWT_FUNC_MATCHED)) break; diff --git a/src/include/target.h b/src/include/target.h index b6ea67d..34f26eb 100644 --- a/src/include/target.h +++ b/src/include/target.h @@ -116,39 +116,39 @@ struct target_s { target_destroy_callback destroy_callback; /* Attach/Detach funcitons */ - bool (*attach)(struct target_s *target); - void (*detach)(struct target_s *target); - int (*check_error)(struct target_s *target); + bool (*attach)(target *t); + void (*detach)(target *t); + int (*check_error)(target *t); /* Memory access functions */ - void (*mem_read)(struct target_s *target, void *dest, uint32_t src, + void (*mem_read)(target *t, void *dest, uint32_t src, size_t len); - void (*mem_write)(struct target_s *target, uint32_t dest, + void (*mem_write)(target *t, uint32_t dest, const void *src, size_t len); /* Register access functions */ int regs_size; const char *tdesc; - int (*regs_read)(struct target_s *target, void *data); - int (*regs_write)(struct target_s *target, const void *data); + int (*regs_read)(target *t, void *data); + int (*regs_write)(target *t, const void *data); - uint32_t (*pc_read)(struct target_s *target); - int (*pc_write)(struct target_s *target, const uint32_t val); + uint32_t (*pc_read)(target *t); + int (*pc_write)(target *t, const uint32_t val); /* Halt/resume functions */ - void (*reset)(struct target_s *target); - void (*halt_request)(struct target_s *target); - int (*halt_wait)(struct target_s *target); - void (*halt_resume)(struct target_s *target, bool step); + void (*reset)(target *t); + void (*halt_request)(target *t); + int (*halt_wait)(target *t); + void (*halt_resume)(target *t, bool step); /* Break-/watchpoint functions */ - int (*set_hw_bp)(struct target_s *target, uint32_t addr); - int (*clear_hw_bp)(struct target_s *target, uint32_t addr); + int (*set_hw_bp)(target *t, uint32_t addr); + int (*clear_hw_bp)(target *t, uint32_t addr); - int (*set_hw_wp)(struct target_s *target, uint8_t type, uint32_t addr, uint8_t len); - int (*clear_hw_wp)(struct target_s *target, uint8_t type, uint32_t addr, uint8_t len); + int (*set_hw_wp)(target *t, uint8_t type, uint32_t addr, uint8_t len); + int (*clear_hw_wp)(target *t, uint8_t type, uint32_t addr, uint8_t len); - int (*check_hw_wp)(struct target_s *target, uint32_t *addr); + int (*check_hw_wp)(target *t, uint32_t *addr); /* target-defined options */ unsigned target_options; @@ -156,8 +156,8 @@ struct target_s { /* Flash memory access functions */ const char *xml_mem_map; - int (*flash_erase)(struct target_s *target, uint32_t addr, size_t len); - int (*flash_write)(struct target_s *target, uint32_t dest, + int (*flash_erase)(target *t, uint32_t addr, size_t len); + int (*flash_write)(target *t, uint32_t dest, const uint8_t *src, size_t len); /* Host I/O support */ @@ -226,18 +226,18 @@ static inline void target_mem_write8(target *t, uint32_t addr, uint8_t value) /* Probe for various targets. * Actual functions implemented in their respective drivers. */ -bool cortexm_probe(struct target_s *target); -bool stm32f1_probe(struct target_s *target); -bool stm32f4_probe(struct target_s *target); -bool stm32l0_probe(struct target_s *target); -bool stm32l1_probe(struct target_s *target); -bool lmi_probe(struct target_s *target); -bool lpc11xx_probe(struct target_s *target); -bool lpc43xx_probe(struct target_s *target); -bool sam3x_probe(struct target_s *target); -bool nrf51_probe(struct target_s *target); -bool samd_probe(struct target_s *target); -bool kinetis_probe(struct target_s *target); +bool cortexm_probe(target *t); +bool stm32f1_probe(target *t); +bool stm32f4_probe(target *t); +bool stm32l0_probe(target *t); +bool stm32l1_probe(target *t); +bool lmi_probe(target *t); +bool lpc11xx_probe(target *t); +bool lpc43xx_probe(target *t); +bool sam3x_probe(target *t); +bool nrf51_probe(target *t); +bool samd_probe(target *t); +bool kinetis_probe(target *t); #endif -- cgit v1.2.3 From d9af3cca6ce9ef661436d57da286ddb96d07f120 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sun, 22 Mar 2015 20:47:30 -0700 Subject: Remove unfinished ARM7TDMI driver. --- src/Makefile | 1 - src/arm7tdmi.c | 291 -------------------------------------------------------- src/jtag_scan.c | 3 - 3 files changed, 295 deletions(-) delete mode 100644 src/arm7tdmi.c (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 73fb8e9..39c19ac 100644 --- a/src/Makefile +++ b/src/Makefile @@ -20,7 +20,6 @@ SRC = \ adiv5.c \ adiv5_jtagdp.c \ adiv5_swdp.c \ - arm7tdmi.c \ command.c \ cortexm.c \ crc32.c \ diff --git a/src/arm7tdmi.c b/src/arm7tdmi.c deleted file mode 100644 index afd623c..0000000 --- a/src/arm7tdmi.c +++ /dev/null @@ -1,291 +0,0 @@ -/* - * This file is part of the Black Magic Debug project. - * - * Copyright (C) 2011 Black Sphere Technologies Ltd. - * Written by Gareth McMullin - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * 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, see . - */ - -/* This file implements the ARM7TDMI target support using the JTAG - * interface as described in ARM7TDMI Technical Reference Manual, - * ARM Document DDI 0210C - */ - -#include "general.h" -#include "target.h" -#include "jtag_scan.h" -#include "jtagtap.h" - -/* TODO: - * Skeleton target. - * EmbeddedICE registers, halt/resume target. - * Check target mode on halt, switch to ARM if needed. - * Read registers on halt, restore on resume. Give GDB cached copy. - * System speed access, read/write memory. - * Misaligned/byte memory access. - * Breakpoint support. - * Watchpoint support. - * Funnies: abort on breakpointed instruction, etc. - * Flash programming for STR73x and LPC2xxx. - */ -static const char arm7_driver_str[] = "ARM7TDMI"; - -/* ARM7 JTAG IR values */ -#define ARM7_IR_EXTEST 0x0 -#define ARM7_IR_SCAN_N 0x2 -#define ARM7_IR_SAMPLE_PRELOAD 0x3 -#define ARM7_IR_RESTART 0x4 -#define ARM7_IR_CLAMP 0x5 -#define ARM7_IR_HIGHZ 0x7 -#define ARM7_IR_CLAMPZ 0x9 -#define ARM7_IR_INTEST 0xC -#define ARM7_IR_IDCODE 0xE -#define ARM7_IR_BYPASS 0xF - -/* ARM7 SCAN_N scan chain values */ -#define ARM7_SCANN_BOUNDARY 0 -#define ARM7_SCANN_DBUS 1 -#define ARM7_SCANN_EICE 2 - -/* EmbeddedICE-RT Register addresses */ -#define ARM7_EICE_DEBUG_CTRL 0x00 -#define ARM7_EICE_DEBUG_STAT 0x01 -#define ARM7_EICE_ABORT_STAT 0x02 -#define ARM7_EICE_COMMS_CTRL 0x04 -#define ARM7_EICE_COMMS_DATA 0x05 -#define ARM7_EICE_WATCH_ADDR(x) (0x08 + (8 * (x)) -#define ARM7_EICE_WATCH_ADDR_MASK(x) (0x09 + (8 * (x)) -#define ARM7_EICE_WATCH_DATA(x) (0x0A + (8 * (x)) -#define ARM7_EICE_WATCH_DATA_MASK(x) (0x0B + (8 * (x)) -#define ARM7_EICE_WATCH_CTRL(x) (0x0C + (8 * (x)) -#define ARM7_EICE_WATCH_CTRL_MASK(x) (0x0D + (8 * (x)) - -/* Read/write bit in EmbeddedICE-RT scan chain */ -#define ARM7_EICE_READ (0uLL << 37) -#define ARM7_EICE_WRITE (1uLL << 37) - -/* Debug Control Register bits */ -#define ARM7_EICE_DEBUG_CTRL_EICE_DISABLE (1 << 5) -#define ARM7_EICE_DEBUG_CTRL_MONITOR (1 << 4) -/* Bit 3 - Reserved */ -#define ARM7_EICE_DEBUG_CTRL_INTDIS (1 << 2) -#define ARM7_EICE_DEBUG_CTRL_DBGRQ (1 << 1) -#define ARM7_EICE_DEBUG_CTRL_DBGACK (1 << 0) - -/* Debug Status Register bits */ -#define ARM7_EICE_DEBUG_STAT_TBIT (1 << 4) -#define ARM7_EICE_DEBUG_STAT_NMREQ (1 << 3) -#define ARM7_EICE_DEBUG_STAT_INTDIS (1 << 2) -#define ARM7_EICE_DEBUG_STAT_DBGRQ (1 << 1) -#define ARM7_EICE_DEBUG_STAT_DBGACK (1 << 0) - -#define ARM7_OP_NOP 0xE1A00000 - -struct target_arm7_s { - target t; - jtag_dev_t *jtag; - uint32_t reg_cache[16]; -}; - -/* FIXME: Remove: */ -static void do_nothing(void) -{ -} - -static bool arm7_attach(struct target_s *target); -static int arm7_regs_read(struct target_s *target, void *data); -static int arm7_regs_write(struct target_s *target, const void *data); -static void arm7_halt_request(struct target_s *target); -static int arm7_halt_wait(struct target_s *target); -static void arm7_halt_resume(struct target_s *target, bool step); - -void arm7tdmi_jtag_handler(jtag_dev_t *dev) -{ - struct target_arm7_s *tj = (void*)target_new(sizeof(*tj)); - target *t = (target *)tj; - - t->driver = arm7_driver_str; - tj->jtag = dev; - - /* Setup mandatory virtual methods */ - t->attach = arm7_attach; - t->detach = (void *)do_nothing; - t->check_error = (void *)do_nothing; - t->mem_read = (void *)do_nothing; - t->mem_write = (void *)do_nothing; - t->regs_size = 16 * sizeof(uint32_t); - t->regs_read = (void *)arm7_regs_read; - t->regs_write = (void *)arm7_regs_write; - t->pc_write = (void *)do_nothing; - t->reset = (void *)do_nothing; - t->halt_request = arm7_halt_request; - t->halt_wait = arm7_halt_wait; - t->halt_resume = arm7_halt_resume; - - /* TODO: Breakpoint and watchpoint functions. */ - /* TODO: Fault unwinder. */ - /* TODO: Memory map / Flash programming. */ -} - -static void arm7_select_scanchain(struct target_arm7_s *target, uint8_t chain) -{ - jtag_dev_write_ir(target->jtag, ARM7_IR_SCAN_N); - jtag_dev_shift_dr(target->jtag, NULL, &chain, 4); - jtag_dev_write_ir(target->jtag, ARM7_IR_INTEST); -} - -static void arm7_eice_write(struct target_arm7_s *target, - uint8_t addr, uint32_t value) -{ - uint64_t val = ((uint64_t)addr << 32) | value | ARM7_EICE_WRITE; - - arm7_select_scanchain(target, ARM7_SCANN_EICE); - jtag_dev_shift_dr(target->jtag, NULL, (uint8_t *)&val, 38); - DEBUG("eice_write(%d, 0x%08X)\n", addr, value); -} - -static uint32_t arm7_eice_read(struct target_arm7_s *target, uint8_t addr) -{ - uint64_t val = ((uint64_t)addr << 32) | ARM7_EICE_READ; - - arm7_select_scanchain(target, ARM7_SCANN_EICE); - jtag_dev_shift_dr(target->jtag, NULL, (uint8_t *)&val, 38); - jtag_dev_shift_dr(target->jtag, (uint8_t *)&val, (uint8_t *)&val, 38); - DEBUG("eice_read(%d, 0x%08X)\n", addr, (uint32_t)val); - - return (uint32_t)val; -} - -/* Execute a single instruction at debug speed. - * Performs datalen data bus accesses after the op to capture data. - */ -static void arm7_op_debug(struct target_arm7_s *t, uint32_t op, uint32_t *data, - int datalen) -{ - uint64_t tmp; - /* FIXME: This routine is broken. - * This process isn't very well documented. Maybe NOPs need to - * be shifted into pipeline before data is read out. - */ - DEBUG("op_debug(0x%08X)\n", op); - arm7_select_scanchain(t, ARM7_SCANN_DBUS); - tmp = op; - jtag_dev_shift_dr(t->jtag, NULL, (const uint8_t*)&tmp, 33); - while(datalen--) { - tmp = *data; - jtag_dev_shift_dr(t->jtag, (uint8_t*)&tmp, (uint8_t*)&tmp, 33); - *data = (uint32_t)tmp; - DEBUG("\t0x%08X\n", *data); - data++; - } -} - -/* Execute a single instruction at system speed. */ -static void arm7_op_system(struct target_arm7_s *t, uint32_t op) -{ - uint64_t tmp; - arm7_select_scanchain(t, ARM7_SCANN_DBUS); - tmp = op | (1uLL << 32); - jtag_dev_shift_dr(t->jtag, NULL, (const uint8_t*)&tmp, 33); -} - -static void arm7_halt_request(struct target_s *target) -{ - struct target_arm7_s *t = (struct target_arm7_s *)target; - - arm7_eice_write(t, ARM7_EICE_DEBUG_CTRL, ARM7_EICE_DEBUG_CTRL_DBGRQ); -} - -static int arm7_halt_wait(struct target_s *target) -{ - struct target_arm7_s *t = (struct target_arm7_s *)target; - int stat = arm7_eice_read(t, ARM7_EICE_DEBUG_STAT); - - if(!(stat & ARM7_EICE_DEBUG_STAT_DBGACK)) - return 0; - - /* We are halted, so switch to ARM mode if needed. */ - if(stat & ARM7_EICE_DEBUG_STAT_TBIT) { - /* This sequence switches to ARM mode: - * 6000 STR R0, [R0] ; Save R0 before use - * 4678 MOV R0, PC ; Copy PC into R0 - * 6000 STR R0, [R0] ; Now save the PC in R0 - * 4778 BX PC ; Jump into ARM state - * 46c0 MOV R8, R8 ; NOP - * 46c0 MOV R8, R8 ; NOP - */ - /* FIXME: Switch to ARM mode. */ - } - - /* Fetch core register values */ - /* E880FFFF STM R0, {R0-R15} */ - arm7_op_debug(t, 0xE880FFFF, t->reg_cache, 16); - - return 1; -} - -static void arm7_halt_resume(struct target_s *target, bool step) -{ - struct target_arm7_s *t = (struct target_arm7_s *)target; - - if(step) { - /* FIXME: Set breakpoint on any instruction to single step. */ - } - - /* Restore core registers. */ - /* E890FFFF LDM R0, {R0-R15} */ - arm7_op_debug(t, 0xE890FFFF, t->reg_cache, 16); - - /* Release DBGRQ */ - arm7_eice_write(t, ARM7_EICE_DEBUG_CTRL, 0); - /* This sequence restores PC if no other instructions issued in - * debug mode... - * 0 E1A00000; MOV R0, R0 - * 1 E1A00000; MOV R0, R0 - * 0 EAFFFFFA; B -6 - * FIXME: Add adjustment for other opcodes. - */ - arm7_op_debug(t, ARM7_OP_NOP, NULL, 0); - arm7_op_system(t, ARM7_OP_NOP); - arm7_op_debug(t, 0xEAFFFFF8, NULL, 0); - - jtag_dev_write_ir(t->jtag, ARM7_IR_RESTART); -} - -static bool arm7_attach(struct target_s *target) -{ - int tries = 0; - target_halt_request(target); - while(!target_halt_wait(target) && --tries) - platform_delay(2); - if(!tries) - return false; - return true; -} - -static int arm7_regs_read(struct target_s *target, void *data) -{ - struct target_arm7_s *t = (struct target_arm7_s *)target; - memcpy(data, t->reg_cache, target->regs_size); - return 0; -} - -static int arm7_regs_write(struct target_s *target, const void *data) -{ - struct target_arm7_s *t = (struct target_arm7_s *)target; - memcpy(t->reg_cache, data, target->regs_size); - return 0; -} - diff --git a/src/jtag_scan.c b/src/jtag_scan.c index c4e80cf..f46a148 100644 --- a/src/jtag_scan.c +++ b/src/jtag_scan.c @@ -43,9 +43,6 @@ static struct jtag_dev_descr_s { {.idcode = 0x0BA00477, .idmask = 0x0FFF0FFF, .descr = "ARM Limited: ADIv5 JTAG-DP port.", .handler = adiv5_jtag_dp_handler}, - {.idcode = 0x3F0F0F0F, .idmask = 0xFFFFFFFF, - .descr = "ST Microelectronics: STR730", - .handler = arm7tdmi_jtag_handler}, {.idcode = 0x06410041, .idmask = 0x0FFFFFFF, .descr = "ST Microelectronics: STM32, Medium density."}, {.idcode = 0x06412041, .idmask = 0x0FFFFFFF, -- cgit v1.2.3 From f74def35526fe4a3bbd000e13bef11c00de1c481 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sun, 22 Mar 2015 20:54:45 -0700 Subject: Remove old STM32L1 driver. --- src/Makefile | 1 - src/cortexm.c | 1 - src/stm32l0.c | 7 -- src/stm32l1.c | 229 ---------------------------------------------------------- 4 files changed, 238 deletions(-) delete mode 100644 src/stm32l1.c (limited to 'src') diff --git a/src/Makefile b/src/Makefile index 39c19ac..f76ea74 100644 --- a/src/Makefile +++ b/src/Makefile @@ -43,7 +43,6 @@ SRC = \ stm32f1.c \ stm32f4.c \ stm32l0.c \ - stm32l1.c \ swdptap.c \ target.c \ diff --git a/src/cortexm.c b/src/cortexm.c index 78f78df..4a4b5bf 100644 --- a/src/cortexm.c +++ b/src/cortexm.c @@ -256,7 +256,6 @@ bool cortexm_probe(target *t) PROBE(stm32f1_probe); PROBE(stm32f4_probe); PROBE(stm32l0_probe); /* STM32L0xx & STM32L1xx */ - PROBE(stm32l1_probe); PROBE(lpc11xx_probe); PROBE(lpc43xx_probe); PROBE(sam3x_probe); diff --git a/src/stm32l0.c b/src/stm32l0.c index 28088a8..93c5d94 100644 --- a/src/stm32l0.c +++ b/src/stm32l0.c @@ -112,8 +112,6 @@ */ -#define CONFIG_STM32L1 /* Include support for STM32L1 */ - #include "general.h" #include "adiv5.h" #include "target.h" @@ -190,7 +188,6 @@ static const char stm32l0_xml_memory_map[] = "" " " ""; -#if defined(CONFIG_STM32L1) static const char stm32l1_driver_str[] = "STM32L1xx"; static const char stm32l1_xml_memory_map[] = "" @@ -209,7 +206,6 @@ static const char stm32l1_xml_memory_map[] = "" /* SRAM; ranges from 4KiB to 80KiB(0x14000). */ " " ""; -#endif static const uint16_t stm32l0_nvm_prog_write_stub [] = { #include "../flashstub/stm32l05x-nvm-prog-write.stub" @@ -286,8 +282,6 @@ bool stm32l0_probe(struct target_s* target) { uint32_t idcode; -#if defined(CONFIG_STM32L1) - idcode = target_mem_read32(target, STM32L1_DBGMCU_IDCODE_PHYS) & 0xfff; switch (idcode) { @@ -304,7 +298,6 @@ bool stm32l0_probe(struct target_s* target) target_add_commands(target, stm32lx_cmd_list, "STM32L1x"); return true; } -#endif idcode = target_mem_read32(target, STM32L0_DBGMCU_IDCODE_PHYS) & 0xfff; diff --git a/src/stm32l1.c b/src/stm32l1.c deleted file mode 100644 index 8e63347..0000000 --- a/src/stm32l1.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * This file is part of the Black Magic Debug project. - * - * Copyright (C) 2012 Vegard Storheil Eriksen - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * 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, see . - */ - -/* This file implements STM32L1 target specific functions for detecting - * the device, providing the XML memory map and Flash memory programming. - * - * Refereces: - * ST doc - RM0038 - * Reference manual - STM32L151xx, STM32L152xx and STM32L162xx - * advanced ARM-based 32-bit MCUs - * ST doc - PM0062 - * Programming manual - STM32L151xx, STM32L152xx and STM32L162xx - * Flash and EEPROM programming - */ - -#include "general.h" -#include "adiv5.h" -#include "target.h" -#include "command.h" -#include "gdb_packet.h" - -static int stm32l1_flash_erase(struct target_s *target, uint32_t addr, - size_t len); -static int stm32l1_flash_write(struct target_s *target, uint32_t dest, - const uint8_t *src, size_t len); - -static const char stm32l1_driver_str[] = "STM32L1xx"; - -static const char stm32l1_xml_memory_map[] = "" -/* ""*/ - "" - " " - " 0x100" - " " - " " - ""; - -/* Flash Controller Register Map */ -#define STM32L1_FLASH_BASE 0x40023C00 -#define STM32L1_FLASH_ACR (STM32L1_FLASH_BASE + 0x00) -#define STM32L1_FLASH_PECR (STM32L1_FLASH_BASE + 0x04) -#define STM32L1_FLASH_PDKEYR (STM32L1_FLASH_BASE + 0x08) -#define STM32L1_FLASH_PEKEYR (STM32L1_FLASH_BASE + 0x0C) -#define STM32L1_FLASH_PRGKEYR (STM32L1_FLASH_BASE + 0x10) -#define STM32L1_FLASH_OPTKEYR (STM32L1_FLASH_BASE + 0x14) -#define STM32L1_FLASH_SR (STM32L1_FLASH_BASE + 0x18) -#define STM32L1_FLASH_OBR (STM32L1_FLASH_BASE + 0x1C) -#define STM32L1_FLASH_WRPR1 (STM32L1_FLASH_BASE + 0x20) -#define STM32L1_FLASH_WRPR2 (STM32L1_FLASH_BASE + 0x80) -#define STM32L1_FLASH_WRPR3 (STM32L1_FLASH_BASE + 0x84) - -#define STM32L1_FLASH_PECR_FPRG (1 << 10) -#define STM32L1_FLASH_PECR_ERASE (1 << 9) -#define STM32L1_FLASH_PECR_PROG (1 << 3) - -#define STM32L1_FLASH_SR_BSY (1 << 0) -#define STM32L1_FLASH_SR_EOP (1 << 1) - -#define STM32L1_FLASH_SR_ERROR_MASK (0x1f << 8) - -#define STM32L1_PEKEY1 0x89ABCDEF -#define STM32L1_PEKEY2 0x02030405 -#define STM32L1_PRGKEY1 0x8C9DAEBF -#define STM32L1_PRGKEY2 0x13141516 - -#define STM32L1_DBGMCU_IDCODE 0xE0042000 - -bool stm32l1_probe(struct target_s *target) -{ - uint32_t idcode; - - idcode = target_mem_read32(target, STM32L1_DBGMCU_IDCODE); - switch(idcode & 0xFFF) { - case 0x416: /* CAT. 1 device */ - case 0x429: /* CAT. 2 device */ - case 0x427: /* CAT. 3 device */ - case 0x436: /* CAT. 4 device */ - case 0x437: /* CAT. 5 device */ - target->idcode = idcode & 0xFFF; - target->driver = stm32l1_driver_str; - target->xml_mem_map = stm32l1_xml_memory_map; - target->flash_erase = stm32l1_flash_erase; - target->flash_write = stm32l1_flash_write; - return true; - } - - return false; -} - -static void stm32l1_flash_unlock(target *t) -{ - target_mem_write32(t, STM32L1_FLASH_PEKEYR, STM32L1_PEKEY1); - target_mem_write32(t, STM32L1_FLASH_PEKEYR, STM32L1_PEKEY2); - target_mem_write32(t, STM32L1_FLASH_PRGKEYR, STM32L1_PRGKEY1); - target_mem_write32(t, STM32L1_FLASH_PRGKEYR, STM32L1_PRGKEY2); -} - -static int stm32l1_flash_erase(struct target_s *target, uint32_t addr, size_t len) -{ - uint16_t sr; - - addr &= ~255; - len &= ~255; - - stm32l1_flash_unlock(target); - - /* Flash page erase instruction */ - target_mem_write32(target, STM32L1_FLASH_PECR, STM32L1_FLASH_PECR_ERASE | STM32L1_FLASH_PECR_PROG); - - /* Read FLASH_SR to poll for BSY bit */ - while(target_mem_read32(target, STM32L1_FLASH_SR) & STM32L1_FLASH_SR_BSY) - if(target_check_error(target)) - return -1; - - while(len) { - /* Write first word of page to 0 */ - target_mem_write32(target, addr, 0); - - len -= 256; - addr += 256; - } - - /* Disable programming mode */ - target_mem_write32(target, STM32L1_FLASH_PECR, 0); - - /* Check for error */ - sr = target_mem_read32(target, STM32L1_FLASH_SR); - if ((sr & STM32L1_FLASH_SR_ERROR_MASK) || !(sr & STM32L1_FLASH_SR_EOP)) - return -1; - - return 0; -} - -static int stm32l1_flash_write(struct target_s *target, uint32_t dest, - const uint8_t *src, size_t len) -{ - uint16_t sr; - - /* Handle non word-aligned start */ - if(dest & 3) { - uint32_t data = 0; - uint32_t wlen = 4 - (dest & 3); - if(wlen > len) - wlen = len; - - memcpy((uint8_t *)&data + (dest & 3), src, wlen); - target_mem_write32(target, dest & ~3, data); - src += wlen; - dest += wlen; - len -= wlen; - } - - /* Handle non half-page-aligned start */ - if(dest & 127 && len >= 4) { - uint32_t xlen = 128 - (dest & 127); - if(xlen > len) - xlen = len & ~3; - - target_mem_write(target, dest, src, xlen); - src += xlen; - dest += xlen; - len -= xlen; - } - - /* Write half-pages */ - if(len > 128) { - /* Enable half page mode */ - target_mem_write32(target, STM32L1_FLASH_PECR, STM32L1_FLASH_PECR_FPRG | STM32L1_FLASH_PECR_PROG); - - /* Read FLASH_SR to poll for BSY bit */ - while(target_mem_read32(target, STM32L1_FLASH_SR) & STM32L1_FLASH_SR_BSY) - if(target_check_error(target)) - return -1; - - target_mem_write(target, dest, src, len & ~127); - src += len & ~127; - dest += len & ~127; - len -= len & ~127; - - /* Disable half page mode */ - target_mem_write32(target, STM32L1_FLASH_PECR, 0); - - /* Read FLASH_SR to poll for BSY bit */ - while(target_mem_read32(target, STM32L1_FLASH_SR) & STM32L1_FLASH_SR_BSY) - if(target_check_error(target)) - return -1; - } - - /* Handle non-full page at the end */ - if(len >= 4) { - target_mem_write(target, dest, src, len & ~3); - src += len & ~3; - dest += len & ~3; - len -= len & ~3; - } - - /* Handle non-full word at the end */ - if(len) { - uint32_t data = 0; - - memcpy((uint8_t *)&data, src, len); - target_mem_write32(target, dest, data); - } - - /* Check for error */ - sr = target_mem_read32(target, STM32L1_FLASH_SR); - if ((sr & STM32L1_FLASH_SR_ERROR_MASK) || !(sr & STM32L1_FLASH_SR_EOP)) - return -1; - - return 0; -} -- cgit v1.2.3 From 4313b64bbe27024ab4238bbd18e4b6624a1c8bca Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sun, 22 Mar 2015 22:18:17 -0700 Subject: Add a flash_done target method. --- src/gdb_main.c | 2 +- src/include/target.h | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/gdb_main.c b/src/gdb_main.c index 750dfe2..961a1d9 100644 --- a/src/gdb_main.c +++ b/src/gdb_main.c @@ -424,7 +424,7 @@ handle_v_packet(char *packet, int plen) } else if (!strcmp(packet, "vFlashDone")) { /* Commit flash operations. */ - gdb_putpacketz("OK"); + gdb_putpacketz(target_flash_done(cur_target) ? "EFF" : "OK"); flash_mode = 0; } else { diff --git a/src/include/target.h b/src/include/target.h index 34f26eb..92703b7 100644 --- a/src/include/target.h +++ b/src/include/target.h @@ -107,6 +107,9 @@ target *target_attach(target *t, target_destroy_callback destroy_cb); #define target_flash_write(target, dest, src, len) \ (target)->flash_write((target), (dest), (src), (len)) +#define target_flash_done(target) \ + ((target)->flash_done ? (target)->flash_done(target) : 0) + /* Host I/O */ #define target_hostio_reply(target, recode, errcode) \ (target)->hostio_reply((target), (retcode), (errcode)) @@ -159,6 +162,7 @@ struct target_s { int (*flash_erase)(target *t, uint32_t addr, size_t len); int (*flash_write)(target *t, uint32_t dest, const uint8_t *src, size_t len); + int (*flash_done)(target *t); /* Host I/O support */ void (*hostio_reply)(target *t, int32_t retcode, uint32_t errcode); -- cgit v1.2.3 From 1e54139f4a45d379c1cda7ad02a3f4a7d321b78e Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sat, 28 Mar 2015 20:15:33 -0700 Subject: target: Remove pc_read/pc_write methods. --- src/cortexm.c | 5 +---- src/include/cortexm.h | 1 + src/include/target.h | 9 --------- src/lmi.c | 3 ++- src/nrf51.c | 3 ++- src/stm32l0.c | 5 +++-- 6 files changed, 9 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/cortexm.c b/src/cortexm.c index 4a4b5bf..0a9785f 100644 --- a/src/cortexm.c +++ b/src/cortexm.c @@ -62,7 +62,6 @@ const struct command_s cortexm_cmd_list[] = { static int cortexm_regs_read(target *t, void *data); static int cortexm_regs_write(target *t, const void *data); -static int cortexm_pc_write(target *t, const uint32_t val); static uint32_t cortexm_pc_read(target *t); static void cortexm_reset(target *t); @@ -218,8 +217,6 @@ bool cortexm_probe(target *t) t->tdesc = tdesc_cortex_m; t->regs_read = cortexm_regs_read; t->regs_write = cortexm_regs_write; - t->pc_write = cortexm_pc_write; - t->pc_read = cortexm_pc_read; t->reset = cortexm_reset; t->halt_request = cortexm_halt_request; @@ -428,7 +425,7 @@ static uint32_t cortexm_pc_read(target *t) return 0; } -static int cortexm_pc_write(target *t, const uint32_t val) +int cortexm_pc_write(target *t, const uint32_t val) { target_mem_write32(t, CORTEXM_DCRDR, val); target_mem_write32(t, CORTEXM_DCRSR, CORTEXM_DCRSR_REGWnR | 0x0F); diff --git a/src/include/cortexm.h b/src/include/cortexm.h index 8f4d45d..9c906a1 100644 --- a/src/include/cortexm.h +++ b/src/include/cortexm.h @@ -149,6 +149,7 @@ void cortexm_halt_resume(struct target_s *target, bool step); int cortexm_run_stub(struct target_s *target, uint32_t loadaddr, const uint16_t *stub, uint32_t stublen, uint32_t r0, uint32_t r1, uint32_t r2, uint32_t r3); +int cortexm_pc_write(target *t, const uint32_t val); #endif diff --git a/src/include/target.h b/src/include/target.h index 92703b7..48e81f2 100644 --- a/src/include/target.h +++ b/src/include/target.h @@ -61,12 +61,6 @@ target *target_attach(target *t, target_destroy_callback destroy_cb); #define target_regs_write(target, data) \ (target)->regs_write((target), (data)) -#define target_pc_read(target) \ - (target)->pc_read((target)) - -#define target_pc_write(target, val) \ - (target)->pc_write((target), (val)) - /* Halt/resume functions */ #define target_reset(target) \ @@ -135,9 +129,6 @@ struct target_s { int (*regs_read)(target *t, void *data); int (*regs_write)(target *t, const void *data); - uint32_t (*pc_read)(target *t); - int (*pc_write)(target *t, const uint32_t val); - /* Halt/resume functions */ void (*reset)(target *t); void (*halt_request)(target *t); diff --git a/src/lmi.c b/src/lmi.c index d9aa613..f9fd225 100644 --- a/src/lmi.c +++ b/src/lmi.c @@ -30,6 +30,7 @@ #include "general.h" #include "adiv5.h" #include "target.h" +#include "cortexm.h" static int lmi_flash_erase(struct target_s *target, uint32_t addr, size_t len); static int lmi_flash_write(struct target_s *target, uint32_t dest, @@ -163,7 +164,7 @@ int lmi_flash_write(struct target_s *target, uint32_t dest, DEBUG("Sending data\n"); target_mem_write(target, 0x20000030, data, len + 8); DEBUG("Running stub\n"); - target_pc_write(target, 0x20000000); + cortexm_pc_write(target, 0x20000000); target_halt_resume(target, 0); DEBUG("Waiting for halt\n"); while(!target_halt_wait(target)); diff --git a/src/nrf51.c b/src/nrf51.c index ed0137c..a75b356 100644 --- a/src/nrf51.c +++ b/src/nrf51.c @@ -26,6 +26,7 @@ #include "target.h" #include "command.h" #include "gdb_packet.h" +#include "cortexm.h" static int nrf51_flash_erase(struct target_s *target, uint32_t addr, size_t len); static int nrf51_flash_write(struct target_s *target, uint32_t dest, @@ -229,7 +230,7 @@ static int nrf51_flash_write(struct target_s *target, uint32_t dest, /* Write stub and data to target ram and set PC */ target_mem_write(target, 0x20000000, nrf51_flash_write_stub, 0x28); target_mem_write(target, 0x20000028, data, len + 8); - target_pc_write(target, 0x20000000); + cortexm_pc_write(target, 0x20000000); if(target_check_error(target)) return -1; diff --git a/src/stm32l0.c b/src/stm32l0.c index 93c5d94..6d02ad2 100644 --- a/src/stm32l0.c +++ b/src/stm32l0.c @@ -117,6 +117,7 @@ #include "target.h" #include "command.h" #include "gdb_packet.h" +#include "cortexm.h" #include "stm32lx-nvm.h" @@ -386,7 +387,7 @@ static int stm32lx_nvm_prog_erase_stubbed(struct target_s* target, &info, sizeof(info)); /* Execute stub */ - target_pc_write(target, STM32Lx_STUB_PHYS); + cortexm_pc_write(target, STM32Lx_STUB_PHYS); if (target_check_error(target)) return -1; target_halt_resume(target, 0); @@ -462,7 +463,7 @@ static int stm32lx_nvm_prog_write_stubbed(struct target_s* target, &info, sizeof(info)); /* Execute stub */ - target_pc_write(target, STM32Lx_STUB_PHYS); + cortexm_pc_write(target, STM32Lx_STUB_PHYS); if (target_check_error(target)) return -1; target_halt_resume(target, 0); -- cgit v1.2.3 From 9f271d5cd7c51251ec5e90a986f6f70a3fff75d8 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sat, 28 Mar 2015 20:47:17 -0700 Subject: Consistently use 'target *t' for target var. --- src/adiv5.c | 20 ++-- src/crc32.c | 10 +- src/include/cortexm.h | 8 +- src/include/crc32.h | 2 +- src/kinetis.c | 12 +-- src/lmi.c | 41 ++++---- src/lpc11xx.c | 78 +++++++------- src/lpc43xx.c | 135 ++++++++++++------------- src/nrf51.c | 64 ++++++------ src/sam3x.c | 104 +++++++++---------- src/samd.c | 119 +++++++++++----------- src/stm32f1.c | 98 +++++++++--------- src/stm32f4.c | 38 +++---- src/stm32l0.c | 275 +++++++++++++++++++++++--------------------------- 14 files changed, 488 insertions(+), 516 deletions(-) (limited to 'src') diff --git a/src/adiv5.c b/src/adiv5.c index 88aac31..039f129 100644 --- a/src/adiv5.c +++ b/src/adiv5.c @@ -37,12 +37,10 @@ static const char adiv5_driver_str[] = "ARM ADIv5 MEM-AP"; -static int ap_check_error(struct target_s *target); +static int ap_check_error(target *t); -static void ap_mem_read(struct target_s *target, void *dest, uint32_t src, - size_t len); -static void ap_mem_write(struct target_s *target, uint32_t dest, - const void *src, size_t len); +static void ap_mem_read(target *t, void *dest, uint32_t src, size_t len); +static void ap_mem_write(target *t, uint32_t dest, const void *src, size_t len); void adiv5_dp_ref(ADIv5_DP_t *dp) { @@ -160,9 +158,9 @@ void adiv5_dp_init(ADIv5_DP_t *dp) } static int -ap_check_error(struct target_s *target) +ap_check_error(target *t) { - ADIv5_AP_t *ap = adiv5_target_ap(target); + ADIv5_AP_t *ap = adiv5_target_ap(t); return adiv5_dp_error(ap->dp); } @@ -212,9 +210,9 @@ static void * extract(void *dest, uint32_t src, uint32_t val, enum align align) } static void -ap_mem_read(struct target_s *target, void *dest, uint32_t src, size_t len) +ap_mem_read(target *t, void *dest, uint32_t src, size_t len) { - ADIv5_AP_t *ap = adiv5_target_ap(target); + ADIv5_AP_t *ap = adiv5_target_ap(t); uint32_t tmp; uint32_t osrc = src; enum align align = MIN(ALIGNOF(src), ALIGNOF(len)); @@ -241,9 +239,9 @@ ap_mem_read(struct target_s *target, void *dest, uint32_t src, size_t len) } static void -ap_mem_write(struct target_s *target, uint32_t dest, const void *src, size_t len) +ap_mem_write(target *t, uint32_t dest, const void *src, size_t len) { - ADIv5_AP_t *ap = adiv5_target_ap(target); + ADIv5_AP_t *ap = adiv5_target_ap(t); uint32_t odest = dest; enum align align = MIN(ALIGNOF(dest), ALIGNOF(len)); diff --git a/src/crc32.c b/src/crc32.c index e8a046d..6f1c0e3 100644 --- a/src/crc32.c +++ b/src/crc32.c @@ -94,13 +94,13 @@ uint32_t crc32_calc(uint32_t crc, uint8_t data) return (crc << 8) ^ crc32_table[((crc >> 24) ^ data) & 255]; } -uint32_t generic_crc32(struct target_s *target, uint32_t base, int len) +uint32_t generic_crc32(target *t, uint32_t base, int len) { uint32_t crc = -1; uint8_t byte; while (len--) { - byte = target_mem_read8(target, base); + byte = target_mem_read8(t, base); crc = crc32_calc(crc, byte); base++; @@ -109,7 +109,7 @@ uint32_t generic_crc32(struct target_s *target, uint32_t base, int len) } #else #include -uint32_t generic_crc32(struct target_s *target, uint32_t base, int len) +uint32_t generic_crc32(target *t, uint32_t base, int len) { uint32_t data; uint32_t crc; @@ -118,7 +118,7 @@ uint32_t generic_crc32(struct target_s *target, uint32_t base, int len) CRC_CR |= CRC_CR_RESET; while (len > 3) { - data = target_mem_read32(target, base); + data = target_mem_read32(t, base); CRC_DR = __builtin_bswap32(data); base += 4; @@ -128,7 +128,7 @@ uint32_t generic_crc32(struct target_s *target, uint32_t base, int len) crc = CRC_DR; while (len--) { - data = target_mem_read8(target, base++); + data = target_mem_read8(t, base++); crc ^= data << 24; for (i = 0; i < 8; i++) { diff --git a/src/include/cortexm.h b/src/include/cortexm.h index 9c906a1..24e4c4d 100644 --- a/src/include/cortexm.h +++ b/src/include/cortexm.h @@ -143,10 +143,10 @@ #define CORTEXM_DWT_FUNC_FUNC_WRITE (6 << 0) #define CORTEXM_DWT_FUNC_FUNC_ACCESS (7 << 0) -bool cortexm_attach(struct target_s *target); -void cortexm_detach(struct target_s *target); -void cortexm_halt_resume(struct target_s *target, bool step); -int cortexm_run_stub(struct target_s *target, uint32_t loadaddr, +bool cortexm_attach(target *t); +void cortexm_detach(target *t); +void cortexm_halt_resume(target *t, bool step); +int cortexm_run_stub(target *t, uint32_t loadaddr, const uint16_t *stub, uint32_t stublen, uint32_t r0, uint32_t r1, uint32_t r2, uint32_t r3); int cortexm_pc_write(target *t, const uint32_t val); diff --git a/src/include/crc32.h b/src/include/crc32.h index 9966d8d..bd8d5c4 100644 --- a/src/include/crc32.h +++ b/src/include/crc32.h @@ -22,6 +22,6 @@ #define __CRC32_H uint32_t crc32_calc(uint32_t crc, uint8_t data); -uint32_t generic_crc32(struct target_s *target, uint32_t base, int len); +uint32_t generic_crc32(target *t, uint32_t base, int len); #endif diff --git a/src/kinetis.c b/src/kinetis.c index 9f27d9b..7ccb28d 100644 --- a/src/kinetis.c +++ b/src/kinetis.c @@ -54,8 +54,8 @@ #define KL25_PAGESIZE 0x400 -static int kl25_flash_erase(struct target_s *target, uint32_t addr, size_t len); -static int kl25_flash_write(struct target_s *target, uint32_t dest, +static int kl25_flash_erase(target *t, uint32_t addr, size_t len); +static int kl25_flash_write(target *t, uint32_t dest, const uint8_t *src, size_t len); static const char kl25_xml_memory_map[] = "" @@ -70,7 +70,7 @@ static const char kl25_xml_memory_map[] = "" " " ""; -bool kinetis_probe(struct target_s *t) +bool kinetis_probe(target *t) { uint32_t sdid = target_mem_read32(t, SIM_SDID); switch (sdid >> 20) { @@ -85,7 +85,7 @@ bool kinetis_probe(struct target_s *t) } static bool -kl25_command(struct target_s *t, uint8_t cmd, uint32_t addr, const uint8_t data[8]) +kl25_command(target *t, uint8_t cmd, uint32_t addr, const uint8_t data[8]) { uint8_t fstat; @@ -120,7 +120,7 @@ kl25_command(struct target_s *t, uint8_t cmd, uint32_t addr, const uint8_t data[ return true; } -static int kl25_flash_erase(struct target_s *t, uint32_t addr, size_t len) +static int kl25_flash_erase(target *t, uint32_t addr, size_t len) { addr &= ~(KL25_PAGESIZE - 1); len = (len + KL25_PAGESIZE - 1) & ~(KL25_PAGESIZE - 1); @@ -133,7 +133,7 @@ static int kl25_flash_erase(struct target_s *t, uint32_t addr, size_t len) return 0; } -static int kl25_flash_write(struct target_s *t, uint32_t dest, +static int kl25_flash_write(target *t, uint32_t dest, const uint8_t *src, size_t len) { /* FIXME handle misaligned start and end of sections */ diff --git a/src/lmi.c b/src/lmi.c index f9fd225..803a19e 100644 --- a/src/lmi.c +++ b/src/lmi.c @@ -32,8 +32,8 @@ #include "target.h" #include "cortexm.h" -static int lmi_flash_erase(struct target_s *target, uint32_t addr, size_t len); -static int lmi_flash_write(struct target_s *target, uint32_t dest, +static int lmi_flash_erase(target *t, uint32_t addr, size_t len); +static int lmi_flash_write(target *t, uint32_t dest, const uint8_t *src, size_t len); static const char lmi_driver_str[] = "TI Stellaris/Tiva"; @@ -99,30 +99,30 @@ static const uint16_t lmi_flash_write_stub[] = { // ... }; -bool lmi_probe(struct target_s *target) +bool lmi_probe(target *t) { - uint32_t did1 = target_mem_read32(target, 0x400FE004); + uint32_t did1 = target_mem_read32(t, 0x400FE004); switch (did1 >> 16) { case 0x1049: /* LM3S3748 */ - target->driver = lmi_driver_str; - target->xml_mem_map = lmi_xml_memory_map; - target->flash_erase = lmi_flash_erase; - target->flash_write = lmi_flash_write; + t->driver = lmi_driver_str; + t->xml_mem_map = lmi_xml_memory_map; + t->flash_erase = lmi_flash_erase; + t->flash_write = lmi_flash_write; return true; case 0x10A1: /* TM4C123GH6PM */ - target->driver = lmi_driver_str; - target->xml_mem_map = tm4c123gh6pm_xml_memory_map; - target->flash_erase = lmi_flash_erase; - target->flash_write = lmi_flash_write; + t->driver = lmi_driver_str; + t->xml_mem_map = tm4c123gh6pm_xml_memory_map; + t->flash_erase = lmi_flash_erase; + t->flash_write = lmi_flash_write; return true; } return false; } -int lmi_flash_erase(struct target_s *target, uint32_t addr, size_t len) +int lmi_flash_erase(target *t, uint32_t addr, size_t len) { - ADIv5_AP_t *ap = adiv5_target_ap(target); + ADIv5_AP_t *ap = adiv5_target_ap(t); uint32_t tmp; addr &= 0xFFFFFC00; @@ -152,22 +152,21 @@ int lmi_flash_erase(struct target_s *target, uint32_t addr, size_t len) return 0; } -int lmi_flash_write(struct target_s *target, uint32_t dest, - const uint8_t *src, size_t len) +int lmi_flash_write(target *t, uint32_t dest, const uint8_t *src, size_t len) { uint32_t data[(len>>2)+2]; data[0] = dest; data[1] = len >> 2; memcpy(&data[2], src, len); DEBUG("Sending stub\n"); - target_mem_write(target, 0x20000000, (void*)lmi_flash_write_stub, 0x30); + target_mem_write(t, 0x20000000, (void*)lmi_flash_write_stub, 0x30); DEBUG("Sending data\n"); - target_mem_write(target, 0x20000030, data, len + 8); + target_mem_write(t, 0x20000030, data, len + 8); DEBUG("Running stub\n"); - cortexm_pc_write(target, 0x20000000); - target_halt_resume(target, 0); + cortexm_pc_write(t, 0x20000000); + target_halt_resume(t, 0); DEBUG("Waiting for halt\n"); - while(!target_halt_wait(target)); + while(!target_halt_wait(t)); return 0; } diff --git a/src/lpc11xx.c b/src/lpc11xx.c index 6224464..3a85ded 100644 --- a/src/lpc11xx.c +++ b/src/lpc11xx.c @@ -61,10 +61,10 @@ static struct flash_program flash_pgm; static const char lpc8xx_driver[] = "lpc8xx"; static const char lpc11xx_driver[] = "lpc11xx"; -static void lpc11x_iap_call(struct target_s *target, struct flash_param *param, unsigned param_len); -static int lpc11xx_flash_prepare(struct target_s *target, uint32_t addr, int len); -static int lpc11xx_flash_erase(struct target_s *target, uint32_t addr, size_t len); -static int lpc11xx_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, +static void lpc11x_iap_call(target *t, struct flash_param *param, unsigned param_len); +static int lpc11xx_flash_prepare(target *t, uint32_t addr, int len); +static int lpc11xx_flash_erase(target *t, uint32_t addr, size_t len); +static int lpc11xx_flash_write(target *t, uint32_t dest, const uint8_t *src, size_t len); /* @@ -103,12 +103,12 @@ static const char lpc8xx_xml_memory_map[] = "" ""; bool -lpc11xx_probe(struct target_s *target) +lpc11xx_probe(target *t) { uint32_t idcode; /* read the device ID register */ - idcode = target_mem_read32(target, 0x400483F4); + idcode = target_mem_read32(t, 0x400483F4); switch (idcode) { @@ -143,18 +143,18 @@ lpc11xx_probe(struct target_s *target) case 0x2972402B: /* lpc11u23/301 */ case 0x2988402B: /* lpc11u24x/301 */ case 0x2980002B: /* lpc11u24x/401 */ - target->driver = lpc11xx_driver; - target->xml_mem_map = lpc11xx_xml_memory_map; - target->flash_erase = lpc11xx_flash_erase; - target->flash_write = lpc11xx_flash_write; + t->driver = lpc11xx_driver; + t->xml_mem_map = lpc11xx_xml_memory_map; + t->flash_erase = lpc11xx_flash_erase; + t->flash_write = lpc11xx_flash_write; return true; case 0x1812202b: /* LPC812M101FDH20 */ - target->driver = lpc8xx_driver; - target->xml_mem_map = lpc8xx_xml_memory_map; - target->flash_erase = lpc11xx_flash_erase; - target->flash_write = lpc11xx_flash_write; + t->driver = lpc8xx_driver; + t->xml_mem_map = lpc8xx_xml_memory_map; + t->flash_erase = lpc11xx_flash_erase; + t->flash_write = lpc11xx_flash_write; return true; } @@ -163,55 +163,55 @@ lpc11xx_probe(struct target_s *target) } static void -lpc11x_iap_call(struct target_s *target, struct flash_param *param, unsigned param_len) +lpc11x_iap_call(target *t, struct flash_param *param, unsigned param_len) { - uint32_t regs[target->regs_size / sizeof(uint32_t)]; + uint32_t regs[t->regs_size / sizeof(uint32_t)]; /* fill out the remainder of the parameters and copy the structure to RAM */ param->opcodes[0] = 0xbe00; param->opcodes[1] = 0x0000; - target_mem_write(target, IAP_RAM_BASE, param, param_len); + target_mem_write(t, IAP_RAM_BASE, param, param_len); /* set up for the call to the IAP ROM */ - target_regs_read(target, regs); + target_regs_read(t, regs); regs[0] = IAP_RAM_BASE + offsetof(struct flash_param, command); regs[1] = IAP_RAM_BASE + offsetof(struct flash_param, result); // stack pointer - top of the smallest ram less 32 for IAP usage - if (target->driver == lpc8xx_driver) + if (t->driver == lpc8xx_driver) regs[MSP] = IAP_RAM_BASE + MIN_RAM_SIZE_FOR_LPC8xx - RAM_USAGE_FOR_IAP_ROUTINES; else regs[MSP] = IAP_RAM_BASE + MIN_RAM_SIZE_FOR_LPC1xxx - RAM_USAGE_FOR_IAP_ROUTINES; regs[14] = IAP_RAM_BASE | 1; regs[15] = IAP_ENTRYPOINT; - target_regs_write(target, regs); + target_regs_write(t, regs); /* start the target and wait for it to halt again */ - target_halt_resume(target, 0); - while (!target_halt_wait(target)); + target_halt_resume(t, 0); + while (!target_halt_wait(t)); /* copy back just the parameters structure */ - target_mem_read(target, param, IAP_RAM_BASE, sizeof(struct flash_param)); + target_mem_read(t, param, IAP_RAM_BASE, sizeof(struct flash_param)); } -static int flash_page_size(struct target_s *target) +static int flash_page_size(target *t) { - if (target->driver == lpc8xx_driver) + if (t->driver == lpc8xx_driver) return 1024; else return 4096; } static int -lpc11xx_flash_prepare(struct target_s *target, uint32_t addr, int len) +lpc11xx_flash_prepare(target *t, uint32_t addr, int len) { /* prepare the sector(s) to be erased */ memset(&flash_pgm.p, 0, sizeof(flash_pgm.p)); flash_pgm.p.command[0] = IAP_CMD_PREPARE; - flash_pgm.p.command[1] = addr / flash_page_size(target); - flash_pgm.p.command[2] = (addr + len - 1) / flash_page_size(target); + flash_pgm.p.command[1] = addr / flash_page_size(t); + flash_pgm.p.command[2] = (addr + len - 1) / flash_page_size(t); - lpc11x_iap_call(target, &flash_pgm.p, sizeof(flash_pgm.p)); + lpc11x_iap_call(t, &flash_pgm.p, sizeof(flash_pgm.p)); if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { return -1; } @@ -220,27 +220,27 @@ lpc11xx_flash_prepare(struct target_s *target, uint32_t addr, int len) } static int -lpc11xx_flash_erase(struct target_s *target, uint32_t addr, size_t len) +lpc11xx_flash_erase(target *t, uint32_t addr, size_t len) { - if (addr % flash_page_size(target)) + if (addr % flash_page_size(t)) return -1; /* prepare... */ - if (lpc11xx_flash_prepare(target, addr, len)) + if (lpc11xx_flash_prepare(t, addr, len)) return -1; /* and now erase them */ flash_pgm.p.command[0] = IAP_CMD_ERASE; - flash_pgm.p.command[1] = addr / flash_page_size(target); - flash_pgm.p.command[2] = (addr + len - 1) / flash_page_size(target); + flash_pgm.p.command[1] = addr / flash_page_size(t); + flash_pgm.p.command[2] = (addr + len - 1) / flash_page_size(t); flash_pgm.p.command[3] = 12000; /* XXX safe to assume this? */ - lpc11x_iap_call(target, &flash_pgm.p, sizeof(flash_pgm.p)); + lpc11x_iap_call(t, &flash_pgm.p, sizeof(flash_pgm.p)); if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { return -1; } flash_pgm.p.command[0] = IAP_CMD_BLANKCHECK; - lpc11x_iap_call(target, &flash_pgm.p, sizeof(flash_pgm.p)); + lpc11x_iap_call(t, &flash_pgm.p, sizeof(flash_pgm.p)); if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { return -1; } @@ -249,7 +249,7 @@ lpc11xx_flash_erase(struct target_s *target, uint32_t addr, size_t len) } static int -lpc11xx_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, size_t len) +lpc11xx_flash_write(target *t, uint32_t dest, const uint8_t *src, size_t len) { unsigned first_chunk = dest / IAP_PGM_CHUNKSIZE; unsigned last_chunk = (dest + len - 1) / IAP_PGM_CHUNKSIZE; @@ -300,7 +300,7 @@ lpc11xx_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, } /* prepare... */ - if (lpc11xx_flash_prepare(target, chunk * IAP_PGM_CHUNKSIZE, IAP_PGM_CHUNKSIZE)) + if (lpc11xx_flash_prepare(t, chunk * IAP_PGM_CHUNKSIZE, IAP_PGM_CHUNKSIZE)) return -1; /* set the destination address and program */ @@ -310,7 +310,7 @@ lpc11xx_flash_write(struct target_s *target, uint32_t dest, const uint8_t *src, flash_pgm.p.command[3] = IAP_PGM_CHUNKSIZE; /* assuming we are running off IRC - safe lower bound */ flash_pgm.p.command[4] = 12000; /* XXX safe to presume this? */ - lpc11x_iap_call(target, &flash_pgm.p, sizeof(flash_pgm)); + lpc11x_iap_call(t, &flash_pgm.p, sizeof(flash_pgm)); if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { return -1; } diff --git a/src/lpc43xx.c b/src/lpc43xx.c index 29e202a..1519306 100644 --- a/src/lpc43xx.c +++ b/src/lpc43xx.c @@ -119,20 +119,20 @@ struct flash_program { uint8_t data[IAP_PGM_CHUNKSIZE]; }; -static bool lpc43xx_cmd_erase(target *target, int argc, const char *argv[]); -static bool lpc43xx_cmd_reset(target *target, int argc, const char *argv[]); -static bool lpc43xx_cmd_mkboot(target *target, int argc, const char *argv[]); -static int lpc43xx_flash_init(struct target_s *target); -static void lpc43xx_iap_call(struct target_s *target, struct flash_param *param, +static bool lpc43xx_cmd_erase(target *t, int argc, const char *argv[]); +static bool lpc43xx_cmd_reset(target *t, int argc, const char *argv[]); +static bool lpc43xx_cmd_mkboot(target *t, int argc, const char *argv[]); +static int lpc43xx_flash_init(target *t); +static void lpc43xx_iap_call(target *t, struct flash_param *param, unsigned param_len); -static int lpc43xx_flash_prepare(struct target_s *target, +static int lpc43xx_flash_prepare(target *t, uint32_t addr, int len); -static int lpc43xx_flash_erase(struct target_s *target, uint32_t addr, size_t len); -static int lpc43xx_flash_write(struct target_s *target, +static int lpc43xx_flash_erase(target *t, uint32_t addr, size_t len); +static int lpc43xx_flash_write(target *t, uint32_t dest, const uint8_t *src, size_t len); -static void lpc43xx_set_internal_clock(struct target_s *target); -static void lpc43xx_wdt_set_period(struct target_s *target); -static void lpc43xx_wdt_pet(struct target_s *target); +static void lpc43xx_set_internal_clock(target *t); +static void lpc43xx_wdt_set_period(target *t); +static void lpc43xx_wdt_pet(target *t); const struct command_s lpc43xx_cmd_list[] = { {"erase_mass", lpc43xx_cmd_erase, "Erase entire flash memory"}, @@ -166,45 +166,45 @@ static const char lpc4337_xml_memory_map[] = "" " " ""; -bool lpc43xx_probe(struct target_s *target) +bool lpc43xx_probe(target *t) { uint32_t chipid, cpuid; - chipid = target_mem_read32(target, LPC43XX_CHIPID); - cpuid = target_mem_read32(target, ARM_CPUID); + chipid = target_mem_read32(t, LPC43XX_CHIPID); + cpuid = target_mem_read32(t, ARM_CPUID); switch(chipid) { case 0x4906002B: /* Parts with on-chip flash */ switch (cpuid & 0xFF00FFF0) { case 0x4100C240: - target->driver = "LPC43xx Cortex-M4"; + t->driver = "LPC43xx Cortex-M4"; if (cpuid == 0x410FC241) { /* LPC4337 */ - target->xml_mem_map = lpc4337_xml_memory_map; - target->flash_erase = lpc43xx_flash_erase; - target->flash_write = lpc43xx_flash_write; - target_add_commands(target, lpc43xx_cmd_list, "LPC43xx"); + t->xml_mem_map = lpc4337_xml_memory_map; + t->flash_erase = lpc43xx_flash_erase; + t->flash_write = lpc43xx_flash_write; + target_add_commands(t, lpc43xx_cmd_list, "LPC43xx"); } break; case 0x4100C200: - target->driver = "LPC43xx Cortex-M0"; + t->driver = "LPC43xx Cortex-M0"; break; default: - target->driver = "LPC43xx "; + t->driver = "LPC43xx "; } return true; case 0x5906002B: /* Flashless parts */ case 0x6906002B: switch (cpuid & 0xFF00FFF0) { case 0x4100C240: - target->driver = "LPC43xx Cortex-M4"; + t->driver = "LPC43xx Cortex-M4"; break; case 0x4100C200: - target->driver = "LPC43xx Cortex-M0"; + t->driver = "LPC43xx Cortex-M0"; break; default: - target->driver = "LPC43xx "; + t->driver = "LPC43xx "; } return true; } @@ -213,7 +213,7 @@ bool lpc43xx_probe(struct target_s *target) } /* Reset all major systems _except_ debug */ -static bool lpc43xx_cmd_reset(target *target, int argc, const char *argv[]) +static bool lpc43xx_cmd_reset(target *t, int argc, const char *argv[]) { (void)argc; (void)argv; @@ -224,12 +224,12 @@ static bool lpc43xx_cmd_reset(target *target, int argc, const char *argv[]) static const uint32_t reset_val = 0x05FA0004; /* System reset on target */ - target_mem_write(target, AIRCR, &reset_val, sizeof(reset_val)); + target_mem_write(t, AIRCR, &reset_val, sizeof(reset_val)); return true; } -static bool lpc43xx_cmd_erase(target *target, int argc, const char *argv[]) +static bool lpc43xx_cmd_erase(target *t, int argc, const char *argv[]) { (void)argc; (void)argv; @@ -237,7 +237,7 @@ static bool lpc43xx_cmd_erase(target *target, int argc, const char *argv[]) uint32_t bank = 0; struct flash_program flash_pgm; - lpc43xx_flash_init(target); + lpc43xx_flash_init(t); for (bank = 0; bank < FLASH_NUM_BANK; bank++) { @@ -246,7 +246,7 @@ static bool lpc43xx_cmd_erase(target *target, int argc, const char *argv[]) flash_pgm.p.params.prepare.end_sector = FLASH_NUM_SECTOR-1; flash_pgm.p.params.prepare.flash_bank = bank; flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS; - lpc43xx_iap_call(target, &flash_pgm.p, sizeof(flash_pgm.p)); + lpc43xx_iap_call(t, &flash_pgm.p, sizeof(flash_pgm.p)); if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { return false; } @@ -257,7 +257,7 @@ static bool lpc43xx_cmd_erase(target *target, int argc, const char *argv[]) flash_pgm.p.params.erase.cpu_clk_khz = CPU_CLK_KHZ; flash_pgm.p.params.erase.flash_bank = bank; flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS; - lpc43xx_iap_call(target, &flash_pgm.p, sizeof(flash_pgm.p)); + lpc43xx_iap_call(t, &flash_pgm.p, sizeof(flash_pgm.p)); if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { return false; @@ -269,20 +269,20 @@ static bool lpc43xx_cmd_erase(target *target, int argc, const char *argv[]) return true; } -static int lpc43xx_flash_init(struct target_s *target) +static int lpc43xx_flash_init(target *t) { /* Deal with WDT */ - lpc43xx_wdt_set_period(target); + lpc43xx_wdt_set_period(t); /* Force internal clock */ - lpc43xx_set_internal_clock(target); + lpc43xx_set_internal_clock(t); struct flash_program flash_pgm; /* Initialize flash IAP */ flash_pgm.p.command = IAP_CMD_INIT; flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS; - lpc43xx_iap_call(target, &flash_pgm.p, sizeof(flash_pgm.p)); + lpc43xx_iap_call(t, &flash_pgm.p, sizeof(flash_pgm.p)); if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) return -1; @@ -332,40 +332,40 @@ static int32_t sector_number(uint32_t addr) } } -static void lpc43xx_iap_call(struct target_s *target, struct flash_param *param, unsigned param_len) +static void lpc43xx_iap_call(target *t, struct flash_param *param, unsigned param_len) { - uint32_t regs[target->regs_size / sizeof(uint32_t)]; + uint32_t regs[t->regs_size / sizeof(uint32_t)]; uint32_t iap_entry; /* Pet WDT before each IAP call, if it is on */ - lpc43xx_wdt_pet(target); + lpc43xx_wdt_pet(t); - target_mem_read(target, &iap_entry, IAP_ENTRYPOINT_LOCATION, sizeof(iap_entry)); + target_mem_read(t, &iap_entry, IAP_ENTRYPOINT_LOCATION, sizeof(iap_entry)); /* fill out the remainder of the parameters and copy the structure to RAM */ param->opcode = ARM_THUMB_BREAKPOINT; /* breakpoint */ param->pad0 = 0x0000; /* pad */ - target_mem_write(target, IAP_RAM_BASE, param, param_len); + target_mem_write(t, IAP_RAM_BASE, param, param_len); /* set up for the call to the IAP ROM */ - target_regs_read(target, regs); + target_regs_read(t, regs); regs[0] = IAP_RAM_BASE + offsetof(struct flash_param, command); regs[1] = IAP_RAM_BASE + offsetof(struct flash_param, result); regs[R_MSP] = IAP_RAM_BASE + IAP_RAM_SIZE; regs[R_LR] = IAP_RAM_BASE | 1; regs[R_PC] = iap_entry; - target_regs_write(target, regs); + target_regs_write(t, regs); /* start the target and wait for it to halt again */ - target_halt_resume(target, 0); - while (!target_halt_wait(target)); + target_halt_resume(t, 0); + while (!target_halt_wait(t)); /* copy back just the parameters structure */ - target_mem_read(target, param, IAP_RAM_BASE, sizeof(struct flash_param)); + target_mem_read(t, param, IAP_RAM_BASE, sizeof(struct flash_param)); } -static int lpc43xx_flash_prepare(struct target_s *target, uint32_t addr, int len) +static int lpc43xx_flash_prepare(target *t, uint32_t addr, int len) { struct flash_program flash_pgm; @@ -376,7 +376,7 @@ static int lpc43xx_flash_prepare(struct target_s *target, uint32_t addr, int len flash_pgm.p.params.prepare.flash_bank = flash_bank(addr); flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS; - lpc43xx_iap_call(target, &flash_pgm.p, sizeof(flash_pgm.p)); + lpc43xx_iap_call(t, &flash_pgm.p, sizeof(flash_pgm.p)); if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { return -1; } @@ -384,7 +384,7 @@ static int lpc43xx_flash_prepare(struct target_s *target, uint32_t addr, int len return 0; } -static int lpc43xx_flash_erase(struct target_s *target, uint32_t addr, size_t len) +static int lpc43xx_flash_erase(target *t, uint32_t addr, size_t len) { struct flash_program flash_pgm; @@ -393,11 +393,11 @@ static int lpc43xx_flash_erase(struct target_s *target, uint32_t addr, size_t le return -1; /* init */ - if (lpc43xx_flash_init(target)) + if (lpc43xx_flash_init(t)) return -1; /* prepare... */ - if (lpc43xx_flash_prepare(target, addr, len)) + if (lpc43xx_flash_prepare(t, addr, len)) return -1; /* and now erase them */ @@ -407,7 +407,7 @@ static int lpc43xx_flash_erase(struct target_s *target, uint32_t addr, size_t le flash_pgm.p.params.erase.cpu_clk_khz = CPU_CLK_KHZ; flash_pgm.p.params.erase.flash_bank = flash_bank(addr); flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS; - lpc43xx_iap_call(target, &flash_pgm.p, sizeof(flash_pgm.p)); + lpc43xx_iap_call(t, &flash_pgm.p, sizeof(flash_pgm.p)); if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { return -1; } @@ -418,7 +418,7 @@ static int lpc43xx_flash_erase(struct target_s *target, uint32_t addr, size_t le flash_pgm.p.params.blank_check.end_sector = sector_number(addr+len); flash_pgm.p.params.blank_check.flash_bank = flash_bank(addr); flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS; - lpc43xx_iap_call(target, &flash_pgm.p, sizeof(flash_pgm.p)); + lpc43xx_iap_call(t, &flash_pgm.p, sizeof(flash_pgm.p)); if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { return -1; } @@ -426,13 +426,13 @@ static int lpc43xx_flash_erase(struct target_s *target, uint32_t addr, size_t le return 0; } -static void lpc43xx_set_internal_clock(struct target_s *target) +static void lpc43xx_set_internal_clock(target *t) { const uint32_t val2 = (1 << 11) | (1 << 24); - target_mem_write(target, 0x40050000 + 0x06C, &val2, sizeof(val2)); + target_mem_write(t, 0x40050000 + 0x06C, &val2, sizeof(val2)); } -static int lpc43xx_flash_write(struct target_s *target, +static int lpc43xx_flash_write(target *t, uint32_t dest, const uint8_t *src, size_t len) { unsigned first_chunk = dest / IAP_PGM_CHUNKSIZE; @@ -472,12 +472,12 @@ static int lpc43xx_flash_write(struct target_s *target, } /* prepare... */ - if (lpc43xx_flash_prepare(target, chunk * IAP_PGM_CHUNKSIZE, IAP_PGM_CHUNKSIZE)) { + if (lpc43xx_flash_prepare(t, chunk * IAP_PGM_CHUNKSIZE, IAP_PGM_CHUNKSIZE)) { return -1; } /* copy buffer into target memory */ - target_mem_write(target, + target_mem_write(t, IAP_RAM_BASE + offsetof(struct flash_program, data), flash_pgm.data, sizeof(flash_pgm.data)); @@ -488,7 +488,7 @@ static int lpc43xx_flash_write(struct target_s *target, flash_pgm.p.params.program.byte_count = IAP_PGM_CHUNKSIZE; flash_pgm.p.params.program.cpu_clk_khz = CPU_CLK_KHZ; flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS; - lpc43xx_iap_call(target, &flash_pgm.p, sizeof(flash_pgm)); + lpc43xx_iap_call(t, &flash_pgm.p, sizeof(flash_pgm)); if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { return -1; } @@ -504,7 +504,7 @@ static int lpc43xx_flash_write(struct target_s *target, * This is done indepently of writing to give the user a chance to verify flash * before changing it. */ -static bool lpc43xx_cmd_mkboot(target *target, int argc, const char *argv[]) +static bool lpc43xx_cmd_mkboot(target *t, int argc, const char *argv[]) { /* Usage: mkboot 0 or mkboot 1 */ if (argc != 2) { @@ -519,7 +519,7 @@ static bool lpc43xx_cmd_mkboot(target *target, int argc, const char *argv[]) return false; } - lpc43xx_flash_init(target); + lpc43xx_flash_init(t); struct flash_program flash_pgm; /* special command to compute/write magic vector for signature */ @@ -527,7 +527,7 @@ static bool lpc43xx_cmd_mkboot(target *target, int argc, const char *argv[]) flash_pgm.p.params.make_active.flash_bank = bank; flash_pgm.p.params.make_active.cpu_clk_khz = CPU_CLK_KHZ; flash_pgm.p.result[0] = IAP_STATUS_CMD_SUCCESS; - lpc43xx_iap_call(target, &flash_pgm.p, sizeof(flash_pgm)); + lpc43xx_iap_call(t, &flash_pgm.p, sizeof(flash_pgm)); if (flash_pgm.p.result[0] != IAP_STATUS_CMD_SUCCESS) { gdb_outf("Set bootable failed.\n"); return false; @@ -537,11 +537,11 @@ static bool lpc43xx_cmd_mkboot(target *target, int argc, const char *argv[]) return true; } -static void lpc43xx_wdt_set_period(struct target_s *target) +static void lpc43xx_wdt_set_period(target *t) { uint32_t wdt_mode = 0; /* Check if WDT is on */ - target_mem_read(target, &wdt_mode, LPC43XX_WDT_MODE, sizeof(wdt_mode)); + target_mem_read(t, &wdt_mode, LPC43XX_WDT_MODE, sizeof(wdt_mode)); /* If WDT on, we can't disable it, but we may be able to set a long period */ if (wdt_mode && !(wdt_mode & LPC43XX_WDT_PROTECT)) @@ -549,15 +549,15 @@ static void lpc43xx_wdt_set_period(struct target_s *target) const uint32_t wdt_period = LPC43XX_WDT_PERIOD_MAX; - target_mem_write(target, LPC43XX_WDT_CNT, &wdt_period, sizeof(wdt_period)); + target_mem_write(t, LPC43XX_WDT_CNT, &wdt_period, sizeof(wdt_period)); } } -static void lpc43xx_wdt_pet(struct target_s *target) +static void lpc43xx_wdt_pet(target *t) { uint32_t wdt_mode = 0; /* Check if WDT is on */ - target_mem_read(target, &wdt_mode, LPC43XX_WDT_MODE, sizeof(wdt_mode)); + target_mem_read(t, &wdt_mode, LPC43XX_WDT_MODE, sizeof(wdt_mode)); /* If WDT on, pet */ if (wdt_mode) @@ -565,8 +565,7 @@ static void lpc43xx_wdt_pet(struct target_s *target) const uint32_t feed1 = 0xAA;; const uint32_t feed2 = 0x55;; - - target_mem_write(target, LPC43XX_WDT_FEED, &feed1, sizeof(feed1)); - target_mem_write(target, LPC43XX_WDT_FEED, &feed2, sizeof(feed2)); + target_mem_write(t, LPC43XX_WDT_FEED, &feed1, sizeof(feed1)); + target_mem_write(t, LPC43XX_WDT_FEED, &feed2, sizeof(feed2)); } } diff --git a/src/nrf51.c b/src/nrf51.c index a75b356..59b70f8 100644 --- a/src/nrf51.c +++ b/src/nrf51.c @@ -28,8 +28,8 @@ #include "gdb_packet.h" #include "cortexm.h" -static int nrf51_flash_erase(struct target_s *target, uint32_t addr, size_t len); -static int nrf51_flash_write(struct target_s *target, uint32_t dest, +static int nrf51_flash_erase(target *t, uint32_t addr, size_t len); +static int nrf51_flash_write(target *t, uint32_t dest, const uint8_t *src, size_t len); static bool nrf51_cmd_erase_all(target *t); @@ -135,11 +135,11 @@ static const uint16_t nrf51_flash_write_stub[] = { }; -bool nrf51_probe(struct target_s *target) +bool nrf51_probe(target *t) { - target->idcode = target_mem_read32(target, NRF51_FICR_CONFIGID) & 0xFFFF; + t->idcode = target_mem_read32(t, NRF51_FICR_CONFIGID) & 0xFFFF; - switch (target->idcode) { + switch (t->idcode) { case 0x001D: case 0x002A: case 0x0044: @@ -151,43 +151,43 @@ bool nrf51_probe(struct target_s *target) case 0x004D: case 0x0026: case 0x004C: - target->driver = "Nordic nRF51"; - target->xml_mem_map = nrf51_xml_memory_map; - target->flash_erase = nrf51_flash_erase; - target->flash_write = nrf51_flash_write; - target_add_commands(target, nrf51_cmd_list, "nRF51"); + t->driver = "Nordic nRF51"; + t->xml_mem_map = nrf51_xml_memory_map; + t->flash_erase = nrf51_flash_erase; + t->flash_write = nrf51_flash_write; + target_add_commands(t, nrf51_cmd_list, "nRF51"); return true; } return false; } -static int nrf51_flash_erase(struct target_s *target, uint32_t addr, size_t len) +static int nrf51_flash_erase(target *t, uint32_t addr, size_t len) { addr &= ~(NRF51_PAGE_SIZE - 1); len &= ~(NRF51_PAGE_SIZE - 1); /* Enable erase */ - target_mem_write32(target, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_EEN); + target_mem_write32(t, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_EEN); /* Poll for NVMC_READY */ - while (target_mem_read32(target, NRF51_NVMC_READY) == 0) - if(target_check_error(target)) + while (target_mem_read32(t, NRF51_NVMC_READY) == 0) + if(target_check_error(t)) return -1; while (len) { if (addr == NRF51_UICR) { // Special Case /* Write to the ERASE_UICR register to erase */ - target_mem_write32(target, NRF51_NVMC_ERASEUICR, 0x1); + target_mem_write32(t, NRF51_NVMC_ERASEUICR, 0x1); } else { // Standard Flash Page /* Write address of first word in page to erase it */ - target_mem_write32(target, NRF51_NVMC_ERASEPAGE, addr); + target_mem_write32(t, NRF51_NVMC_ERASEPAGE, addr); } /* Poll for NVMC_READY */ - while (target_mem_read32(target, NRF51_NVMC_READY) == 0) - if(target_check_error(target)) + while (target_mem_read32(t, NRF51_NVMC_READY) == 0) + if(target_check_error(t)) return -1; addr += NRF51_PAGE_SIZE; @@ -195,17 +195,17 @@ static int nrf51_flash_erase(struct target_s *target, uint32_t addr, size_t len) } /* Return to read-only */ - target_mem_write32(target, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_REN); + target_mem_write32(t, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_REN); /* Poll for NVMC_READY */ - while (target_mem_read32(target, NRF51_NVMC_READY) == 0) - if(target_check_error(target)) + while (target_mem_read32(t, NRF51_NVMC_READY) == 0) + if(target_check_error(t)) return -1; return 0; } -static int nrf51_flash_write(struct target_s *target, uint32_t dest, +static int nrf51_flash_write(target *t, uint32_t dest, const uint8_t *src, size_t len) { uint32_t offset = dest % 4; @@ -220,26 +220,26 @@ static int nrf51_flash_write(struct target_s *target, uint32_t dest, memcpy((uint8_t *)&data[2] + offset, src, len); /* Enable write */ - target_mem_write32(target, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_WEN); + target_mem_write32(t, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_WEN); /* Poll for NVMC_READY */ - while (target_mem_read32(target, NRF51_NVMC_READY) == 0) - if(target_check_error(target)) + while (target_mem_read32(t, NRF51_NVMC_READY) == 0) + if(target_check_error(t)) return -1; /* Write stub and data to target ram and set PC */ - target_mem_write(target, 0x20000000, nrf51_flash_write_stub, 0x28); - target_mem_write(target, 0x20000028, data, len + 8); - cortexm_pc_write(target, 0x20000000); - if(target_check_error(target)) + target_mem_write(t, 0x20000000, nrf51_flash_write_stub, 0x28); + target_mem_write(t, 0x20000028, data, len + 8); + cortexm_pc_write(t, 0x20000000); + if(target_check_error(t)) return -1; /* Execute the stub */ - target_halt_resume(target, 0); - while(!target_halt_wait(target)); + target_halt_resume(t, 0); + while(!target_halt_wait(t)); /* Return to read-only */ - target_mem_write32(target, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_REN); + target_mem_write32(t, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_REN); return 0; } diff --git a/src/sam3x.c b/src/sam3x.c index b9e59a0..63b0991 100644 --- a/src/sam3x.c +++ b/src/sam3x.c @@ -28,8 +28,8 @@ #include "command.h" #include "gdb_packet.h" -static int sam3x_flash_erase(struct target_s *target, uint32_t addr, size_t len); -static int sam3x_flash_write(struct target_s *target, uint32_t dest, +static int sam3x_flash_erase(target *t, uint32_t addr, size_t len); +static int sam3x_flash_write(target *t, uint32_t dest, const uint8_t *src, size_t len); static bool sam3x_cmd_gpnvm_get(target *t); @@ -146,59 +146,59 @@ static const char sam4s_xml_memory_map[] = "" #define SAM3_PAGE_SIZE 256 #define SAM4_PAGE_SIZE 512 -bool sam3x_probe(struct target_s *target) +bool sam3x_probe(target *t) { - target->idcode = target_mem_read32(target, SAM3X_CHIPID_CIDR); + t->idcode = target_mem_read32(t, SAM3X_CHIPID_CIDR); /* FIXME: Check for all variants with similar flash interface */ - switch (target->idcode & (CHIPID_CIDR_ARCH_MASK | CHIPID_CIDR_EPROC_MASK)) { + switch (t->idcode & (CHIPID_CIDR_ARCH_MASK | CHIPID_CIDR_EPROC_MASK)) { case CHIPID_CIDR_ARCH_SAM3XxC | CHIPID_CIDR_EPROC_CM3: case CHIPID_CIDR_ARCH_SAM3XxE | CHIPID_CIDR_EPROC_CM3: case CHIPID_CIDR_ARCH_SAM3XxG | CHIPID_CIDR_EPROC_CM3: - target->driver = "Atmel SAM3X"; - target->xml_mem_map = sam3x_xml_memory_map; - target->flash_erase = sam3x_flash_erase; - target->flash_write = sam3x_flash_write; - target_add_commands(target, sam3x_cmd_list, "SAM3X"); + t->driver = "Atmel SAM3X"; + t->xml_mem_map = sam3x_xml_memory_map; + t->flash_erase = sam3x_flash_erase; + t->flash_write = sam3x_flash_write; + target_add_commands(t, sam3x_cmd_list, "SAM3X"); return true; } - target->idcode = target_mem_read32(target, SAM3N_CHIPID_CIDR); - switch (target->idcode & (CHIPID_CIDR_ARCH_MASK | CHIPID_CIDR_EPROC_MASK)) { + t->idcode = target_mem_read32(t, SAM3N_CHIPID_CIDR); + switch (t->idcode & (CHIPID_CIDR_ARCH_MASK | CHIPID_CIDR_EPROC_MASK)) { case CHIPID_CIDR_ARCH_SAM3NxA | CHIPID_CIDR_EPROC_CM3: case CHIPID_CIDR_ARCH_SAM3NxB | CHIPID_CIDR_EPROC_CM3: case CHIPID_CIDR_ARCH_SAM3NxC | CHIPID_CIDR_EPROC_CM3: - target->driver = "Atmel SAM3N"; - target->xml_mem_map = sam3n_xml_memory_map; - target->flash_erase = sam3x_flash_erase; - target->flash_write = sam3x_flash_write; - target_add_commands(target, sam3x_cmd_list, "SAM3N"); + t->driver = "Atmel SAM3N"; + t->xml_mem_map = sam3n_xml_memory_map; + t->flash_erase = sam3x_flash_erase; + t->flash_write = sam3x_flash_write; + target_add_commands(t, sam3x_cmd_list, "SAM3N"); return true; } - target->idcode = target_mem_read32(target, SAM3S_CHIPID_CIDR); - switch (target->idcode & (CHIPID_CIDR_ARCH_MASK | CHIPID_CIDR_EPROC_MASK)) { + t->idcode = target_mem_read32(t, SAM3S_CHIPID_CIDR); + switch (t->idcode & (CHIPID_CIDR_ARCH_MASK | CHIPID_CIDR_EPROC_MASK)) { case CHIPID_CIDR_ARCH_SAM3SxA | CHIPID_CIDR_EPROC_CM3: case CHIPID_CIDR_ARCH_SAM3SxB | CHIPID_CIDR_EPROC_CM3: case CHIPID_CIDR_ARCH_SAM3SxC | CHIPID_CIDR_EPROC_CM3: - target->driver = "Atmel SAM3S"; - target->xml_mem_map = sam3n_xml_memory_map; - target->flash_erase = sam3x_flash_erase; - target->flash_write = sam3x_flash_write; - target_add_commands(target, sam3x_cmd_list, "SAM3S"); + t->driver = "Atmel SAM3S"; + t->xml_mem_map = sam3n_xml_memory_map; + t->flash_erase = sam3x_flash_erase; + t->flash_write = sam3x_flash_write; + target_add_commands(t, sam3x_cmd_list, "SAM3S"); return true; } - target->idcode = target_mem_read32(target, SAM4S_CHIPID_CIDR); - switch (target->idcode & (CHIPID_CIDR_ARCH_MASK | CHIPID_CIDR_EPROC_MASK)) { + t->idcode = target_mem_read32(t, SAM4S_CHIPID_CIDR); + switch (t->idcode & (CHIPID_CIDR_ARCH_MASK | CHIPID_CIDR_EPROC_MASK)) { case CHIPID_CIDR_ARCH_SAM4SxA | CHIPID_CIDR_EPROC_CM4: case CHIPID_CIDR_ARCH_SAM4SxB | CHIPID_CIDR_EPROC_CM4: case CHIPID_CIDR_ARCH_SAM4SxC | CHIPID_CIDR_EPROC_CM4: - target->driver = "Atmel SAM4S"; - target->xml_mem_map = sam4s_xml_memory_map; - target->flash_erase = sam3x_flash_erase; - target->flash_write = sam3x_flash_write; - target_add_commands(target, sam3x_cmd_list, "SAM4S"); + t->driver = "Atmel SAM4S"; + t->xml_mem_map = sam4s_xml_memory_map; + t->flash_erase = sam3x_flash_erase; + t->flash_write = sam3x_flash_write; + target_add_commands(t, sam3x_cmd_list, "SAM4S"); return true; } @@ -206,27 +206,27 @@ bool sam3x_probe(struct target_s *target) } static int -sam3x_flash_cmd(struct target_s *target, uint32_t base, uint8_t cmd, uint16_t arg) +sam3x_flash_cmd(target *t, uint32_t base, uint8_t cmd, uint16_t arg) { DEBUG("%s: base = 0x%08x cmd = 0x%02X, arg = 0x%06X\n", __func__, base, cmd, arg); - target_mem_write32(target, EEFC_FCR(base), + target_mem_write32(t, EEFC_FCR(base), EEFC_FCR_FKEY | cmd | ((uint32_t)arg << 8)); - while (!(target_mem_read32(target, EEFC_FSR(base)) & EEFC_FSR_FRDY)) - if(target_check_error(target)) + while (!(target_mem_read32(t, EEFC_FSR(base)) & EEFC_FSR_FRDY)) + if(target_check_error(t)) return -1; - uint32_t sr = target_mem_read32(target, EEFC_FSR(base)); + uint32_t sr = target_mem_read32(t, EEFC_FSR(base)); return sr & EEFC_FSR_ERROR; } static uint32_t -sam3x_flash_base(struct target_s *target, uint32_t addr, uint32_t *offset) +sam3x_flash_base(target *t, uint32_t addr, uint32_t *offset) { - if (strcmp(target->driver, "Atmel SAM3X") == 0) { + if (strcmp(t->driver, "Atmel SAM3X") == 0) { uint32_t half = -1; - switch (target->idcode & CHIPID_CIDR_NVPSIZ_MASK) { + switch (t->idcode & CHIPID_CIDR_NVPSIZ_MASK) { case CHIPID_CIDR_NVPSIZ_128K: half = 0x00090000; break; @@ -248,9 +248,9 @@ sam3x_flash_base(struct target_s *target, uint32_t addr, uint32_t *offset) } } - if (strcmp(target->driver, "Atmel SAM4S") == 0) { + if (strcmp(t->driver, "Atmel SAM4S") == 0) { uint32_t half = -1; - switch (target->idcode & CHIPID_CIDR_NVPSIZ_MASK) { + switch (t->idcode & CHIPID_CIDR_NVPSIZ_MASK) { case CHIPID_CIDR_NVPSIZ_128K: case CHIPID_CIDR_NVPSIZ_256K: case CHIPID_CIDR_NVPSIZ_512K: @@ -281,16 +281,16 @@ sam3x_flash_base(struct target_s *target, uint32_t addr, uint32_t *offset) return SAM3N_EEFC_BASE; } -static int sam3x_flash_erase(struct target_s *target, uint32_t addr, size_t len) +static int sam3x_flash_erase(target *t, uint32_t addr, size_t len) { uint32_t offset; - uint32_t base = sam3x_flash_base(target, addr, &offset); + uint32_t base = sam3x_flash_base(t, addr, &offset); /* The SAM4S is the only supported device with a page erase command. * Erasing is done in 8-page chunks. arg[15:2] contains the page * number and arg[1:0] contains 0x1, indicating 8-page chunks. */ - if (strcmp(target->driver, "Atmel SAM4S") == 0) { + if (strcmp(t->driver, "Atmel SAM4S") == 0) { unsigned chunk = offset / SAM4_PAGE_SIZE; /* Fail if the start address is not 8-page-aligned. */ @@ -302,7 +302,7 @@ static int sam3x_flash_erase(struct target_s *target, uint32_t addr, size_t len) */ while (len > 0) { int16_t arg = chunk | 0x1; - if(sam3x_flash_cmd(target, base, EEFC_FCR_FCMD_EPA, arg)) + if(sam3x_flash_cmd(t, base, EEFC_FCR_FCMD_EPA, arg)) return -1; len -= SAM4_PAGE_SIZE * 8; @@ -322,10 +322,10 @@ static int sam3x_flash_erase(struct target_s *target, uint32_t addr, size_t len) memset(buf, 0xff, sizeof(buf)); /* Only do this once, since it doesn't change. */ - target_mem_write(target, addr, buf, SAM3_PAGE_SIZE); + target_mem_write(t, addr, buf, SAM3_PAGE_SIZE); while (len) { - if(sam3x_flash_cmd(target, base, EEFC_FCR_FCMD_EWP, chunk)) + if(sam3x_flash_cmd(t, base, EEFC_FCR_FCMD_EWP, chunk)) return -1; len -= SAM3_PAGE_SIZE; @@ -336,17 +336,17 @@ static int sam3x_flash_erase(struct target_s *target, uint32_t addr, size_t len) return 0; } -static int sam3x_flash_write(struct target_s *target, uint32_t dest, +static int sam3x_flash_write(target *t, uint32_t dest, const uint8_t *src, size_t len) { unsigned page_size; - if (strcmp(target->driver, "Atmel SAM4S") == 0) { + if (strcmp(t->driver, "Atmel SAM4S") == 0) { page_size = SAM4_PAGE_SIZE; } else { page_size = SAM3_PAGE_SIZE; } uint32_t offset; - uint32_t base = sam3x_flash_base(target, dest, &offset); + uint32_t base = sam3x_flash_base(t, dest, &offset); uint8_t buf[page_size]; unsigned first_chunk = offset / page_size; unsigned last_chunk = (offset + len - 1) / page_size; @@ -380,8 +380,8 @@ static int sam3x_flash_write(struct target_s *target, uint32_t dest, src += page_size; } - target_mem_write(target, dest, buf, page_size); - if(sam3x_flash_cmd(target, base, EEFC_FCR_FCMD_WP, chunk)) + target_mem_write(t, dest, buf, page_size); + if(sam3x_flash_cmd(t, base, EEFC_FCR_FCMD_WP, chunk)) return -1; } diff --git a/src/samd.c b/src/samd.c index a996610..c8517aa 100644 --- a/src/samd.c +++ b/src/samd.c @@ -40,8 +40,8 @@ #include "gdb_packet.h" #include "cortexm.h" -static int samd_flash_erase(struct target_s *target, uint32_t addr, size_t len); -static int samd_flash_write(struct target_s *target, uint32_t dest, +static int samd_flash_erase(target *t, uint32_t addr, size_t len); +static int samd_flash_write(target *t, uint32_t dest, const uint8_t *src, size_t len); static bool samd_cmd_erase_all(target *t); @@ -162,28 +162,28 @@ static const char samd_xml_memory_map[] = "" /** * Reads the SAM D20 Peripheral ID */ -uint64_t samd_read_pid(struct target_s *target) +uint64_t samd_read_pid(target *t) { uint64_t pid = 0; uint8_t i, j; /* Five PID registers to read LSB first */ for (i = 0, j = 0; i < 5; i++, j += 8) - pid |= (target_mem_read32(target, SAMD_DSU_PID(i)) & 0xFF) << j; + pid |= (target_mem_read32(t, SAMD_DSU_PID(i)) & 0xFF) << j; return pid; } /** * Reads the SAM D20 Component ID */ -uint32_t samd_read_cid(struct target_s *target) +uint32_t samd_read_cid(target *t) { uint64_t cid = 0; uint8_t i, j; /* Four CID registers to read LSB first */ for (i = 0, j = 0; i < 4; i++, j += 8) - cid |= (target_mem_read32(target, SAMD_DSU_CID(i)) & 0xFF) << j; + cid |= (target_mem_read32(t, SAMD_DSU_CID(i)) & 0xFF) << j; return cid; } @@ -193,7 +193,7 @@ uint32_t samd_read_cid(struct target_s *target) * removes the target from extended reset where required. */ static void -samd_reset(struct target_s *target) +samd_reset(target *t) { /** * SRST is not asserted here as it appears to reset the adiv5 @@ -212,31 +212,30 @@ samd_reset(struct target_s *target) */ /* Read DHCSR here to clear S_RESET_ST bit before reset */ - target_mem_read32(target, CORTEXM_DHCSR); + target_mem_read32(t, CORTEXM_DHCSR); /* Request system reset from NVIC: SRST doesn't work correctly */ /* This could be VECTRESET: 0x05FA0001 (reset only core) * or SYSRESETREQ: 0x05FA0004 (system reset) */ - target_mem_write32(target, CORTEXM_AIRCR, + target_mem_write32(t, CORTEXM_AIRCR, CORTEXM_AIRCR_VECTKEY | CORTEXM_AIRCR_SYSRESETREQ); /* Exit extended reset */ - if (target_mem_read32(target, SAMD_DSU_CTRLSTAT) & + if (target_mem_read32(t, SAMD_DSU_CTRLSTAT) & SAMD_STATUSA_CRSTEXT) { /* Write bit to clear from extended reset */ - target_mem_write32(target, SAMD_DSU_CTRLSTAT, - SAMD_STATUSA_CRSTEXT); + target_mem_write32(t, SAMD_DSU_CTRLSTAT, SAMD_STATUSA_CRSTEXT); } /* Poll for release from reset */ - while (target_mem_read32(target, CORTEXM_DHCSR) & CORTEXM_DHCSR_S_RESET_ST); + while (target_mem_read32(t, CORTEXM_DHCSR) & CORTEXM_DHCSR_S_RESET_ST); /* Reset DFSR flags */ - target_mem_write32(target, CORTEXM_DFSR, CORTEXM_DFSR_RESETALL); + target_mem_write32(t, CORTEXM_DFSR, CORTEXM_DFSR_RESETALL); /* Clear any target errors */ - target_check_error(target); + target_check_error(t); } /** @@ -246,16 +245,16 @@ samd_reset(struct target_s *target) * Only required for SAM D20 _Revision B_ Silicon */ static void -samd20_revB_detach(struct target_s *target) +samd20_revB_detach(target *t) { - cortexm_detach(target); + cortexm_detach(t); /* ---- Additional ---- */ /* Exit extended reset */ - if (target_mem_read32(target, SAMD_DSU_CTRLSTAT) & + if (target_mem_read32(t, SAMD_DSU_CTRLSTAT) & SAMD_STATUSA_CRSTEXT) { /* Write bit to clear from extended reset */ - target_mem_write32(target, SAMD_DSU_CTRLSTAT, + target_mem_write32(t, SAMD_DSU_CTRLSTAT, SAMD_STATUSA_CRSTEXT); } } @@ -267,16 +266,15 @@ samd20_revB_detach(struct target_s *target) * Only required for SAM D20 _Revision B_ Silicon */ static void -samd20_revB_halt_resume(struct target_s *target, bool step) +samd20_revB_halt_resume(target *t, bool step) { - cortexm_halt_resume(target, step); + cortexm_halt_resume(t, step); /* ---- Additional ---- */ /* Exit extended reset */ - if (target_mem_read32(target, SAMD_DSU_CTRLSTAT) & - SAMD_STATUSA_CRSTEXT) { + if (target_mem_read32(t, SAMD_DSU_CTRLSTAT) & SAMD_STATUSA_CRSTEXT) { /* Write bit to clear from extended reset */ - target_mem_write32(target, SAMD_DSU_CTRLSTAT, + target_mem_write32(t, SAMD_DSU_CTRLSTAT, SAMD_STATUSA_CRSTEXT); } } @@ -290,7 +288,7 @@ samd20_revB_halt_resume(struct target_s *target, bool step) * rescue the device. */ static bool -samd_protected_attach(struct target_s *target) +samd_protected_attach(target *t) { /** * TODO: Notify the user that we're not really attached and @@ -299,7 +297,7 @@ samd_protected_attach(struct target_s *target) */ /* Patch back in the normal cortexm attach for next time */ - target->attach = cortexm_attach; + t->attach = cortexm_attach; /* Allow attach this time */ return true; @@ -365,10 +363,10 @@ struct samd_descr samd_parse_device_id(uint32_t did) char variant_string[40]; -bool samd_probe(struct target_s *target) +bool samd_probe(target *t) { - uint32_t cid = samd_read_cid(target); - uint32_t pid = samd_read_pid(target); + uint32_t cid = samd_read_cid(t); + uint32_t pid = samd_read_pid(t); /* Check the ARM Coresight Component and Perhiperal IDs */ if ((cid != SAMD_CID_VALUE) || @@ -376,14 +374,13 @@ bool samd_probe(struct target_s *target) return false; /* Read the Device ID */ - uint32_t did = target_mem_read32(target, SAMD_DSU_DID); + uint32_t did = target_mem_read32(t, SAMD_DSU_DID); /* If the Device ID matches */ if ((did & SAMD_DID_MASK) != SAMD_DID_CONST_VALUE) return false; - uint32_t ctrlstat = target_mem_read32(target, - SAMD_DSU_CTRLSTAT); + uint32_t ctrlstat = target_mem_read32(t, SAMD_DSU_CTRLSTAT); struct samd_descr samd = samd_parse_device_id(did); /* Protected? */ @@ -403,8 +400,8 @@ bool samd_probe(struct target_s *target) } /* Setup Target */ - target->driver = variant_string; - target->reset = samd_reset; + t->driver = variant_string; + t->reset = samd_reset; if (samd.series == 20 && samd.revision == 'B') { /** @@ -412,8 +409,8 @@ bool samd_probe(struct target_s *target) * extended reset. Appears to be * related to Errata 35.4.1 ref 12015 */ - target->detach = samd20_revB_detach; - target->halt_resume = samd20_revB_halt_resume; + t->detach = samd20_revB_detach; + t->halt_resume = samd20_revB_halt_resume; } if (protected) { /** @@ -423,23 +420,23 @@ bool samd_probe(struct target_s *target) * attach on a temporary basis so they * can rescue the device. */ - target->attach = samd_protected_attach; + t->attach = samd_protected_attach; } - target->xml_mem_map = samd_xml_memory_map; - target->flash_erase = samd_flash_erase; - target->flash_write = samd_flash_write; - target_add_commands(target, samd_cmd_list, "SAMD"); + t->xml_mem_map = samd_xml_memory_map; + t->flash_erase = samd_flash_erase; + t->flash_write = samd_flash_write; + target_add_commands(t, samd_cmd_list, "SAMD"); /* If we're not in reset here */ if (!connect_assert_srst) { /* We'll have to release the target from * extended reset to make attach possible */ - if (target_mem_read32(target, SAMD_DSU_CTRLSTAT) & + if (target_mem_read32(t, SAMD_DSU_CTRLSTAT) & SAMD_STATUSA_CRSTEXT) { /* Write bit to clear from extended reset */ - target_mem_write32(target, SAMD_DSU_CTRLSTAT, + target_mem_write32(t, SAMD_DSU_CTRLSTAT, SAMD_STATUSA_CRSTEXT); } } @@ -450,23 +447,23 @@ bool samd_probe(struct target_s *target) /** * Temporary (until next reset) flash memory locking / unlocking */ -static void samd_lock_current_address(struct target_s *target) +static void samd_lock_current_address(target *t) { /* Issue the unlock command */ - target_mem_write32(target, SAMD_NVMC_CTRLA, + target_mem_write32(t, SAMD_NVMC_CTRLA, SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_LOCK); } -static void samd_unlock_current_address(struct target_s *target) +static void samd_unlock_current_address(target *t) { /* Issue the unlock command */ - target_mem_write32(target, SAMD_NVMC_CTRLA, + target_mem_write32(t, SAMD_NVMC_CTRLA, SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_UNLOCK); } /** * Erase flash row by row */ -static int samd_flash_erase(struct target_s *target, uint32_t addr, size_t len) +static int samd_flash_erase(target *t, uint32_t addr, size_t len) { addr &= ~(SAMD_ROW_SIZE - 1); len &= ~(SAMD_ROW_SIZE - 1); @@ -474,21 +471,21 @@ static int samd_flash_erase(struct target_s *target, uint32_t addr, size_t len) while (len) { /* Write address of first word in row to erase it */ /* Must be shifted right for 16-bit address, see Datasheet §20.8.8 Address */ - target_mem_write32(target, SAMD_NVMC_ADDRESS, addr >> 1); + target_mem_write32(t, SAMD_NVMC_ADDRESS, addr >> 1); /* Unlock */ - samd_unlock_current_address(target); + samd_unlock_current_address(t); /* Issue the erase command */ - target_mem_write32(target, SAMD_NVMC_CTRLA, + target_mem_write32(t, SAMD_NVMC_CTRLA, SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_ERASEROW); /* Poll for NVM Ready */ - while ((target_mem_read32(target, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0) - if (target_check_error(target)) + while ((target_mem_read32(t, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0) + if (target_check_error(t)) return -1; /* Lock */ - samd_lock_current_address(target); + samd_lock_current_address(t); addr += SAMD_ROW_SIZE; len -= SAMD_ROW_SIZE; @@ -500,7 +497,7 @@ static int samd_flash_erase(struct target_s *target, uint32_t addr, size_t len) /** * Write flash page by page */ -static int samd_flash_write(struct target_s *target, uint32_t dest, +static int samd_flash_write(target *t, uint32_t dest, const uint8_t *src, size_t len) { /* Find the size of our 32-bit data buffer */ @@ -529,26 +526,26 @@ static int samd_flash_write(struct target_s *target, uint32_t dest, length = MIN(end + 4, next_page) - addr; /* Write within a single page. This may be part or all of the page */ - target_mem_write(target, addr, &data[i], length); + target_mem_write(t, addr, &data[i], length); addr += length; i += (length >> 2); /* If MANW=0 (default) we may have triggered an automatic * write. Ignore this */ /* Unlock */ - samd_unlock_current_address(target); + samd_unlock_current_address(t); /* Issue the write page command */ - target_mem_write32(target, SAMD_NVMC_CTRLA, + target_mem_write32(t, SAMD_NVMC_CTRLA, SAMD_CTRLA_CMD_KEY | SAMD_CTRLA_CMD_WRITEPAGE); /* Poll for NVM Ready */ - while ((target_mem_read32(target, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0) - if (target_check_error(target)) + while ((target_mem_read32(t, SAMD_NVMC_INTFLAG) & SAMD_NVMC_READY) == 0) + if (target_check_error(t)) return -1; /* Lock */ - samd_lock_current_address(target); + samd_lock_current_address(t); } return 0; diff --git a/src/stm32f1.c b/src/stm32f1.c index 8f7a7d7..49a5815 100644 --- a/src/stm32f1.c +++ b/src/stm32f1.c @@ -46,11 +46,11 @@ const struct command_s stm32f1_cmd_list[] = { }; -static int stm32md_flash_erase(struct target_s *target, uint32_t addr, size_t len); -static int stm32hd_flash_erase(struct target_s *target, uint32_t addr, size_t len); -static int stm32f1_flash_erase(struct target_s *target, uint32_t addr, size_t len, +static int stm32md_flash_erase(target *t, uint32_t addr, size_t len); +static int stm32hd_flash_erase(target *t, uint32_t addr, size_t len); +static int stm32f1_flash_erase(target *t, uint32_t addr, size_t len, uint32_t pagesize); -static int stm32f1_flash_write(struct target_s *target, uint32_t dest, +static int stm32f1_flash_write(target *t, uint32_t dest, const uint8_t *src, size_t len); static const char stm32f1_driver_str[] = "STM32, Medium density."; @@ -127,66 +127,66 @@ static const uint16_t stm32f1_flash_write_stub[] = { #define SRAM_BASE 0x20000000 #define STUB_BUFFER_BASE ALIGN(SRAM_BASE + sizeof(stm32f1_flash_write_stub), 4) -bool stm32f1_probe(struct target_s *target) +bool stm32f1_probe(target *t) { - target->idcode = target_mem_read32(target, DBGMCU_IDCODE) & 0xfff; - switch(target->idcode) { + t->idcode = target_mem_read32(t, DBGMCU_IDCODE) & 0xfff; + switch(t->idcode) { case 0x410: /* Medium density */ case 0x412: /* Low denisty */ case 0x420: /* Value Line, Low-/Medium density */ - target->driver = stm32f1_driver_str; - target->xml_mem_map = stm32f1_xml_memory_map; - target->flash_erase = stm32md_flash_erase; - target->flash_write = stm32f1_flash_write; - target_add_commands(target, stm32f1_cmd_list, "STM32 LD/MD"); + t->driver = stm32f1_driver_str; + t->xml_mem_map = stm32f1_xml_memory_map; + t->flash_erase = stm32md_flash_erase; + t->flash_write = stm32f1_flash_write; + target_add_commands(t, stm32f1_cmd_list, "STM32 LD/MD"); return true; case 0x414: /* High density */ case 0x418: /* Connectivity Line */ case 0x428: /* Value Line, High Density */ - target->driver = stm32hd_driver_str; - target->xml_mem_map = stm32hd_xml_memory_map; - target->flash_erase = stm32hd_flash_erase; - target->flash_write = stm32f1_flash_write; - target_add_commands(target, stm32f1_cmd_list, "STM32 HD/CL"); + t->driver = stm32hd_driver_str; + t->xml_mem_map = stm32hd_xml_memory_map; + t->flash_erase = stm32hd_flash_erase; + t->flash_write = stm32f1_flash_write; + target_add_commands(t, stm32f1_cmd_list, "STM32 HD/CL"); return true; case 0x422: /* STM32F30x */ case 0x432: /* STM32F37x */ - target->driver = stm32f3_driver_str; - target->xml_mem_map = stm32hd_xml_memory_map; - target->flash_erase = stm32hd_flash_erase; - target->flash_write = stm32f1_flash_write; - target_add_commands(target, stm32f1_cmd_list, "STM32F3"); + t->driver = stm32f3_driver_str; + t->xml_mem_map = stm32hd_xml_memory_map; + t->flash_erase = stm32hd_flash_erase; + t->flash_write = stm32f1_flash_write; + target_add_commands(t, stm32f1_cmd_list, "STM32F3"); return true; } - target->idcode = target_mem_read32(target, DBGMCU_IDCODE_F0) & 0xfff; - switch(target->idcode) { + t->idcode = target_mem_read32(t, DBGMCU_IDCODE_F0) & 0xfff; + switch(t->idcode) { case 0x444: /* STM32F03 RM0091 Rev.7 */ case 0x445: /* STM32F04 RM0091 Rev.7 */ case 0x440: /* STM32F05 RM0091 Rev.7 */ case 0x448: /* STM32F07 RM0091 Rev.7 */ case 0x442: /* STM32F09 RM0091 Rev.7 */ - switch(target->idcode) { + switch(t->idcode) { case 0x444: /* STM32F03 */ - target->driver = stm32f03_driver_str; + t->driver = stm32f03_driver_str; break; case 0x445: /* STM32F04 */ - target->driver = stm32f04_driver_str; + t->driver = stm32f04_driver_str; break; case 0x440: /* STM32F05 */ - target->driver = stm32f05_driver_str; + t->driver = stm32f05_driver_str; break; case 0x448: /* STM32F07 */ - target->driver = stm32f07_driver_str; + t->driver = stm32f07_driver_str; break; case 0x442: /* STM32F09 */ - target->driver = stm32f09_driver_str; + t->driver = stm32f09_driver_str; break; } - target->xml_mem_map = stm32f1_xml_memory_map; - target->flash_erase = stm32md_flash_erase; - target->flash_write = stm32f1_flash_write; - target_add_commands(target, stm32f1_cmd_list, "STM32F0"); + t->xml_mem_map = stm32f1_xml_memory_map; + t->flash_erase = stm32md_flash_erase; + t->flash_write = stm32f1_flash_write; + target_add_commands(t, stm32f1_cmd_list, "STM32F0"); return true; } @@ -199,7 +199,7 @@ static void stm32f1_flash_unlock(target *t) target_mem_write32(t, FLASH_KEYR, KEY2); } -static int stm32f1_flash_erase(struct target_s *target, uint32_t addr, +static int stm32f1_flash_erase(target *t, uint32_t addr, size_t len, uint32_t pagesize) { uint16_t sr; @@ -207,19 +207,19 @@ static int stm32f1_flash_erase(struct target_s *target, uint32_t addr, addr &= ~(pagesize - 1); len = (len + pagesize - 1) & ~(pagesize - 1); - stm32f1_flash_unlock(target); + stm32f1_flash_unlock(t); while(len) { /* Flash page erase instruction */ - target_mem_write32(target, FLASH_CR, FLASH_CR_PER); + target_mem_write32(t, FLASH_CR, FLASH_CR_PER); /* write address to FMA */ - target_mem_write32(target, FLASH_AR, addr); + target_mem_write32(t, FLASH_AR, addr); /* Flash page erase start instruction */ - target_mem_write32(target, FLASH_CR, FLASH_CR_STRT | FLASH_CR_PER); + target_mem_write32(t, FLASH_CR, FLASH_CR_STRT | FLASH_CR_PER); /* Read FLASH_SR to poll for BSY bit */ - while (target_mem_read32(target, FLASH_SR) & FLASH_SR_BSY) - if(target_check_error(target)) + while (target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY) + if(target_check_error(t)) return -1; len -= pagesize; @@ -227,24 +227,24 @@ static int stm32f1_flash_erase(struct target_s *target, uint32_t addr, } /* Check for error */ - sr = target_mem_read32(target, FLASH_SR); + sr = target_mem_read32(t, FLASH_SR); if ((sr & SR_ERROR_MASK) || !(sr & SR_EOP)) return -1; return 0; } -static int stm32hd_flash_erase(struct target_s *target, uint32_t addr, size_t len) +static int stm32hd_flash_erase(target *t, uint32_t addr, size_t len) { - return stm32f1_flash_erase(target, addr, len, 0x800); + return stm32f1_flash_erase(t, addr, len, 0x800); } -static int stm32md_flash_erase(struct target_s *target, uint32_t addr, size_t len) +static int stm32md_flash_erase(target *t, uint32_t addr, size_t len) { - return stm32f1_flash_erase(target, addr, len, 0x400); + return stm32f1_flash_erase(t, addr, len, 0x400); } -static int stm32f1_flash_write(struct target_s *target, uint32_t dest, +static int stm32f1_flash_write(target *t, uint32_t dest, const uint8_t *src, size_t len) { uint32_t offset = dest % 4; @@ -256,8 +256,8 @@ static int stm32f1_flash_write(struct target_s *target, uint32_t dest, memcpy((uint8_t *)data + offset, src, len); /* Write stub and data to target ram and set PC */ - target_mem_write(target, STUB_BUFFER_BASE, (void*)data, sizeof(data)); - return cortexm_run_stub(target, SRAM_BASE, stm32f1_flash_write_stub, + target_mem_write(t, STUB_BUFFER_BASE, (void*)data, sizeof(data)); + return cortexm_run_stub(t, SRAM_BASE, stm32f1_flash_write_stub, sizeof(stm32f1_flash_write_stub), dest - offset, STUB_BUFFER_BASE, sizeof(data), 0); diff --git a/src/stm32f4.c b/src/stm32f4.c index fe844ca..125a15e 100644 --- a/src/stm32f4.c +++ b/src/stm32f4.c @@ -47,8 +47,8 @@ const struct command_s stm32f4_cmd_list[] = { }; -static int stm32f4_flash_erase(struct target_s *target, uint32_t addr, size_t len); -static int stm32f4_flash_write(struct target_s *target, uint32_t dest, +static int stm32f4_flash_erase(target *t, uint32_t addr, size_t len); +static int stm32f4_flash_write(target *t, uint32_t dest, const uint8_t *src, size_t len); static const char stm32f4_driver_str[] = "STM32F4xx"; @@ -127,11 +127,11 @@ static const uint16_t stm32f4_flash_write_stub[] = { #define SRAM_BASE 0x20000000 #define STUB_BUFFER_BASE ALIGN(SRAM_BASE + sizeof(stm32f4_flash_write_stub), 4) -bool stm32f4_probe(struct target_s *target) +bool stm32f4_probe(target *t) { uint32_t idcode; - idcode = target_mem_read32(target, DBGMCU_IDCODE); + idcode = target_mem_read32(t, DBGMCU_IDCODE); switch(idcode & 0xFFF) { case 0x411: /* Documented to be 0x413! This is what I read... */ case 0x413: /* F407VGT6 */ @@ -139,11 +139,11 @@ bool stm32f4_probe(struct target_s *target) case 0x423: /* F401 B/C RM0368 Rev.3 */ case 0x431: /* F411 RM0383 Rev.4 */ case 0x433: /* F401 D/E RM0368 Rev.3 */ - target->xml_mem_map = stm32f4_xml_memory_map; - target->driver = stm32f4_driver_str; - target->flash_erase = stm32f4_flash_erase; - target->flash_write = stm32f4_flash_write; - target_add_commands(target, stm32f4_cmd_list, "STM32F4"); + t->xml_mem_map = stm32f4_xml_memory_map; + t->driver = stm32f4_driver_str; + t->flash_erase = stm32f4_flash_erase; + t->flash_write = stm32f4_flash_write; + target_add_commands(t, stm32f4_cmd_list, "STM32F4"); return true; } return false; @@ -158,7 +158,7 @@ static void stm32f4_flash_unlock(target *t) } } -static int stm32f4_flash_erase(struct target_s *target, uint32_t addr, size_t len) +static int stm32f4_flash_erase(target *t, uint32_t addr, size_t len) { uint16_t sr; uint32_t cr; @@ -166,7 +166,7 @@ static int stm32f4_flash_erase(struct target_s *target, uint32_t addr, size_t le addr &= 0x07FFC000; - stm32f4_flash_unlock(target); + stm32f4_flash_unlock(t); while(len) { if (addr < 0x10000) { /* Sector 0..3 */ @@ -183,13 +183,13 @@ static int stm32f4_flash_erase(struct target_s *target, uint32_t addr, size_t le } cr |= FLASH_CR_EOPIE | FLASH_CR_ERRIE | FLASH_CR_SER; /* Flash page erase instruction */ - target_mem_write32(target, FLASH_CR, cr); + target_mem_write32(t, FLASH_CR, cr); /* write address to FMA */ - target_mem_write32(target, FLASH_CR, cr | FLASH_CR_STRT); + target_mem_write32(t, FLASH_CR, cr | FLASH_CR_STRT); /* Read FLASH_SR to poll for BSY bit */ - while(target_mem_read32(target, FLASH_SR) & FLASH_SR_BSY) - if(target_check_error(target)) + while(target_mem_read32(t, FLASH_SR) & FLASH_SR_BSY) + if(target_check_error(t)) return -1; len -= pagesize; @@ -197,14 +197,14 @@ static int stm32f4_flash_erase(struct target_s *target, uint32_t addr, size_t le } /* Check for error */ - sr = target_mem_read32(target, FLASH_SR); + sr = target_mem_read32(t, FLASH_SR); if(sr & SR_ERROR_MASK) return -1; return 0; } -static int stm32f4_flash_write(struct target_s *target, uint32_t dest, +static int stm32f4_flash_write(target *t, uint32_t dest, const uint8_t *src, size_t len) { uint32_t offset = dest % 4; @@ -216,8 +216,8 @@ static int stm32f4_flash_write(struct target_s *target, uint32_t dest, memcpy((uint8_t *)data + offset, src, len); /* Write buffer to target ram call stub */ - target_mem_write(target, STUB_BUFFER_BASE, data, sizeof(data)); - return cortexm_run_stub(target, SRAM_BASE, stm32f4_flash_write_stub, + target_mem_write(t, STUB_BUFFER_BASE, data, sizeof(data)); + return cortexm_run_stub(t, SRAM_BASE, stm32f4_flash_write_stub, sizeof(stm32f4_flash_write_stub), dest - offset, STUB_BUFFER_BASE, sizeof(data), 0); diff --git a/src/stm32l0.c b/src/stm32l0.c index 6d02ad2..695bd22 100644 --- a/src/stm32l0.c +++ b/src/stm32l0.c @@ -123,37 +123,25 @@ static int inhibit_stubs; /* Local option to force non-stub flash IO */ -static int stm32lx_nvm_erase(struct target_s* target, - uint32_t addr, size_t len); -static int stm32lx_nvm_write(struct target_s* target, - uint32_t destination, - const uint8_t* source, +static int stm32lx_nvm_erase(target *t, uint32_t addr, size_t len); +static int stm32lx_nvm_write(target *t, uint32_t dest, const uint8_t* src, size_t size); -static int stm32lx_nvm_prog_erase(struct target_s* target, - uint32_t addr, size_t len); -static int stm32lx_nvm_prog_write(struct target_s* target, - uint32_t destination, - const uint8_t* source, +static int stm32lx_nvm_prog_erase(target *t, uint32_t addr, size_t len); +static int stm32lx_nvm_prog_write(target *t, uint32_t dest, const uint8_t* src, size_t size); -static int stm32lx_nvm_prog_erase_stubbed(struct target_s* target, - uint32_t addr, size_t len); -static int stm32lx_nvm_prog_write_stubbed(struct target_s* target, - uint32_t destination, - const uint8_t* source, - size_t size); +static int stm32lx_nvm_prog_erase_stubbed(target *t, uint32_t addr, size_t len); +static int stm32lx_nvm_prog_write_stubbed(target *t, uint32_t dest, + const uint8_t* src, size_t size); -static int stm32lx_nvm_data_erase(struct target_s* target, - uint32_t addr, size_t len); -static int stm32lx_nvm_data_write(struct target_s* target, - uint32_t destination, - const uint8_t* source, - size_t size); +static int stm32lx_nvm_data_erase(target *t, uint32_t addr, size_t len); +static int stm32lx_nvm_data_write(target *t, uint32_t dest, + const uint8_t* src, size_t size); -static bool stm32lx_cmd_option (target* t, int argc, char** argv); -static bool stm32lx_cmd_eeprom (target* t, int argc, char** argv); -static bool stm32lx_cmd_stubs (target* t, int argc, char** argv); +static bool stm32lx_cmd_option(target* t, int argc, char** argv); +static bool stm32lx_cmd_eeprom(target* t, int argc, char** argv); +static bool stm32lx_cmd_stubs(target* t, int argc, char** argv); static const struct command_s stm32lx_cmd_list[] = { { "stubs", (cmd_handler) stm32lx_cmd_stubs, @@ -216,9 +204,9 @@ static const uint16_t stm32l0_nvm_prog_erase_stub [] = { #include "../flashstub/stm32l05x-nvm-prog-erase.stub" }; -static uint32_t stm32lx_nvm_prog_page_size(struct target_s* target) +static uint32_t stm32lx_nvm_prog_page_size(target *t) { - switch (target->idcode) { + switch (t->idcode) { case 0x417: /* STM32L0xx */ return STM32L0_NVM_PROG_PAGE_SIZE; default: /* STM32L1xx */ @@ -226,9 +214,9 @@ static uint32_t stm32lx_nvm_prog_page_size(struct target_s* target) } } -static bool stm32lx_is_stm32l1(struct target_s* target) +static bool stm32lx_is_stm32l1(target *t) { - switch (target->idcode) { + switch (t->idcode) { case 0x417: /* STM32L0xx */ return false; default: /* STM32L1xx */ @@ -236,9 +224,9 @@ static bool stm32lx_is_stm32l1(struct target_s* target) } } -static uint32_t stm32lx_nvm_eeprom_size(struct target_s* target) +static uint32_t stm32lx_nvm_eeprom_size(target *t) { - switch (target->idcode) { + switch (t->idcode) { case 0x417: /* STM32L0xx */ return STM32L0_NVM_EEPROM_SIZE; default: /* STM32L1xx */ @@ -246,9 +234,9 @@ static uint32_t stm32lx_nvm_eeprom_size(struct target_s* target) } } -static uint32_t stm32lx_nvm_phys(struct target_s* target) +static uint32_t stm32lx_nvm_phys(target *t) { - switch (target->idcode) { + switch (t->idcode) { case 0x417: /* STM32L0xx */ return STM32L0_NVM_PHYS; default: /* STM32L1xx */ @@ -256,9 +244,9 @@ static uint32_t stm32lx_nvm_phys(struct target_s* target) } } -static uint32_t stm32lx_nvm_data_page_size(struct target_s* target) +static uint32_t stm32lx_nvm_data_page_size(target *t) { - switch (target->idcode) { + switch (t->idcode) { case 0x417: /* STM32L0xx */ return STM32L0_NVM_DATA_PAGE_SIZE; default: /* STM32L1xx */ @@ -266,9 +254,9 @@ static uint32_t stm32lx_nvm_data_page_size(struct target_s* target) } } -static uint32_t stm32lx_nvm_option_size(struct target_s* target) +static uint32_t stm32lx_nvm_option_size(target *t) { - switch (target->idcode) { + switch (t->idcode) { case 0x417: /* STM32L0xx */ return STM32L0_NVM_OPT_SIZE; default: /* STM32L1xx */ @@ -279,40 +267,38 @@ static uint32_t stm32lx_nvm_option_size(struct target_s* target) /** Query MCU memory for an indication as to whether or not the currently attached target is served by this module. We detect the STM32L0xx parts as well as the STM32L1xx's. */ -bool stm32l0_probe(struct target_s* target) +bool stm32l0_probe(target *t) { uint32_t idcode; - idcode = target_mem_read32(target, - STM32L1_DBGMCU_IDCODE_PHYS) & 0xfff; + idcode = target_mem_read32(t, STM32L1_DBGMCU_IDCODE_PHYS) & 0xfff; switch (idcode) { case 0x416: /* CAT. 1 device */ case 0x429: /* CAT. 2 device */ case 0x427: /* CAT. 3 device */ case 0x436: /* CAT. 4 device */ case 0x437: /* CAT. 5 device */ - target->idcode = idcode; - target->driver = stm32l1_driver_str; - target->xml_mem_map = stm32l1_xml_memory_map; - target->flash_erase = stm32lx_nvm_erase; - target->flash_write = stm32lx_nvm_write; - target_add_commands(target, stm32lx_cmd_list, "STM32L1x"); + t->idcode = idcode; + t->driver = stm32l1_driver_str; + t->xml_mem_map = stm32l1_xml_memory_map; + t->flash_erase = stm32lx_nvm_erase; + t->flash_write = stm32lx_nvm_write; + target_add_commands(t, stm32lx_cmd_list, "STM32L1x"); return true; } - idcode = target_mem_read32(target, - STM32L0_DBGMCU_IDCODE_PHYS) & 0xfff; + idcode = target_mem_read32(t, STM32L0_DBGMCU_IDCODE_PHYS) & 0xfff; switch (idcode) { default: break; case 0x417: /* STM32L0x[123] & probably others */ - target->idcode = idcode; - target->driver = stm32l0_driver_str; - target->xml_mem_map = stm32l0_xml_memory_map; - target->flash_erase = stm32lx_nvm_erase; - target->flash_write = stm32lx_nvm_write; - target_add_commands(target, stm32lx_cmd_list, "STM32L0x"); + t->idcode = idcode; + t->driver = stm32l0_driver_str; + t->xml_mem_map = stm32l0_xml_memory_map; + t->flash_erase = stm32lx_nvm_erase; + t->flash_write = stm32lx_nvm_write; + target_add_commands(t, stm32lx_cmd_list, "STM32L0x"); return true; } @@ -364,17 +350,17 @@ static bool stm32lx_nvm_opt_unlock(target *t, uint32_t nvm) /** Erase a region of flash using a stub function. This only works when the MCU hasn't entered a fault state(see NOTES). The flash array is erased for all pages from addr to addr+len inclusive. */ -static int stm32lx_nvm_prog_erase_stubbed(struct target_s* target, +static int stm32lx_nvm_prog_erase_stubbed(target *t, uint32_t addr, size_t size) { struct stm32lx_nvm_stub_info info; - const uint32_t nvm = stm32lx_nvm_phys(target); + const uint32_t nvm = stm32lx_nvm_phys(t); info.nvm = nvm; - info.page_size = stm32lx_nvm_prog_page_size(target); + info.page_size = stm32lx_nvm_prog_page_size(t); /* Load the stub */ - target_mem_write(target, STM32Lx_STUB_PHYS, + target_mem_write(t, STM32Lx_STUB_PHYS, &stm32l0_nvm_prog_erase_stub[0], sizeof(stm32l0_nvm_prog_erase_stub)); @@ -383,21 +369,20 @@ static int stm32lx_nvm_prog_erase_stubbed(struct target_s* target, info.size = size; /* Copy parameters */ - target_mem_write(target, STM32Lx_STUB_INFO_PHYS, - &info, sizeof(info)); + target_mem_write(t, STM32Lx_STUB_INFO_PHYS, &info, sizeof(info)); /* Execute stub */ - cortexm_pc_write(target, STM32Lx_STUB_PHYS); - if (target_check_error(target)) + cortexm_pc_write(t, STM32Lx_STUB_PHYS); + if (target_check_error(t)) return -1; - target_halt_resume(target, 0); - while (!target_halt_wait(target)) + target_halt_resume(t, 0); + while (!target_halt_wait(t)) ; - { - if (target_mem_read32(target, STM32Lx_NVM_SR(nvm)) - & STM32Lx_NVM_SR_ERR_M) - return -1; - } + + if (target_mem_read32(t, STM32Lx_NVM_SR(nvm)) + & STM32Lx_NVM_SR_ERR_M) + return -1; + return 0; } @@ -407,14 +392,14 @@ static int stm32lx_nvm_prog_erase_stubbed(struct target_s* target, when the MCU hasn't entered a fault state. Once the MCU faults, this function will not succeed because the MCU will fault before executing a single instruction in the stub. */ -static int stm32lx_nvm_prog_write_stubbed(struct target_s* target, +static int stm32lx_nvm_prog_write_stubbed(target *t, uint32_t destination, const uint8_t* source, size_t size) { struct stm32lx_nvm_stub_info info; - const uint32_t nvm = stm32lx_nvm_phys(target); - const size_t page_size = stm32lx_nvm_prog_page_size(target); + const uint32_t nvm = stm32lx_nvm_phys(t); + const size_t page_size = stm32lx_nvm_prog_page_size(t); /* We can only handle word aligned writes and even word-multiple ranges. The stm32lx's cannot perform @@ -427,7 +412,7 @@ static int stm32lx_nvm_prog_write_stubbed(struct target_s* target, info.page_size = page_size; /* Load the stub */ - target_mem_write(target, STM32Lx_STUB_PHYS, + target_mem_write(t, STM32Lx_STUB_PHYS, &stm32l0_nvm_prog_write_stub[0], sizeof(stm32l0_nvm_prog_write_stub)); @@ -451,7 +436,7 @@ static int stm32lx_nvm_prog_write_stubbed(struct target_s* target, info.size = cb; /* Copy data to write to flash */ - target_mem_write(target, info.source, source, info.size); + target_mem_write(t, info.source, source, info.size); /* Move pointers early */ destination += cb; @@ -459,18 +444,18 @@ static int stm32lx_nvm_prog_write_stubbed(struct target_s* target, size -= cb; /* Copy parameters */ - target_mem_write(target, STM32Lx_STUB_INFO_PHYS, + target_mem_write(t, STM32Lx_STUB_INFO_PHYS, &info, sizeof(info)); /* Execute stub */ - cortexm_pc_write(target, STM32Lx_STUB_PHYS); - if (target_check_error(target)) + cortexm_pc_write(t, STM32Lx_STUB_PHYS); + if (target_check_error(t)) return -1; - target_halt_resume(target, 0); - while (!target_halt_wait(target)) + target_halt_resume(t, 0); + while (!target_halt_wait(t)) ; - if (target_mem_read32(target, STM32Lx_NVM_SR(nvm)) + if (target_mem_read32(t, STM32Lx_NVM_SR(nvm)) & STM32Lx_NVM_SR_ERR_M) return -1; } @@ -482,19 +467,19 @@ static int stm32lx_nvm_prog_write_stubbed(struct target_s* target, /** Erase a region of NVM for STM32Lx. This is the lead function and it will invoke an implementation, stubbed or not depending on the options and the range of addresses. */ -static int stm32lx_nvm_erase(struct target_s* target, uint32_t addr, size_t size) +static int stm32lx_nvm_erase(target *t, uint32_t addr, size_t size) { if (addr >= STM32Lx_NVM_EEPROM_PHYS) - return stm32lx_nvm_data_erase(target, addr, size); + return stm32lx_nvm_data_erase(t, addr, size); /* Use stub if not inhibited, the MCU is in a non-exceptonal state and there is stub. */ volatile uint32_t regs[20]; - target_regs_read(target, ®s); + target_regs_read(t, ®s); if (inhibit_stubs || (regs[16] & 0xf)) - return stm32lx_nvm_prog_erase(target, addr, size); + return stm32lx_nvm_prog_erase(t, addr, size); - return stm32lx_nvm_prog_erase_stubbed(target, addr, size); + return stm32lx_nvm_prog_erase_stubbed(t, addr, size); } @@ -503,13 +488,13 @@ static int stm32lx_nvm_erase(struct target_s* target, uint32_t addr, size_t size the options and the range of addresses. Data (EEPROM) writes don't have to care about alignment, but the program flash does. There is a fixup for unaligned program flash writes. */ -static int stm32lx_nvm_write(struct target_s* target, +static int stm32lx_nvm_write(target *t, uint32_t destination, const uint8_t* source, size_t size) { if (destination >= STM32Lx_NVM_EEPROM_PHYS) - return stm32lx_nvm_data_write(target, destination, source, + return stm32lx_nvm_data_write(t, destination, source, size); /* Unaligned destinations. To make this feature simple to @@ -532,12 +517,12 @@ static int stm32lx_nvm_write(struct target_s* target, /* Skip stub if the MCU is in a questionable state, or if the user asks us to avoid stubs. */ volatile uint32_t regs[20]; - target_regs_read(target, ®s); + target_regs_read(t, ®s); if (inhibit_stubs || (regs[16] & 0xf)) - return stm32lx_nvm_prog_write(target, destination, source, + return stm32lx_nvm_prog_write(t, destination, source, size); - return stm32lx_nvm_prog_write_stubbed(target, destination, source, + return stm32lx_nvm_prog_write_stubbed(t, destination, source, size); } @@ -546,49 +531,46 @@ static int stm32lx_nvm_write(struct target_s* target, interface. This is slower than stubbed versions(see NOTES). The flash array is erased for all pages from addr to addr+len inclusive. NVM register file address chosen from target. */ -static int stm32lx_nvm_prog_erase(struct target_s* target, - uint32_t addr, size_t len) +static int stm32lx_nvm_prog_erase(target *t, uint32_t addr, size_t len) { - const size_t page_size = stm32lx_nvm_prog_page_size(target); - const uint32_t nvm = stm32lx_nvm_phys(target); + const size_t page_size = stm32lx_nvm_prog_page_size(t); + const uint32_t nvm = stm32lx_nvm_phys(t); /* Word align */ len += (addr & 3); addr &= ~3; - if (!stm32lx_nvm_prog_data_unlock(target, nvm)) + if (!stm32lx_nvm_prog_data_unlock(t, nvm)) return -1; /* Flash page erase instruction */ - target_mem_write32(target, STM32Lx_NVM_PECR(nvm), + target_mem_write32(t, STM32Lx_NVM_PECR(nvm), STM32Lx_NVM_PECR_ERASE | STM32Lx_NVM_PECR_PROG); - { - uint32_t pecr = target_mem_read32(target, STM32Lx_NVM_PECR(nvm)); - if ((pecr & (STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE)) - != (STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE)) - return -1; - } + uint32_t pecr = target_mem_read32(t, STM32Lx_NVM_PECR(nvm)); + if ((pecr & (STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE)) + != (STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_ERASE)) + return -1; /* Clear errors. Note that this only works when we wait for the NVM block to complete the last operation. */ - target_mem_write32(target, STM32Lx_NVM_SR(nvm), STM32Lx_NVM_SR_ERR_M); + target_mem_write32(t, STM32Lx_NVM_SR(nvm), STM32Lx_NVM_SR_ERR_M); while (len > 0) { /* Write first word of page to 0 */ - target_mem_write32(target, addr, 0); + target_mem_write32(t, addr, 0); len -= page_size; addr += page_size; } /* Disable further programming by locking PECR */ - stm32lx_nvm_lock(target, nvm); + stm32lx_nvm_lock(t, nvm); /* Wait for completion or an error */ while (1) { - uint32_t sr = target_mem_read32(target, STM32Lx_NVM_SR(nvm)); - if (target_check_error(target)) + uint32_t sr = target_mem_read32(t, STM32Lx_NVM_SR(nvm)); + if (target_check_error(t)) return -1; if (sr & STM32Lx_NVM_SR_BSY) continue; @@ -604,13 +586,13 @@ static int stm32lx_nvm_prog_erase(struct target_s* target, /** Write to program flash using operations through the debug interface. This is slower than the stubbed write(see NOTES). NVM register file address chosen from target. */ -static int stm32lx_nvm_prog_write(struct target_s* target, +static int stm32lx_nvm_prog_write(target *t, uint32_t destination, const uint8_t* source_8, size_t size) { - const uint32_t nvm = stm32lx_nvm_phys(target); - const bool is_stm32l1 = stm32lx_is_stm32l1(target); + const uint32_t nvm = stm32lx_nvm_phys(t); + const bool is_stm32l1 = stm32lx_is_stm32l1(t); /* We can only handle word aligned writes and even word-multiple ranges. The stm32lx's cannot perform @@ -619,19 +601,19 @@ static int stm32lx_nvm_prog_write(struct target_s* target, if ((destination & 3) || (size & 3)) return -1; - if (!stm32lx_nvm_prog_data_unlock(target, nvm)) + if (!stm32lx_nvm_prog_data_unlock(t, nvm)) return -1; - const size_t half_page_size = stm32lx_nvm_prog_page_size(target)/2; + const size_t half_page_size = stm32lx_nvm_prog_page_size(t)/2; uint32_t* source = (uint32_t*) source_8; while (size > 0) { /* Wait for BSY to clear because we cannot write the PECR until the previous operation completes on STM32Lxxx. */ - while (target_mem_read32(target, STM32Lx_NVM_SR(nvm)) + while (target_mem_read32(t, STM32Lx_NVM_SR(nvm)) & STM32Lx_NVM_SR_BSY) - if (target_check_error(target)) { + if (target_check_error(t)) { return -1; } @@ -639,7 +621,7 @@ static int stm32lx_nvm_prog_write(struct target_s* target, // than a half page to write if (size < half_page_size || (destination & (half_page_size - 1))) { - target_mem_write32(target, STM32Lx_NVM_PECR(nvm), + target_mem_write32(t, STM32Lx_NVM_PECR(nvm), is_stm32l1 ? 0 : STM32Lx_NVM_PECR_PROG); @@ -650,31 +632,31 @@ static int stm32lx_nvm_prog_write(struct target_s* target, c = size; size -= c; - target_mem_write(target, destination, source, c); + target_mem_write(t, destination, source, c); source += c/4; destination += c; } // Or we are writing a half-page(s) else { - target_mem_write32(target, STM32Lx_NVM_PECR(nvm), + target_mem_write32(t, STM32Lx_NVM_PECR(nvm), STM32Lx_NVM_PECR_PROG | STM32Lx_NVM_PECR_FPRG); size_t c = size & ~(half_page_size - 1); size -= c; - target_mem_write(target, destination, source, c); + target_mem_write(t, destination, source, c); source += c/4; destination += c; } } /* Disable further programming by locking PECR */ - stm32lx_nvm_lock(target, nvm); + stm32lx_nvm_lock(t, nvm); /* Wait for completion or an error */ while (1) { - uint32_t sr = target_mem_read32(target, STM32Lx_NVM_SR(nvm)); - if (target_check_error(target)) { + uint32_t sr = target_mem_read32(t, STM32Lx_NVM_SR(nvm)); + if (target_check_error(t)) { return -1; } if (sr & STM32Lx_NVM_SR_BSY) @@ -693,45 +675,43 @@ static int stm32lx_nvm_prog_write(struct target_s* target, interface . The flash is erased for all pages from addr to addr+len, inclusive, on a word boundary. NVM register file address chosen from target. */ -static int stm32lx_nvm_data_erase(struct target_s* target, +static int stm32lx_nvm_data_erase(target *t, uint32_t addr, size_t len) { - const size_t page_size = stm32lx_nvm_data_page_size(target); - const uint32_t nvm = stm32lx_nvm_phys(target); + const size_t page_size = stm32lx_nvm_data_page_size(t); + const uint32_t nvm = stm32lx_nvm_phys(t); /* Word align */ len += (addr & 3); addr &= ~3; - if (!stm32lx_nvm_prog_data_unlock(target, nvm)) + if (!stm32lx_nvm_prog_data_unlock(t, nvm)) return -1; /* Flash data erase instruction */ - target_mem_write32(target, STM32Lx_NVM_PECR(nvm), + target_mem_write32(t, STM32Lx_NVM_PECR(nvm), STM32Lx_NVM_PECR_ERASE | STM32Lx_NVM_PECR_DATA); - { - uint32_t pecr = target_mem_read32(target, STM32Lx_NVM_PECR(nvm)); - if ((pecr & (STM32Lx_NVM_PECR_ERASE | STM32Lx_NVM_PECR_DATA)) - != (STM32Lx_NVM_PECR_ERASE | STM32Lx_NVM_PECR_DATA)) - return -1; - } + uint32_t pecr = target_mem_read32(t, STM32Lx_NVM_PECR(nvm)); + if ((pecr & (STM32Lx_NVM_PECR_ERASE | STM32Lx_NVM_PECR_DATA)) + != (STM32Lx_NVM_PECR_ERASE | STM32Lx_NVM_PECR_DATA)) + return -1; while (len > 0) { /* Write first word of page to 0 */ - target_mem_write32(target, addr, 0); + target_mem_write32(t, addr, 0); len -= page_size; addr += page_size; } /* Disable further programming by locking PECR */ - stm32lx_nvm_lock(target, nvm); + stm32lx_nvm_lock(t, nvm); /* Wait for completion or an error */ while (1) { - uint32_t sr = target_mem_read32(target, STM32Lx_NVM_SR(nvm)); - if (target_check_error(target)) + uint32_t sr = target_mem_read32(t, STM32Lx_NVM_SR(nvm)); + if (target_check_error(t)) return -1; if (sr & STM32Lx_NVM_SR_BSY) continue; @@ -748,39 +728,38 @@ static int stm32lx_nvm_data_erase(struct target_s* target, NVM register file address chosen from target. Unaligned destination writes are supported (though unaligned sources are not). */ -static int stm32lx_nvm_data_write(struct target_s* target, +static int stm32lx_nvm_data_write(target *t, uint32_t destination, const uint8_t* source_8, size_t size) { - const uint32_t nvm = stm32lx_nvm_phys(target); - const bool is_stm32l1 = stm32lx_is_stm32l1(target); - uint32_t* source = (uint32_t*) source_8; + const uint32_t nvm = stm32lx_nvm_phys(t); + const bool is_stm32l1 = stm32lx_is_stm32l1(t); + uint32_t* source = (uint32_t*) source_8; - if (!stm32lx_nvm_prog_data_unlock(target, nvm)) + if (!stm32lx_nvm_prog_data_unlock(t, nvm)) return -1; - - target_mem_write32(target, STM32Lx_NVM_PECR(nvm), + target_mem_write32(t, STM32Lx_NVM_PECR(nvm), is_stm32l1 ? 0 : STM32Lx_NVM_PECR_DATA); while (size) { size -= 4; uint32_t v = *source++; - target_mem_write32(target, destination, v); + target_mem_write32(t, destination, v); destination += 4; - if (target_check_error(target)) + if (target_check_error(t)) return -1; } /* Disable further programming by locking PECR */ - stm32lx_nvm_lock(target, nvm); + stm32lx_nvm_lock(t, nvm); /* Wait for completion or an error */ while (1) { - uint32_t sr = target_mem_read32(target, STM32Lx_NVM_SR(nvm)); - if (target_check_error(target)) + uint32_t sr = target_mem_read32(t, STM32Lx_NVM_SR(nvm)); + if (target_check_error(t)) return -1; if (sr & STM32Lx_NVM_SR_BSY) continue; -- cgit v1.2.3 From 31fae032f79b64df38bceec85dfb57b5d021174f Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sun, 29 Mar 2015 15:20:00 -0700 Subject: cortexm: Separate stub loading from running. --- src/cortexm.c | 2 -- src/include/cortexm.h | 1 - src/stm32f1.c | 10 +++++----- src/stm32f4.c | 8 ++++---- 4 files changed, 9 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/cortexm.c b/src/cortexm.c index 0a9785f..0c0bf02 100644 --- a/src/cortexm.c +++ b/src/cortexm.c @@ -616,7 +616,6 @@ static int cortexm_fault_unwind(target *t) } int cortexm_run_stub(target *t, uint32_t loadaddr, - const uint16_t *stub, uint32_t stublen, uint32_t r0, uint32_t r1, uint32_t r2, uint32_t r3) { uint32_t regs[t->regs_size / 4]; @@ -630,7 +629,6 @@ int cortexm_run_stub(target *t, uint32_t loadaddr, regs[16] = 0x1000000; regs[19] = 0; - target_mem_write(t, loadaddr, stub, stublen); cortexm_regs_write(t, regs); if (target_check_error(t)) diff --git a/src/include/cortexm.h b/src/include/cortexm.h index 24e4c4d..ec3369c 100644 --- a/src/include/cortexm.h +++ b/src/include/cortexm.h @@ -147,7 +147,6 @@ bool cortexm_attach(target *t); void cortexm_detach(target *t); void cortexm_halt_resume(target *t, bool step); int cortexm_run_stub(target *t, uint32_t loadaddr, - const uint16_t *stub, uint32_t stublen, uint32_t r0, uint32_t r1, uint32_t r2, uint32_t r3); int cortexm_pc_write(target *t, const uint32_t val); diff --git a/src/stm32f1.c b/src/stm32f1.c index 49a5815..459c159 100644 --- a/src/stm32f1.c +++ b/src/stm32f1.c @@ -256,11 +256,11 @@ static int stm32f1_flash_write(target *t, uint32_t dest, memcpy((uint8_t *)data + offset, src, len); /* Write stub and data to target ram and set PC */ - target_mem_write(t, STUB_BUFFER_BASE, (void*)data, sizeof(data)); - return cortexm_run_stub(t, SRAM_BASE, stm32f1_flash_write_stub, - sizeof(stm32f1_flash_write_stub), - dest - offset, STUB_BUFFER_BASE, sizeof(data), - 0); + target_mem_write(t, SRAM_BASE, stm32f1_flash_write_stub, + sizeof(stm32f1_flash_write_stub)); + target_mem_write(t, STUB_BUFFER_BASE, data, sizeof(data)); + return cortexm_run_stub(t, SRAM_BASE, dest - offset, + STUB_BUFFER_BASE, sizeof(data), 0); } static bool stm32f1_cmd_erase_mass(target *t) diff --git a/src/stm32f4.c b/src/stm32f4.c index 125a15e..03a33f0 100644 --- a/src/stm32f4.c +++ b/src/stm32f4.c @@ -216,11 +216,11 @@ static int stm32f4_flash_write(target *t, uint32_t dest, memcpy((uint8_t *)data + offset, src, len); /* Write buffer to target ram call stub */ + target_mem_write(t, SRAM_BASE, stm32f4_flash_write_stub, + sizeof(stm32f4_flash_write_stub)); target_mem_write(t, STUB_BUFFER_BASE, data, sizeof(data)); - return cortexm_run_stub(t, SRAM_BASE, stm32f4_flash_write_stub, - sizeof(stm32f4_flash_write_stub), - dest - offset, STUB_BUFFER_BASE, sizeof(data), - 0); + return cortexm_run_stub(t, SRAM_BASE, dest - offset, + STUB_BUFFER_BASE, sizeof(data), 0); } static bool stm32f4_cmd_erase_mass(target *t) -- cgit v1.2.3 From 2215e33bcfbe677092c75ba51a2a9bb6bd154884 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sun, 29 Mar 2015 15:58:18 -0700 Subject: lmi: Clean up magic numbers, remove adiv5 links, and doc ref. --- src/lmi.c | 59 ++++++++++++++++++++++++++++------------------------------- 1 file changed, 28 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/lmi.c b/src/lmi.c index 803a19e..6fe1cdb 100644 --- a/src/lmi.c +++ b/src/lmi.c @@ -21,17 +21,28 @@ /* This file implements TI/LMI LM3S target specific functions providing * the XML memory map and Flash memory programming. * - * Issues: - * No detection of the target device. - * Add reference to documentation. - * Flash erase is very slow. + * According to: TivaTM TM4C123GH6PM Microcontroller Datasheet */ #include "general.h" -#include "adiv5.h" #include "target.h" #include "cortexm.h" +#define SRAM_BASE 0x20000000 +#define BLOCK_SIZE 0x400 +#define LMI_SCB_BASE 0x400FE000 +#define LMI_SCB_DID1 (LMI_SCB_BASE + 0x004) + +#define LMI_FLASH_BASE 0x400FD000 +#define LMI_FLASH_FMA (LMI_FLASH_BASE + 0x000) +#define LMI_FLASH_FMC (LMI_FLASH_BASE + 0x008) + +#define LMI_FLASH_FMC_WRITE (1 << 0) +#define LMI_FLASH_FMC_ERASE (1 << 1) +#define LMI_FLASH_FMC_MERASE (1 << 2) +#define LMI_FLASH_FMC_COMT (1 << 3) +#define LMI_FLASH_FMC_WRKEY 0xA4420000 + static int lmi_flash_erase(target *t, uint32_t addr, size_t len); static int lmi_flash_write(target *t, uint32_t dest, const uint8_t *src, size_t len); @@ -101,7 +112,7 @@ static const uint16_t lmi_flash_write_stub[] = { bool lmi_probe(target *t) { - uint32_t did1 = target_mem_read32(t, 0x400FE004); + uint32_t did1 = target_mem_read32(t, LMI_SCB_DID1); switch (did1 >> 16) { case 0x1049: /* LM3S3748 */ t->driver = lmi_driver_str; @@ -122,32 +133,18 @@ bool lmi_probe(target *t) int lmi_flash_erase(target *t, uint32_t addr, size_t len) { - ADIv5_AP_t *ap = adiv5_target_ap(t); - uint32_t tmp; - - addr &= 0xFFFFFC00; - len &= 0xFFFFFC00; - - /* setup word access */ - adiv5_ap_write(ap, 0x00, 0xA2000052); - - /* select Flash Control */ - adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, 0x04, 0x400FD000); + addr &= ~(BLOCK_SIZE - 1); + len &= ~(BLOCK_SIZE - 1); while(len) { - /* write address to FMA */ - adiv5_ap_write(ap, ADIV5_AP_DB(0), addr); /* Required to switch banks */ - /* set ERASE bit in FMC */ - adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_DB(2), 0xA4420002); - /* Read FMC to poll for ERASE bit */ - adiv5_dp_low_access(ap->dp, ADIV5_LOW_READ, ADIV5_AP_DB(2), 0); - do { - tmp = adiv5_dp_low_access(ap->dp, ADIV5_LOW_READ, - ADIV5_AP_DB(2), 0); - } while (tmp & 2); - - len -= 0x400; - addr += 0x400; + target_mem_write32(t, LMI_FLASH_FMA, addr); + target_mem_write32(t, LMI_FLASH_FMC, + LMI_FLASH_FMC_WRKEY | LMI_FLASH_FMC_ERASE); + while (target_mem_read32(t, LMI_FLASH_FMC) & + LMI_FLASH_FMC_ERASE); + + len -= BLOCK_SIZE; + addr += BLOCK_SIZE; } return 0; } @@ -159,7 +156,7 @@ int lmi_flash_write(target *t, uint32_t dest, const uint8_t *src, size_t len) data[1] = len >> 2; memcpy(&data[2], src, len); DEBUG("Sending stub\n"); - target_mem_write(t, 0x20000000, (void*)lmi_flash_write_stub, 0x30); + target_mem_write(t, SRAM_BASE, lmi_flash_write_stub, 0x30); DEBUG("Sending data\n"); target_mem_write(t, 0x20000030, data, len + 8); DEBUG("Running stub\n"); -- cgit v1.2.3 From cac286d3985c531fb5d96dc5315530e313212c17 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sun, 29 Mar 2015 16:20:57 -0700 Subject: lmi: Use generated stub with cortexm_run_stub. --- flashstub/lmi.stub | 1 + src/lmi.c | 53 ++++++++--------------------------------------------- 2 files changed, 9 insertions(+), 45 deletions(-) create mode 100644 flashstub/lmi.stub (limited to 'src') diff --git a/flashstub/lmi.stub b/flashstub/lmi.stub new file mode 100644 index 0000000..afaf939 --- /dev/null +++ b/flashstub/lmi.stub @@ -0,0 +1 @@ +0x4809, 0x490B, 0x467A, 0x3230, 0x4B0A, 0x4D08, 0xB15B, 0x6001, 0x6814, 0x6044, 0x6085, 0x6884, 0x2601, 0x4234, 0xD1FB, 0x3B01, 0x3104, 0x3204, 0xE7F2, 0xBE00, 0xD000, 0x400F, 0x0001, 0xA442, 0x0000, 0x0000, 0x0004, 0x0000, 0x6548, 0x6C6C, 0x206F, 0x6F57, 0x6C72, 0x2164, 0x000A, 0x0000, 0x0000, diff --git a/src/lmi.c b/src/lmi.c index 6fe1cdb..fb425a2 100644 --- a/src/lmi.c +++ b/src/lmi.c @@ -29,7 +29,10 @@ #include "cortexm.h" #define SRAM_BASE 0x20000000 +#define STUB_BUFFER_BASE (SRAM_BASE + 0x30) + #define BLOCK_SIZE 0x400 + #define LMI_SCB_BASE 0x400FE000 #define LMI_SCB_DID1 (LMI_SCB_BASE + 0x004) @@ -73,41 +76,7 @@ static const char tm4c123gh6pm_xml_memory_map[] = "" static const uint16_t lmi_flash_write_stub[] = { -// _start: - 0x4809, // ldr r0, [pc, #36] // _flashbase - 0x490b, // ldr r1, [pc, #44] // _addr - 0x467a, // mov r2, pc - 0x3230, // adds r2, #48 - 0x4b0a, // ldr r3, [pc, #40] // _size - 0x4d08, // ldr r5, [pc, #32] // _flash_write_cmd -// _next: - 0xb15b, // cbz r3, _done - 0x6001, // str r1, [r0, #0] - 0x6814, // ldr r4, [r2] - 0x6044, // str r4, [r0, #4] - 0x6085, // str r5, [r0, #8] -// _wait: - 0x6884, // ldr r4, [r0, #8] - 0x2601, // movs r6, #1 - 0x4234, // tst r4, r6 - 0xd1fb, // bne _wait - - 0x3b01, // subs r3, #1 - 0x3104, // adds r1, #4 - 0x3204, // adds r2, #4 - 0xe7f2, // b _next -// _done: - 0xbe00, // bkpt -// _flashbase: - 0xd000, 0x400f, // .word 0x400fd000 -// _flash_write_cmd: - 0x0001, 0xa442, // .word 0xa4420001 -// _addr: -// 0x0000, 0x0000, -// _size: -// 0x0000, 0x0000, -// _data: -// ... +#include "../flashstub/lmi.stub" }; bool lmi_probe(target *t) @@ -155,16 +124,10 @@ int lmi_flash_write(target *t, uint32_t dest, const uint8_t *src, size_t len) data[0] = dest; data[1] = len >> 2; memcpy(&data[2], src, len); - DEBUG("Sending stub\n"); - target_mem_write(t, SRAM_BASE, lmi_flash_write_stub, 0x30); - DEBUG("Sending data\n"); - target_mem_write(t, 0x20000030, data, len + 8); - DEBUG("Running stub\n"); - cortexm_pc_write(t, 0x20000000); - target_halt_resume(t, 0); - DEBUG("Waiting for halt\n"); - while(!target_halt_wait(t)); - return 0; + target_mem_write(t, SRAM_BASE, lmi_flash_write_stub, + sizeof(lmi_flash_write_stub)); + target_mem_write(t, STUB_BUFFER_BASE, data, len + 8); + return cortexm_run_stub(t, SRAM_BASE, 0, 0, 0, 0); } -- cgit v1.2.3 From 810269dce17691ac5a5fd5ba7141eb844db977f8 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sun, 29 Mar 2015 16:28:18 -0700 Subject: nrf51: Use generated stub. --- flashstub/nrf51.stub | 1 + src/nrf51.c | 37 +------------------------------------ 2 files changed, 2 insertions(+), 36 deletions(-) create mode 100644 flashstub/nrf51.stub (limited to 'src') diff --git a/flashstub/nrf51.stub b/flashstub/nrf51.stub new file mode 100644 index 0000000..6c12fa4 --- /dev/null +++ b/flashstub/nrf51.stub @@ -0,0 +1 @@ +0x4808, 0x4909, 0x467A, 0x3228, 0x4B08, 0x2B00, 0xD009, 0x6814, 0x600C, 0x6804, 0x2601, 0x4234, 0xD0FB, 0x3B04, 0x3104, 0x3204, 0xE7F3, 0xBE00, 0xE400, 0x4001, 0x0000, 0x0000, 0x000C, 0x0000, 0xAAAA, 0xAAAA, 0xBBBB, 0xBBBB, 0xCCCC, 0xCCCC, diff --git a/src/nrf51.c b/src/nrf51.c index 59b70f8..acdaa3a 100644 --- a/src/nrf51.c +++ b/src/nrf51.c @@ -97,42 +97,7 @@ static const char nrf51_xml_memory_map[] = "" #define NRF51_PAGE_SIZE 1024 static const uint16_t nrf51_flash_write_stub[] = { -// _start: - 0x4808, // ldr r0, [pc, #32] ; (24 <_ready>) - 0x4909, // ldr r1, [pc, #36] ; (28 <_addr>) - 0x467a, // mov r2, pc - 0x3228, // adds r2, #40 ; 0x28 - 0x4b08, // ldr r3, [pc, #32] ; (2c <_size>) - -// next: - 0x2b00, // cmp r3, #0 - 0xd009, // beq.n 22 <_done> - 0x6814, // ldr r4, [r2, #0] - 0x600c, // str r4, [r1, #0] - -// wait: - 0x6804, // ldr r4, [r0, #0] - 0x2601, // movs r6, #1 - 0x4234, // tst r4, r6 - 0xd0fb, // beq.n 12 <_wait> - - 0x3b04, // subs r3, #4 - 0x3104, // adds r1, #4 - 0x3204, // adds r2, #4 - 0xe7f3, // b.n a <_next> - -// done: - 0xbe00, // bkpt 0x0000 - -// ready: - 0xe400, 0x4001 // .word 0x4001e400 -// addr: -// 0x0000, 0x0000 -// size: -// 0x0000, 0x0000 -// data: -// ... - +#include "../flashstub/nrf51.stub" }; bool nrf51_probe(target *t) -- cgit v1.2.3 From 012922ed0018bffca82e29dc2565990a114a0f6b Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sun, 29 Mar 2015 16:31:38 -0700 Subject: nrf51: use cortexm_run_stub. --- src/nrf51.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/nrf51.c b/src/nrf51.c index acdaa3a..e302de7 100644 --- a/src/nrf51.c +++ b/src/nrf51.c @@ -96,6 +96,9 @@ static const char nrf51_xml_memory_map[] = "" #define NRF51_PAGE_SIZE 1024 +#define SRAM_BASE 0x20000000 +#define STUB_BUFFER_BASE (SRAM_BASE + 0x28) + static const uint16_t nrf51_flash_write_stub[] = { #include "../flashstub/nrf51.stub" }; @@ -192,16 +195,11 @@ static int nrf51_flash_write(target *t, uint32_t dest, if(target_check_error(t)) return -1; - /* Write stub and data to target ram and set PC */ - target_mem_write(t, 0x20000000, nrf51_flash_write_stub, 0x28); - target_mem_write(t, 0x20000028, data, len + 8); - cortexm_pc_write(t, 0x20000000); - if(target_check_error(t)) - return -1; - - /* Execute the stub */ - target_halt_resume(t, 0); - while(!target_halt_wait(t)); + /* Write stub and data to target ram and call stub */ + target_mem_write(t, SRAM_BASE, nrf51_flash_write_stub, + sizeof(nrf51_flash_write_stub)); + target_mem_write(t, STUB_BUFFER_BASE, data, len + 8); + cortexm_run_stub(t, SRAM_BASE, 0, 0, 0, 0); /* Return to read-only */ target_mem_write32(t, NRF51_NVMC_CONFIG, NRF51_NVMC_CONFIG_REN); -- cgit v1.2.3 From 779dcf0f69e6f1a8327365d606c7771c915e4205 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sun, 29 Mar 2015 16:47:55 -0700 Subject: stm32l0: use cortexm_run_stub. --- src/stm32l0.c | 14 ++------------ 1 file changed, 2 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/stm32l0.c b/src/stm32l0.c index 695bd22..8193b12 100644 --- a/src/stm32l0.c +++ b/src/stm32l0.c @@ -372,12 +372,7 @@ static int stm32lx_nvm_prog_erase_stubbed(target *t, target_mem_write(t, STM32Lx_STUB_INFO_PHYS, &info, sizeof(info)); /* Execute stub */ - cortexm_pc_write(t, STM32Lx_STUB_PHYS); - if (target_check_error(t)) - return -1; - target_halt_resume(t, 0); - while (!target_halt_wait(t)) - ; + cortexm_run_stub(t, STM32Lx_STUB_PHYS, 0, 0, 0, 0); if (target_mem_read32(t, STM32Lx_NVM_SR(nvm)) & STM32Lx_NVM_SR_ERR_M) @@ -448,12 +443,7 @@ static int stm32lx_nvm_prog_write_stubbed(target *t, &info, sizeof(info)); /* Execute stub */ - cortexm_pc_write(t, STM32Lx_STUB_PHYS); - if (target_check_error(t)) - return -1; - target_halt_resume(t, 0); - while (!target_halt_wait(t)) - ; + cortexm_run_stub(t, STM32Lx_STUB_PHYS, 0, 0, 0, 0); if (target_mem_read32(t, STM32Lx_NVM_SR(nvm)) & STM32Lx_NVM_SR_ERR_M) -- cgit v1.2.3 From 274b8185173d1bd0b28f1174ee29e2d2fdacbcae Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sun, 29 Mar 2015 16:48:51 -0700 Subject: Make cortexm_pc_write static. --- src/cortexm.c | 9 +-------- src/include/cortexm.h | 1 - 2 files changed, 1 insertion(+), 9 deletions(-) (limited to 'src') diff --git a/src/cortexm.c b/src/cortexm.c index 0c0bf02..c2684b5 100644 --- a/src/cortexm.c +++ b/src/cortexm.c @@ -24,9 +24,6 @@ * ARM doc DDI0403C. * * Also supports Cortex-M0 / ARMv6-M - * - * Issues: - * There are way too many magic numbers used here. */ #include "general.h" #include "exception.h" @@ -421,16 +418,12 @@ static uint32_t cortexm_pc_read(target *t) { target_mem_write32(t, CORTEXM_DCRSR, 0x0F); return target_mem_read32(t, CORTEXM_DCRDR); - - return 0; } -int cortexm_pc_write(target *t, const uint32_t val) +static void cortexm_pc_write(target *t, const uint32_t val) { target_mem_write32(t, CORTEXM_DCRDR, val); target_mem_write32(t, CORTEXM_DCRSR, CORTEXM_DCRSR_REGWnR | 0x0F); - - return 0; } /* The following three routines implement target halt/resume diff --git a/src/include/cortexm.h b/src/include/cortexm.h index ec3369c..f7396bf 100644 --- a/src/include/cortexm.h +++ b/src/include/cortexm.h @@ -148,7 +148,6 @@ void cortexm_detach(target *t); void cortexm_halt_resume(target *t, bool step); int cortexm_run_stub(target *t, uint32_t loadaddr, uint32_t r0, uint32_t r1, uint32_t r2, uint32_t r3); -int cortexm_pc_write(target *t, const uint32_t val); #endif -- cgit v1.2.3 From c2cde32716c5f4283877188d0e452dcf5e85e563 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sun, 29 Mar 2015 17:37:03 -0700 Subject: Improve cortexm_read/write_regs. Use more sensible return types. --- src/adiv5.c | 7 +++---- src/cortexm.c | 44 ++++++++++++++++++++------------------------ src/include/target.h | 6 +++--- 3 files changed, 26 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/adiv5.c b/src/adiv5.c index 039f129..4bc64bb 100644 --- a/src/adiv5.c +++ b/src/adiv5.c @@ -37,7 +37,7 @@ static const char adiv5_driver_str[] = "ARM ADIv5 MEM-AP"; -static int ap_check_error(target *t); +static bool ap_check_error(target *t); static void ap_mem_read(target *t, void *dest, uint32_t src, size_t len); static void ap_mem_write(target *t, uint32_t dest, const void *src, size_t len); @@ -157,11 +157,10 @@ void adiv5_dp_init(ADIv5_DP_t *dp) adiv5_dp_unref(dp); } -static int -ap_check_error(target *t) +static bool ap_check_error(target *t) { ADIv5_AP_t *ap = adiv5_target_ap(t); - return adiv5_dp_error(ap->dp); + return adiv5_dp_error(ap->dp) != 0; } enum align { diff --git a/src/cortexm.c b/src/cortexm.c index c2684b5..ac4c549 100644 --- a/src/cortexm.c +++ b/src/cortexm.c @@ -57,8 +57,8 @@ const struct command_s cortexm_cmd_list[] = { #define SIGSEGV 11 #define SIGLOST 29 -static int cortexm_regs_read(target *t, void *data); -static int cortexm_regs_write(target *t, const void *data); +static void cortexm_regs_read(target *t, void *data); +static void cortexm_regs_write(target *t, const void *data); static uint32_t cortexm_pc_read(target *t); static void cortexm_reset(target *t); @@ -343,15 +343,16 @@ void cortexm_detach(target *t) target_mem_write32(t, CORTEXM_DHCSR, CORTEXM_DHCSR_DBGKEY); } -static int cortexm_regs_read(target *t, void *data) +enum { DB_DHCSR, DB_DCRSR, DB_DCRDR, DB_DEMCR }; + +static void cortexm_regs_read(target *t, void *data) { ADIv5_AP_t *ap = adiv5_target_ap(t); uint32_t *regs = data; unsigned i; /* FIXME: Describe what's really going on here */ - adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw | - ADIV5_AP_CSW_SIZE_WORD | ADIV5_AP_CSW_ADDRINC_SINGLE); + adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw | ADIV5_AP_CSW_SIZE_WORD); /* Map the banked data registers (0x10-0x1c) to the * debug registers DHCSR, DCRSR, DCRDR and DEMCR respectively */ @@ -359,33 +360,30 @@ static int cortexm_regs_read(target *t, void *data) /* Walk the regnum_cortex_m array, reading the registers it * calls out. */ - adiv5_ap_write(ap, ADIV5_AP_DB(1), regnum_cortex_m[0]); /* Required to switch banks */ - *regs++ = adiv5_dp_read(ap->dp, ADIV5_AP_DB(2)); + adiv5_ap_write(ap, ADIV5_AP_DB(DB_DCRSR), regnum_cortex_m[0]); /* Required to switch banks */ + *regs++ = adiv5_dp_read(ap->dp, ADIV5_AP_DB(DB_DCRDR)); for(i = 1; i < sizeof(regnum_cortex_m) / 4; i++) { - adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_DB(1), + adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_DB(DB_DCRSR), regnum_cortex_m[i]); - *regs++ = adiv5_dp_read(ap->dp, ADIV5_AP_DB(2)); + *regs++ = adiv5_dp_read(ap->dp, ADIV5_AP_DB(DB_DCRDR)); } if (t->target_options & TOPT_FLAVOUR_V7MF) for(i = 0; i < sizeof(regnum_cortex_mf) / 4; i++) { adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, - ADIV5_AP_DB(1), + ADIV5_AP_DB(DB_DCRSR), regnum_cortex_mf[i]); - *regs++ = adiv5_dp_read(ap->dp, ADIV5_AP_DB(2)); + *regs++ = adiv5_dp_read(ap->dp, ADIV5_AP_DB(DB_DCRDR)); } - - return 0; } -static int cortexm_regs_write(target *t, const void *data) +static void cortexm_regs_write(target *t, const void *data) { ADIv5_AP_t *ap = adiv5_target_ap(t); const uint32_t *regs = data; unsigned i; /* FIXME: Describe what's really going on here */ - adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw | - ADIV5_AP_CSW_SIZE_WORD | ADIV5_AP_CSW_ADDRINC_SINGLE); + adiv5_ap_write(ap, ADIV5_AP_CSW, ap->csw | ADIV5_AP_CSW_SIZE_WORD); /* Map the banked data registers (0x10-0x1c) to the * debug registers DHCSR, DCRSR, DCRDR and DEMCR respectively */ @@ -393,25 +391,23 @@ static int cortexm_regs_write(target *t, const void *data) /* Walk the regnum_cortex_m array, writing the registers it * calls out. */ - adiv5_ap_write(ap, ADIV5_AP_DB(2), *regs++); /* Required to switch banks */ - adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_DB(1), + adiv5_ap_write(ap, ADIV5_AP_DB(DB_DCRDR), *regs++); /* Required to switch banks */ + adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_DB(DB_DCRSR), 0x10000 | regnum_cortex_m[0]); for(i = 1; i < sizeof(regnum_cortex_m) / 4; i++) { adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, - ADIV5_AP_DB(2), *regs++); - adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_DB(1), + ADIV5_AP_DB(DB_DCRDR), *regs++); + adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, ADIV5_AP_DB(DB_DCRSR), 0x10000 | regnum_cortex_m[i]); } if (t->target_options & TOPT_FLAVOUR_V7MF) for(i = 0; i < sizeof(regnum_cortex_mf) / 4; i++) { adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, - ADIV5_AP_DB(2), *regs++); + ADIV5_AP_DB(DB_DCRDR), *regs++); adiv5_dp_low_access(ap->dp, ADIV5_LOW_WRITE, - ADIV5_AP_DB(1), + ADIV5_AP_DB(DB_DCRSR), 0x10000 | regnum_cortex_mf[i]); } - - return 0; } static uint32_t cortexm_pc_read(target *t) diff --git a/src/include/target.h b/src/include/target.h index 48e81f2..d844057 100644 --- a/src/include/target.h +++ b/src/include/target.h @@ -115,7 +115,7 @@ struct target_s { /* Attach/Detach funcitons */ bool (*attach)(target *t); void (*detach)(target *t); - int (*check_error)(target *t); + bool (*check_error)(target *t); /* Memory access functions */ void (*mem_read)(target *t, void *dest, uint32_t src, @@ -126,8 +126,8 @@ struct target_s { /* Register access functions */ int regs_size; const char *tdesc; - int (*regs_read)(target *t, void *data); - int (*regs_write)(target *t, const void *data); + void (*regs_read)(target *t, void *data); + void (*regs_write)(target *t, const void *data); /* Halt/resume functions */ void (*reset)(target *t); -- cgit v1.2.3 From 21d464293c29fe2867fe974770154f06049ccf1a Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Sun, 29 Mar 2015 18:06:13 -0700 Subject: gdb: don't access target fields directly. --- src/gdb_main.c | 25 +++++++++---------------- src/include/target.h | 10 ++++++++++ 2 files changed, 19 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/gdb_main.c b/src/gdb_main.c index 961a1d9..6b2059f 100644 --- a/src/gdb_main.c +++ b/src/gdb_main.c @@ -77,9 +77,10 @@ gdb_main(void) /* Implementation of these is mandatory! */ case 'g': { /* 'g': Read general registers */ ERROR_IF_NO_TARGET(); - uint8_t arm_regs[cur_target->regs_size]; + uint8_t arm_regs[target_regs_size(cur_target)]; target_regs_read(cur_target, arm_regs); - gdb_putpacket(hexify(pbuf, (void*)arm_regs, cur_target->regs_size), cur_target->regs_size * 2); + gdb_putpacket(hexify(pbuf, arm_regs, sizeof(arm_regs)), + sizeof(arm_regs) * 2); break; } case 'm': { /* 'm addr,len': Read len bytes from addr */ @@ -97,8 +98,8 @@ gdb_main(void) } case 'G': { /* 'G XX': Write general registers */ ERROR_IF_NO_TARGET(); - uint8_t arm_regs[cur_target->regs_size]; - unhexify(arm_regs, &pbuf[1], cur_target->regs_size); + uint8_t arm_regs[target_regs_size(cur_target)]; + unhexify(arm_regs, &pbuf[1], sizeof(arm_regs)); target_regs_write(cur_target, arm_regs); gdb_putpacketz("OK"); break; @@ -327,11 +328,11 @@ handle_q_packet(char *packet, int len) cur_target = target_attach(last_target, gdb_target_destroy_callback); } - if((!cur_target) || (!cur_target->xml_mem_map)) { + if (!cur_target) { gdb_putpacketz("E01"); return; } - handle_q_string_reply(cur_target->xml_mem_map, packet + 23); + handle_q_string_reply(target_mem_map(cur_target), packet + 23); } else if (strncmp (packet, "qXfer:features:read:target.xml:", 31) == 0) { /* Read target description */ @@ -340,11 +341,11 @@ handle_q_packet(char *packet, int len) cur_target = target_attach(last_target, gdb_target_destroy_callback); } - if((!cur_target) || (!cur_target->tdesc)) { + if (!cur_target) { gdb_putpacketz("E01"); return; } - handle_q_string_reply(cur_target->tdesc, packet + 31); + handle_q_string_reply(target_tdesc(cur_target), packet + 31); } else if (sscanf(packet, "qCRC:%" PRIx32 ",%" PRIx32, &addr, &alen) == 2) { if(!cur_target) { gdb_putpacketz("E01"); @@ -450,10 +451,6 @@ handle_z_packet(char *packet, int plen) sscanf(packet + 2, ",%" PRIx32 ",%d", &addr, &len); switch(type) { case 1: /* Hardware breakpoint */ - if(!cur_target->set_hw_bp) { /* Not supported */ - gdb_putpacketz(""); - return; - } if(set) ret = target_set_hw_bp(cur_target, addr); else @@ -463,10 +460,6 @@ handle_z_packet(char *packet, int plen) case 2: case 3: case 4: - if(!cur_target->set_hw_wp) { /* Not supported */ - gdb_putpacketz(""); - return; - } if(set) ret = target_set_hw_wp(cur_target, type, addr, len); else diff --git a/src/include/target.h b/src/include/target.h index d844057..940a360 100644 --- a/src/include/target.h +++ b/src/include/target.h @@ -108,6 +108,16 @@ target *target_attach(target *t, target_destroy_callback destroy_cb); #define target_hostio_reply(target, recode, errcode) \ (target)->hostio_reply((target), (retcode), (errcode)) +/* Accessor functions */ +#define target_regs_size(target) \ + ((target)->regs_size) + +#define target_mem_map(target) \ + ((target)->xml_mem_map ? (target)->xml_mem_map : "") + +#define target_tdesc(target) \ + ((target)->tdesc ? (target)->tdesc : "") + struct target_s { /* Notify controlling debugger if target is lost */ target_destroy_callback destroy_callback; -- cgit v1.2.3 From bc89217e3f96ae60f4c8dfc6a94cc8e64fb426ed Mon Sep 17 00:00:00 2001 From: Florian Larysch Date: Mon, 30 Mar 2015 18:25:13 +0200 Subject: sam3x: add SAM3U support --- src/sam3x.c | 43 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) (limited to 'src') diff --git a/src/sam3x.c b/src/sam3x.c index 63b0991..0566718 100644 --- a/src/sam3x.c +++ b/src/sam3x.c @@ -65,6 +65,18 @@ static const char sam3n_xml_memory_map[] = "" " " ""; +static const char sam3u_xml_memory_map[] = "" +/* ""*/ + "" + " " + " 0x100" + " " + " " + " " + ""; + static const char sam4s_xml_memory_map[] = "" /* "" /* Enhanced Embedded Flash Controller (EEFC) Register Map */ #define SAM3N_EEFC_BASE 0x400E0A00 #define SAM3X_EEFC_BASE(x) (0x400E0A00+((x)*0x400)) +#define SAM3U_EEFC_BASE(x) (0x400E0800+((x)*0x200)) #define SAM4S_EEFC_BASE(x) (0x400E0A00+((x)*0x200)) #define EEFC_FMR(base) ((base)+0x00) #define EEFC_FCR(base) ((base)+0x04) @@ -111,6 +124,7 @@ static const char sam4s_xml_memory_map[] = "" #define SAM3X_CHIPID_CIDR 0x400E0940 #define SAM3N_CHIPID_CIDR 0x400E0740 #define SAM3S_CHIPID_CIDR 0x400E0740 +#define SAM3U_CHIPID_CIDR 0x400E0740 #define SAM4S_CHIPID_CIDR 0x400E0740 #define CHIPID_CIDR_VERSION_MASK (0x1F << 0) @@ -126,6 +140,8 @@ static const char sam4s_xml_memory_map[] = "" #define CHIPID_CIDR_NVPSIZ2_MASK (0x0F << 12) #define CHIPID_CIDR_SRAMSIZ_MASK (0x0F << 16) #define CHIPID_CIDR_ARCH_MASK (0xFF << 20) +#define CHIPID_CIDR_ARCH_SAM3UxC (0x80 << 20) +#define CHIPID_CIDR_ARCH_SAM3UxE (0x81 << 20) #define CHIPID_CIDR_ARCH_SAM3XxC (0x84 << 20) #define CHIPID_CIDR_ARCH_SAM3XxE (0x85 << 20) #define CHIPID_CIDR_ARCH_SAM3XxG (0x86 << 20) @@ -189,6 +205,18 @@ bool sam3x_probe(target *t) return true; } + t->idcode = target_mem_read32(t, SAM3U_CHIPID_CIDR); + switch (t->idcode & (CHIPID_CIDR_ARCH_MASK | CHIPID_CIDR_EPROC_MASK)) { + case CHIPID_CIDR_ARCH_SAM3UxC | CHIPID_CIDR_EPROC_CM3: + case CHIPID_CIDR_ARCH_SAM3UxE | CHIPID_CIDR_EPROC_CM3: + t->driver = "Atmel SAM3U"; + t->xml_mem_map = sam3u_xml_memory_map; + t->flash_erase = sam3x_flash_erase; + t->flash_write = sam3x_flash_write; + target_add_commands(t, sam3x_cmd_list, "SAM3U"); + return true; + } + t->idcode = target_mem_read32(t, SAM4S_CHIPID_CIDR); switch (t->idcode & (CHIPID_CIDR_ARCH_MASK | CHIPID_CIDR_EPROC_MASK)) { case CHIPID_CIDR_ARCH_SAM4SxA | CHIPID_CIDR_EPROC_CM4: @@ -248,6 +276,21 @@ sam3x_flash_base(target *t, uint32_t addr, uint32_t *offset) } } + /* The SAM3U has a constant split between both banks */ + if (strcmp(t->driver, "Atmel SAM3U") == 0) { + if (addr >= 0x100000) { + if(offset) + *offset = addr - 0x100000; + + return SAM3U_EEFC_BASE(1); + } else { + if(offset) + *offset = addr - 0x80000; + + return SAM3U_EEFC_BASE(0); + } + } + if (strcmp(t->driver, "Atmel SAM4S") == 0) { uint32_t half = -1; switch (t->idcode & CHIPID_CIDR_NVPSIZ_MASK) { -- cgit v1.2.3 From 865beaba981582f2a2206928c58a3a55350f4d38 Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Thu, 2 Apr 2015 21:06:18 -0700 Subject: Suppress warning about longjmp clobbering local variable. --- src/cortexm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/cortexm.c b/src/cortexm.c index ac4c549..ae1c59d 100644 --- a/src/cortexm.c +++ b/src/cortexm.c @@ -464,7 +464,7 @@ static int cortexm_halt_wait(target *t) ADIv5_AP_t *ap = adiv5_target_ap(t); struct cortexm_priv *priv = ap->priv; - uint32_t dhcsr = 0; + volatile uint32_t dhcsr = 0; volatile struct exception e; TRY_CATCH (e, EXCEPTION_ALL) { /* If this times out because the target is in WFI then -- cgit v1.2.3 From 97824b7f0230a5fe0e101a444d4ba7d6f625f01d Mon Sep 17 00:00:00 2001 From: Gareth McMullin Date: Fri, 3 Apr 2015 20:21:33 -0700 Subject: Use git describe for version in generated header file. --- .gitignore | 1 + scripts/setlocalversion | 82 --------------------------------- src/Makefile | 15 +++--- src/command.c | 5 +- src/platforms/f4discovery/Makefile.inc | 1 - src/platforms/f4discovery/platform.h | 5 +- src/platforms/launchpad-icdi/platform.h | 6 ++- src/platforms/libftdi/platform.c | 6 +++ src/platforms/native/Makefile.inc | 1 - src/platforms/stlink/Makefile.inc | 1 - src/platforms/stlink/platform.h | 7 +-- src/platforms/swlink/Makefile.inc | 1 - src/platforms/swlink/platform.h | 7 +-- 13 files changed, 33 insertions(+), 105 deletions(-) delete mode 100755 scripts/setlocalversion (limited to 'src') diff --git a/.gitignore b/.gitignore index 162d624..a40d44d 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +src/include/version.h blackmagic *.bin *.hex diff --git a/scripts/setlocalversion b/scripts/setlocalversion deleted file mode 100755 index 46989b8..0000000 --- a/scripts/setlocalversion +++ /dev/null @@ -1,82 +0,0 @@ -#!/bin/sh -# -# This scripts adds local version information from the version -# control systems git, mercurial (hg) and subversion (svn). -# -# If something goes wrong, send a mail the kernel build mailinglist -# (see MAINTAINERS) and CC Nico Schottelius -# . -# -# - -usage() { - echo "Usage: $0 [srctree]" >&2 - exit 1 -} - -cd "${1:-.}" || usage - -# Check for git and a git repo. -if head=`git rev-parse --verify --short HEAD 2>/dev/null`; then - - # If we are at a tagged commit (like "v2.6.30-rc6"), we ignore it, - # because this version is defined in the top level Makefile. - if [ -z "`git describe --exact-match 2>/dev/null`" ]; then - - # If we are past a tagged commit (like "v2.6.30-rc5-302-g72357d5"), - # we pretty print it. - if atag="`git describe 2>/dev/null`"; then - echo "$atag" | awk -F- '{printf("-%05d-%s", $(NF-1),$(NF))}' - - # If we don't have a tag at all we print -g{commitish}. - else - printf '%s%s' -g $head - fi - fi - - # Is this git on svn? - if git config --get svn-remote.svn.url >/dev/null; then - printf -- '-svn%s' "`git svn find-rev $head`" - fi - - # Update index only on r/w media - [ -w . ] && git update-index --refresh --unmerged > /dev/null - - # Check for uncommitted changes - if git diff-index --name-only HEAD | grep -v "^scripts/package" \ - | read dummy; then - printf '%s' -dirty - fi - - # All done with git - exit -fi - -# Check for mercurial and a mercurial repo. -if hgid=`hg id 2>/dev/null`; then - tag=`printf '%s' "$hgid" | cut -d' ' -f2` - - # Do we have an untagged version? - if [ -z "$tag" -o "$tag" = tip ]; then - id=`printf '%s' "$hgid" | sed 's/[+ ].*//'` - printf '%s%s' -hg "$id" - fi - - # Are there uncommitted changes? - # These are represented by + after the changeset id. - case "$hgid" in - *+|*+\ *) printf '%s' -dirty ;; - esac - - # All done with mercurial - exit -fi - -# Check for svn and a svn repo. -if rev=`svn info 2>/dev/null | grep '^Last Changed Rev'`; then - rev=`echo $rev | awk '{print $NF}'` - printf -- '-svn%s' "$rev" - - # All done with svn - exit -fi diff --git a/src/Makefile b/src/Makefile index 80e86fe..d1dc7f9 100644 --- a/src/Makefile +++ b/src/Makefile @@ -7,12 +7,9 @@ MAKEFLAGS += --no-print-dir Q := @ endif -BUILDDATE := `date +"%Y%m%d"` - CFLAGS += -Wall -Wextra -Wno-char-subscripts\ - -O2 -std=gnu99 -g3 -DBUILDDATE=\"$(BUILDDATE)\"\ + -O2 -std=gnu99 -g3 -MD \ -I. -Iinclude -Iplatforms/common -I$(PLATFORM_DIR) \ - -DVERSION_SUFFIX=\"`../scripts/setlocalversion`\" -MD SRC = \ adiv5.c \ @@ -49,9 +46,9 @@ include $(PLATFORM_DIR)/Makefile.inc OBJ = $(SRC:.c=.o) -blackmagic: $(OBJ) +blackmagic: include/version.h $(OBJ) @echo " LD $@" - $(Q)$(CC) -o $@ $^ $(LDFLAGS) + $(Q)$(CC) -o $@ $(OBJ) $(LDFLAGS) %.o: %.c @echo " CC $<" @@ -65,7 +62,7 @@ blackmagic: $(OBJ) @echo " OBJCOPY $@" $(Q)$(OBJCOPY) -O ihex $^ $@ -.PHONY: clean host_clean all_platforms +.PHONY: clean host_clean all_platforms FORCE clean: host_clean $(Q)echo " CLEAN" @@ -86,5 +83,9 @@ all_platforms: fi ;\ done +include/version.h: FORCE + $(Q)echo " GIT include/version.h" + $(Q)echo "#define FIRMWARE_VERSION \"`git describe --dirty`\"" > $@ + -include *.d diff --git a/src/command.c b/src/command.c index f271085..64e4ed6 100644 --- a/src/command.c +++ b/src/command.c @@ -29,6 +29,7 @@ #include "target.h" #include "morse.h" #include "adiv5.h" +#include "version.h" #ifdef PLATFORM_HAS_TRACESWO # include "traceswo.h" @@ -106,8 +107,8 @@ int command_process(target *t, char *cmd) bool cmd_version(void) { - gdb_out("Black Magic Probe (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")\n"); - gdb_out("Copyright (C) 2011 Black Sphere Technologies Ltd.\n"); + gdb_out("Black Magic Probe (Firmware " FIRMWARE_VERSION ")\n"); + gdb_out("Copyright (C) 2015 Black Sphere Technologies Ltd.\n"); gdb_out("License GPLv3+: GNU GPL version 3 or later " "\n\n"); diff --git a/src/platforms/f4discovery/Makefile.inc b/src/platforms/f4discovery/Makefile.inc index e2bebfd..e57bb0e 100644 --- a/src/platforms/f4discovery/Makefile.inc +++ b/src/platforms/f4discovery/Makefile.inc @@ -16,7 +16,6 @@ LDFLAGS = -lopencm3_stm32f4 -Wl,--defsym,_stack=0x20006000 \ VPATH += platforms/stm32 SRC += cdcacm.c \ - platform.c \ traceswo.c \ usbuart.c \ serialno.c \ diff --git a/src/platforms/f4discovery/platform.h b/src/platforms/f4discovery/platform.h index 3c5c582..300a3c1 100644 --- a/src/platforms/f4discovery/platform.h +++ b/src/platforms/f4discovery/platform.h @@ -28,12 +28,13 @@ #include "gpio.h" #include "morse.h" #include "timing.h" +#include "version.h" #include #define PLATFORM_HAS_TRACESWO -#define BOARD_IDENT "Black Magic Probe (F4Discovery), (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" -#define BOARD_IDENT_DFU "Black Magic (Upgrade) for F4Discovery, (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" +#define BOARD_IDENT "Black Magic Probe (F4Discovery), (Firmware " FIRMWARE_VERSION ")" +#define BOARD_IDENT_DFU "Black Magic (Upgrade) for F4Discovery, (Firmware " FIRMWARE_VERSION ")" #define DFU_IDENT "Black Magic Firmware Upgrade (F4Discovery" #define DFU_IFACE_STRING "@Internal Flash /0x08000000/1*016Ka,3*016Kg,1*064Kg,7*128Kg" diff --git a/src/platforms/launchpad-icdi/platform.h b/src/platforms/launchpad-icdi/platform.h index eb3ac6e..dc2efcf 100644 --- a/src/platforms/launchpad-icdi/platform.h +++ b/src/platforms/launchpad-icdi/platform.h @@ -24,8 +24,10 @@ #include #include -#define BOARD_IDENT "Black Magic Probe (Launchpad ICDI), (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" -#define BOARD_IDENT_DFU "Black Magic (Upgrade) for Launchpad, (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" +#include "version.h" + +#define BOARD_IDENT "Black Magic Probe (Launchpad ICDI), (Firmware " FIRMWARE_VERSION ")" +#define BOARD_IDENT_DFU "Black Magic (Upgrade) for Launchpad, (Firmware " FIRMWARE_VERSION ")" #define DFU_IDENT "Black Magic Firmware Upgrade (Launchpad)" #define DFU_IFACE_STRING "lolwut" diff --git a/src/platforms/libftdi/platform.c b/src/platforms/libftdi/platform.c index 634090d..0f16263 100644 --- a/src/platforms/libftdi/platform.c +++ b/src/platforms/libftdi/platform.c @@ -19,6 +19,7 @@ */ #include "general.h" #include "gdb_if.h" +#include "version.h" #include @@ -157,6 +158,11 @@ void platform_init(int argc, char **argv) if(cable_desc[index].cbus_ddr) ftdi_init[8]= cable_desc[index].cbus_ddr; + printf("\nBlack Magic Probe (" FIRMWARE_VERSION ")\n"); + printf("Copyright (C) 2015 Black Sphere Technologies Ltd.\n"); + printf("License GPLv3+: GNU GPL version 3 or later " + "\n\n"); + if(ftdic) { ftdi_usb_close(ftdic); ftdi_free(ftdic); diff --git a/src/platforms/native/Makefile.inc b/src/platforms/native/Makefile.inc index 6ec60b1..8365555 100644 --- a/src/platforms/native/Makefile.inc +++ b/src/platforms/native/Makefile.inc @@ -15,7 +15,6 @@ LDFLAGS = $(LDFLAGS_BOOT) -Wl,-Ttext=0x8002000 VPATH += platforms/stm32 SRC += cdcacm.c \ - platform.c \ traceswo.c \ usbuart.c \ serialno.c \ diff --git a/src/platforms/stlink/Makefile.inc b/src/platforms/stlink/Makefile.inc index 40635cf..dd1ab41 100644 --- a/src/platforms/stlink/Makefile.inc +++ b/src/platforms/stlink/Makefile.inc @@ -15,7 +15,6 @@ LDFLAGS = $(LDFLAGS_BOOT) -Wl,-Ttext=0x8002000 VPATH += platforms/stm32 SRC += cdcacm.c \ - platform.c \ usbuart.c \ serialno.c \ timing.c \ diff --git a/src/platforms/stlink/platform.h b/src/platforms/stlink/platform.h index f026db3..c304db2 100644 --- a/src/platforms/stlink/platform.h +++ b/src/platforms/stlink/platform.h @@ -27,6 +27,7 @@ #include "gdb_packet.h" #include "gpio.h" #include "timing.h" +#include "version.h" #include #include @@ -34,9 +35,9 @@ #include -#define BOARD_IDENT "Black Magic Probe (STLINK), (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" -#define BOARD_IDENT_DFU "Black Magic (Upgrade) for STLink/Discovery, (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" -#define BOARD_IDENT_UPD "Black Magic (DFU Upgrade) for STLink/Discovery, (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" +#define BOARD_IDENT "Black Magic Probe (STLINK), (Firmware " FIRMWARE_VERSION ")" +#define BOARD_IDENT_DFU "Black Magic (Upgrade) for STLink/Discovery, (Firmware " FIRMWARE_VERSION ")" +#define BOARD_IDENT_UPD "Black Magic (DFU Upgrade) for STLink/Discovery, (Firmware " FIRMWARE_VERSION ")" #define DFU_IDENT "Black Magic Firmware Upgrade (STLINK)" #define DFU_IFACE_STRING "@Internal Flash /0x08000000/8*001Ka,56*001Kg" #define UPD_IFACE_STRING "@Internal Flash /0x08000000/8*001Kg" diff --git a/src/platforms/swlink/Makefile.inc b/src/platforms/swlink/Makefile.inc index ca793d4..8899471 100644 --- a/src/platforms/swlink/Makefile.inc +++ b/src/platforms/swlink/Makefile.inc @@ -15,7 +15,6 @@ LDFLAGS = $(LDFLAGS_BOOT) -Wl,-Ttext=0x8002000 VPATH += platforms/stm32 SRC += cdcacm.c \ - platform.c \ usbuart.c \ serialno.c \ timing.c \ diff --git a/src/platforms/swlink/platform.h b/src/platforms/swlink/platform.h index 27cc299..ffa35cf 100644 --- a/src/platforms/swlink/platform.h +++ b/src/platforms/swlink/platform.h @@ -27,12 +27,13 @@ #include "gdb_packet.h" #include "gpio.h" #include "timing.h" +#include "version.h" #include -#define BOARD_IDENT "Black Magic Probe (SWLINK), (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" -#define BOARD_IDENT_DFU "Black Magic (Upgrade), STM8S Discovery, (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" -#define BOARD_IDENT_UPD "Black Magic (DFU Upgrade), STM8S Discovery, (Firmware 1.5" VERSION_SUFFIX ", build " BUILDDATE ")" +#define BOARD_IDENT "Black Magic Probe (SWLINK), (Firmware " FIRMWARE_VERSION ")" +#define BOARD_IDENT_DFU "Black Magic (Upgrade), STM8S Discovery, (Firmware " FIRMWARE_VERSION ")" +#define BOARD_IDENT_UPD "Black Magic (DFU Upgrade), STM8S Discovery, (Firmware " FIRMWARE_VERSION ")" #define DFU_IDENT "Black Magic Firmware Upgrade (SWLINK)" #define DFU_IFACE_STRING "@Internal Flash /0x08000000/8*001Ka,56*001Kg" #define UPD_IFACE_STRING "@Internal Flash /0x08000000/8*001Kg" -- cgit v1.2.3