{"action":"created","comment":{"url":"https://api.github.com/repos/blacksphere/blackmagic/pulls/comments/26007938","id":26007938,"diff_hunk":"@@ -0,0 +1,1076 @@\n+/*\n+ * This file is part of the Black Magic Debug project.\n+ *\n+ * Copyright (C) 2014,2015 Marc Singer <elf@woollysoft.com>\n+ *\n+ * This program is free software: you can redistribute it and/or modify\n+ * it under the terms of the GNU General Public License as published by\n+ * the Free Software Foundation, either version 3 of the License, or\n+ * (at your option) any later version.\n+ *\n+ * This program is distributed in the hope that it will be useful,\n+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\n+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n+ * GNU General Public License for more details.\n+ *\n+ * You should have received a copy of the GNU General Public License\n+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.\n+ */\n+\n+/* Description\n+   -----------\n+\n+   This is an implementation of the target-specific functions for the\n+   STM32L0x[1] and STM32L1x[2] families of ST Microelectronics MCUs,\n+   Cortex M0+ SOCs.  The NVM interface is substantially similar to the\n+   STM32L1x parts.  This module is written to better generalize the\n+   NVM interface and to provide more features.\n+\n+   [1] ST Microelectronics Document RM0377 (DocID025942), \"Reference\n+       manual for Ultra-low-power STM32L0x1 advanced ARM-based 32-bit\n+       MCUs,\" April 2014.\n+\n+   [2] ST Microelectronics Document RM0038 (DocID15965, \"...\"Reference\n+       manual for STM32L100xx, STM32L151xx, STM32L152xx and STM32L162xx\n+       advanced ARM®-based 32-bit MCUs, \" July 2014\n+\n+\n+   NOTES\n+   =====\n+\n+   o Stubbed and non-stubbed NVM operation functions.  The STM32L0xx\n+     appears to behave differently from other STM32 cores.  When it\n+     enters a fault state it will not exit this state without a\n+     reset.  However, the reset will immediately enter a fault state\n+     if program flash is erased.  When in this state, it will not\n+     permit execution of code in RAM in the way that other cores\n+     will.  Changing the PC to the start of RAM and single stepping\n+     will immediately HardFault.\n+\n+     The stub functions can be both faster and simpler because they\n+     have direct access to the MCU.  So, to permit stub operation in\n+     the best circumstances, the NVM operation functions will check\n+     the MCU state and either execute the stub or non-stub version\n+     accordingly. The user can override stubs as well with a command\n+     in case the detection feature fails.\n+\n+   o Erase would be more efficient if we checked for non-blank-ness\n+     before initiating an erase.  This would have to be done in a stub\n+     for efficiency.\n+\n+   o Mass erase broken.  The method for performing a mass erase is to\n+     set the options for read protection, reload the option bytes, set\n+     options for no protection, and then reload the option bytes\n+     again.  The command fails because we lose contact with the target\n+     when we perform the option byte reload.  For the time being, the\n+     command is disabled.\n+\n+   o Errors.  We probably should clear SR errors immediately after\n+     detecting them.  If we don't then we always must wait for the NVM\n+     module to complete the last operation before we can start another.\n+\n+   o There are minor inconsistencies between the stm32l0 and the\n+     stm32l1 in when handling NVM operations.\n+\n+     o When we erase or write individual words (not half-pages) on the\n+       stm32l0, we set the PROG bit.  On the stm32l1 the PROG bit is\n+       only set when erasing.  This  is not documented in the register\n+       summaries, but in the functional quick reference.\n+\n+     o On the STM32L1xx, PECR can only be changed when the NVM\n+       hardware is idle.  The STM32L0xx allows the PECR to be updated\n+       while an operation is in progress.\n+\n+   o Performance.  The throughput for writing is not high.  We suspect\n+     it may be possible to improve throughput significantly by increasing\n+     the MCU clock.  The code, as is, offers a simplicity without\n+     undue knowledge of the inner workings of the MCUs.  Increasing\n+     clock frequencies would require substantial knowledge of the\n+     clock tree.\n+\n+  0x1ff80000: 0x00aa 0xff55 OK\n+  0x1ff80004: 0x8070 0x7f8f OK\n+  0x1ff80008: 0x0000 0xffff OK\n+  OPTR: 0x807000aa, RDPROT 0, WPRMOD 0, WDG_SW 1, BOOT1 1\n+\n+\n+    Options code\n+p *(int*)0x40022004 = 1\n+p *(int*)0x4002200c = 0x89abcdef\n+p *(int*)0x4002200c = 0x02030405\n+p *(int*)0x40022014 = 0xfbead9c8\n+p *(int*)0x40022014 = 0x24252627\n+p *(int*)0x40022004 = 0x10\n+x/4wx 0x40022000\n+p *(int*)0x1ff80000 = 0xff5500aa\n+\n+  l1 program\n+p *(int*)0x40023c04 = 1\n+p *(int*)0x40023c0c = 0x89abcdef\n+p *(int*)0x40023c0c = 0x02030405\n+p *(int*)0x40023c10 = 0x8c9daebf\n+p *(int*)0x40023c10 = 0x13141516\n+\n+\n+p *(int*)0x40023c14 = 0xfbead9c8\n+p *(int*)0x40023c14 = 0x24252627\n+\n+*/\n+\n+#define CONFIG_STM32L1          /* Include support for STM32L1 */\n+\n+#include <stdlib.h>\n+#include <string.h>\n+#include <stdint.h>\n+\n+#include \"general.h\"\n+#include \"adiv5.h\"\n+#include \"target.h\"\n+#include \"command.h\"\n+\n+#include \"stm32lx-nvm.h\"\n+\n+static int inhibit_stubs;\n+\n+static int stm32lx_nvm_erase (struct target_s* target,\n+                              uint32_t addr, int len);\n+static int stm32lx_nvm_write (struct target_s* target,\n+                              uint32_t destination,\n+                              const uint8_t* source,\n+                              int size);\n+\n+static int stm32lx_nvm_prog_erase (struct target_s* target,\n+                                   uint32_t addr, int len);\n+static int stm32lx_nvm_prog_write (struct target_s* target,\n+                                   uint32_t destination,\n+                                   const uint8_t* source,\n+                                   int size);\n+\n+static int stm32lx_nvm_prog_erase_stubbed (struct target_s* target,\n+                                           uint32_t addr, int len);\n+static int stm32lx_nvm_prog_write_stubbed (struct target_s* target,\n+                                           uint32_t destination,\n+                                           const uint8_t* source,\n+                                           int size);\n+\n+static int stm32lx_nvm_data_erase (struct target_s* target,\n+                                   uint32_t addr, int len);\n+static int stm32lx_nvm_data_write (struct target_s* target,\n+                                   uint32_t destination,\n+                                   const uint8_t* source,\n+                                   int size);\n+\n+//static bool stm32l0_cmd_erase_mass (target* t, int argc, char** argv);\n+static bool stm32lx_cmd_option     (target* t, int argc, char** argv);\n+static bool stm32lx_cmd_eeprom     (target* t, int argc, char** argv);\n+//static bool stm32l0_cmd_reset      (target* t, int argc, char** argv);\n+static bool stm32lx_cmd_stubs      (target* t, int argc, char** argv);\n+\n+static const struct command_s stm32lx_cmd_list[] = {\n+  { \"stubs\",\t\t(cmd_handler) stm32lx_cmd_stubs,\n+    \"Enable/disable NVM operation stubs\" },\n+//  { \"erase_mass\",\t(cmd_handler) stm32l0_cmd_erase_mass,\n+//    \"Erase NVM flash and data\" },\n+//  { \"reset\",\t\t(cmd_handler) stm32l0_cmd_reset, \"Reset target\" },\n+  { \"option\",\t\t(cmd_handler) stm32lx_cmd_option,\n+    \"Manipulate option bytes\"},\n+  { \"eeprom\",\t\t(cmd_handler) stm32lx_cmd_eeprom,\n+    \"Manipulate EEPROM (NVM data) memory\"},\n+  { 0 },\n+};\n+\n+enum {\n+  STM32L0_DBGMCU_IDCODE_PHYS = 0x40015800,\n+  STM32L1_DBGMCU_IDCODE_PHYS = 0xe0042000,\n+};\n+\n+static const char stm32l0_driver_str[] = \"STM32L0xx\";\n+\n+static const char stm32l0_xml_memory_map[] = \"<?xml version=\\\"1.0\\\"?>\"\n+/* \"<!DOCTYPE memory-map \"\n+   \"             PUBLIC \\\"+//IDN gnu.org//DTD GDB Memory Map V1.0//EN\\\"\"\n+   \"                    \\\"http://sourceware.org/gdb/gdb-memory-map.dtd\\\">\"*/\n+\t\"<memory-map>\"\n+  /* Program flash; ranges up to 64KiB (0x10000). */\n+\t\"  <memory type=\\\"flash\\\" start=\\\"0x08000000\\\" length=\\\"0x10000\\\">\"\n+\t\"    <property name=\\\"blocksize\\\">0x80</property>\"\n+\t\"  </memory>\"\n+  /* Data (EEPROM) NVRAM; ranges up to 2KiB (0x800). */\n+\t\"  <memory type=\\\"flash\\\" start=\\\"0x08080000\\\" length=\\\"0x800\\\">\"\n+\t\"    <property name=\\\"blocksize\\\">0x4</property>\"\n+\t\"  </memory>\"\n+  /* SRAM; ranges up to 8KiB (0x2000). */\n+\t\"  <memory type=\\\"ram\\\" start=\\\"0x20000000\\\" length=\\\"0x2000\\\"/>\"\n+\t\"</memory-map>\";\n+\n+#if defined (CONFIG_STM32L1)\n+static const char stm32l1_driver_str[] = \"STM32L1xx\";\n+\n+static const char stm32l1_xml_memory_map[] = \"<?xml version=\\\"1.0\\\"?>\"\n+/* \"<!DOCTYPE memory-map \"\n+   \"             PUBLIC \\\"+//IDN gnu.org//DTD GDB Memory Map V1.0//EN\\\"\"\n+   \"                    \\\"http://sourceware.org/gdb/gdb-memory-map.dtd\\\">\"*/\n+\t\"<memory-map>\"\n+  /* Program flash; ranges from 32KiB to 512KiB (0x80000). */\n+\t\"  <memory type=\\\"flash\\\" start=\\\"0x08000000\\\" length=\\\"0x80000\\\">\"\n+\t\"    <property name=\\\"blocksize\\\">0x100</property>\"\n+\t\"  </memory>\"\n+  /* Data (EEPROM) NVRAM; ranges from 2K to 16KiB (0x4000). */\n+\t\"  <memory type=\\\"flash\\\" start=\\\"0x08080000\\\" length=\\\"0x4000\\\">\"\n+\t\"    <property name=\\\"blocksize\\\">0x4</property>\"\n+\t\"  </memory>\"\n+  /* SRAM; ranges from 4KiB to 80KiB (0x14000). */\n+\t\"  <memory type=\\\"ram\\\" start=\\\"0x20000000\\\" length=\\\"0x14000\\\"/>\"\n+\t\"</memory-map>\";\n+#endif\n+\n+static const uint16_t stm32l0_nvm_prog_write_stub [] = {\n+#include \"../flashstub/stm32l05x-nvm-prog-write.stub\"\n+};\n+\n+static const uint16_t stm32l0_nvm_prog_erase_stub [] = {\n+#include \"../flashstub/stm32l05x-nvm-prog-erase.stub\"\n+};\n+\n+static uint32_t stm32lx_nvm_prog_page_size (struct target_s* target)\n+{\n+  switch (target->idcode) {\n+  case 0x417:                   /* STM32L0xx */\n+    return STM32L0_NVM_PROG_PAGE_SIZE;\n+  default:                      /* STM32L1xx */\n+    return STM32L1_NVM_PROG_PAGE_SIZE;\n+  }\n+}\n+\n+static bool stm32lx_is_stm32l1 (struct target_s* target)\n+{\n+  switch (target->idcode) {\n+  case 0x417:                   /* STM32L0xx */\n+    return false;\n+  default:                      /* STM32L1xx */\n+    return true;\n+  }\n+}\n+\n+static uint32_t stm32lx_nvm_eeprom_size (struct target_s* target)\n+{\n+  switch (target->idcode) {\n+  case 0x417:                   /* STM32L0xx */\n+    return STM32L0_NVM_EEPROM_SIZE;\n+  default:                      /* STM32L1xx */\n+    return STM32L1_NVM_EEPROM_SIZE;\n+  }\n+}\n+\n+static uint32_t stm32lx_nvm_phys (struct target_s* target)\n+{\n+  switch (target->idcode) {\n+  case 0x417:                   /* STM32L0xx */\n+    return STM32L0_NVM_PHYS;\n+  default:                      /* STM32L1xx */\n+    return STM32L1_NVM_PHYS;\n+  }\n+}\n+\n+static uint32_t stm32lx_nvm_data_page_size (struct target_s* target)\n+{\n+  switch (target->idcode) {\n+  case 0x417:                   /* STM32L0xx */\n+    return STM32L0_NVM_DATA_PAGE_SIZE;\n+  default:                      /* STM32L1xx */\n+    return STM32L1_NVM_DATA_PAGE_SIZE;\n+  }\n+}\n+\n+static uint32_t stm32lx_nvm_option_size (struct target_s* target)\n+{\n+  switch (target->idcode) {\n+  case 0x417:                   /* STM32L0xx */\n+    return STM32L0_NVM_OPT_SIZE;\n+  default:                      /* STM32L1xx */\n+    return STM32L1_NVM_OPT_SIZE;\n+  }\n+}\n+\n+/** Query MCU memory for an indication as to whether or not the\n+    currently attached target is served by this module.  We detect the\n+    STM32L0xx parts as well as the STM32L1xx's. */\n+bool stm32l0_probe (struct target_s* target)\n+{\n+  uint32_t idcode;\n+\n+#if defined (CONFIG_STM32L1)\n+\n+  idcode = adiv5_ap_mem_read (adiv5_target_ap (target),\n+                              STM32L1_DBGMCU_IDCODE_PHYS) & 0xfff;\n+  switch (idcode) {\n+  case 0x416:                   /* CAT. 1 device */\n+  case 0x429:                   /* CAT. 2 device */\n+  case 0x427:                   /* CAT. 3 device */\n+  case 0x436:                   /* CAT. 4 device */\n+  case 0x437:                   /* CAT. 5 device  */\n+    target->idcode         = idcode;\n+    target->driver         = stm32l1_driver_str;\n+    target->xml_mem_map    = stm32l1_xml_memory_map;\n+    target->flash_erase    = stm32lx_nvm_erase;\n+    target->flash_write    = stm32lx_nvm_write;\n+    target_add_commands (target, stm32lx_cmd_list, \"STM32L1x\");\n+    return true;\n+  }\n+#endif\n+\n+  idcode = adiv5_ap_mem_read (adiv5_target_ap (target),\n+                              STM32L0_DBGMCU_IDCODE_PHYS) & 0xfff;\n+  switch (idcode) {\n+  default:\n+    break;\n+\n+  case 0x417:                   /* STM32L0x[123] & probably others */\n+    target->idcode         = idcode;\n+    target->driver         = stm32l0_driver_str;\n+    target->xml_mem_map    = stm32l0_xml_memory_map;\n+    target->flash_erase    = stm32lx_nvm_erase;\n+    target->flash_write    = stm32lx_nvm_write;\n+    target_add_commands (target, stm32lx_cmd_list, \"STM32L0x\");\n+    return true;\n+  }\n+\n+  return false;\n+}\n+\n+/** Lock the NVM control registers preventing writes or erases. */\n+static void stm32lx_nvm_lock (ADIv5_AP_t* ap, uint32_t nvm)\n+{\n+  adiv5_ap_mem_write (ap, STM32Lx_NVM_PECR(nvm), STM32Lx_NVM_PECR_PELOCK);\n+}\n+\n+/** Unlock the NVM control registers for modifying program or\n+    data flash.  Returns true if the unlock succeeds. */\n+static bool stm32lx_nvm_prog_data_unlock (ADIv5_AP_t* ap, uint32_t nvm)\n+{\n+  /* Always lock first because that's the only way to know that the\n+     unlock can succeed on the STM32L0's. */\n+  adiv5_ap_mem_write (ap, STM32Lx_NVM_PECR(nvm),    STM32Lx_NVM_PECR_PELOCK);\n+  adiv5_ap_mem_write (ap, STM32Lx_NVM_PEKEYR(nvm),  STM32Lx_NVM_PEKEY1);\n+  adiv5_ap_mem_write (ap, STM32Lx_NVM_PEKEYR(nvm),  STM32Lx_NVM_PEKEY2);\n+  adiv5_ap_mem_write (ap, STM32Lx_NVM_PRGKEYR(nvm), STM32Lx_NVM_PRGKEY1);\n+  adiv5_ap_mem_write (ap, STM32Lx_NVM_PRGKEYR(nvm), STM32Lx_NVM_PRGKEY2);\n+\n+  return !(adiv5_ap_mem_read (ap, STM32Lx_NVM_PECR(nvm))\n+           & STM32Lx_NVM_PECR_PRGLOCK);\n+}\n+\n+\n+/** Unlock the NVM control registers for modifying option bytes.\n+    Returns true if the unlock succeeds. */\n+static bool stm32lx_nvm_opt_unlock (ADIv5_AP_t* ap, uint32_t nvm)\n+{\n+  /* Always lock first because that's the only way to know that the\n+     unlock can succeed on the STM32L0's. */\n+  adiv5_ap_mem_write (ap, STM32Lx_NVM_PECR(nvm),    STM32Lx_NVM_PECR_PELOCK);\n+  adiv5_ap_mem_write (ap, STM32Lx_NVM_PEKEYR(nvm),  STM32Lx_NVM_PEKEY1);\n+  adiv5_ap_mem_write (ap, STM32Lx_NVM_PEKEYR(nvm),  STM32Lx_NVM_PEKEY2);\n+  adiv5_ap_mem_write (ap, STM32Lx_NVM_OPTKEYR(nvm), STM32Lx_NVM_OPTKEY1);\n+  adiv5_ap_mem_write (ap, STM32Lx_NVM_OPTKEYR(nvm), STM32Lx_NVM_OPTKEY2);\n+\n+  return !(adiv5_ap_mem_read (ap, STM32Lx_NVM_PECR(nvm))\n+           & STM32Lx_NVM_PECR_OPTLOCK);\n+}\n+\n+\n+/** Erase a region of flash using a stub function.  This only works\n+    when the MCU hasn't entered a fault state (see NOTES).  The flash\n+    array is erased for all pages from addr to addr+len inclusive. */\n+static int stm32lx_nvm_prog_erase_stubbed (struct target_s* target,\n+                                           uint32_t addr, int size)\n+{\n+  struct stm32lx_nvm_stub_info info;\n+  const uint32_t nvm = stm32lx_nvm_phys (target);\n+\n+  info.nvm       = nvm;\n+  info.page_size = stm32lx_nvm_prog_page_size (target);\n+\n+  /* Load the stub */\n+  target_mem_write_words (target, STM32Lx_STUB_PHYS,\n+                          (void*) &stm32l0_nvm_prog_erase_stub[0],\n+                          sizeof (stm32l0_nvm_prog_erase_stub));\n+\n+  /* Setup parameters */\n+  info.destination = addr;\n+  info.size        = size;\n+\n+  /* Copy parameters */\n+  target_mem_write_words (target, STM32Lx_STUB_INFO_PHYS,\n+                          (void*) &info, sizeof (info));\n+\n+  /* Execute stub */\n+  target_pc_write (target, STM32Lx_STUB_PHYS);\n+  if (target_check_error (target))\n+    return -1;\n+  target_halt_resume (target, 0);\n+  while (!target_halt_wait (target))\n+    ;\n+  {\n+    ADIv5_AP_t* ap = adiv5_target_ap(target);\n+    if (adiv5_ap_mem_read (ap, STM32Lx_NVM_SR(nvm)) & STM32Lx_NVM_SR_ERR_M)\n+      return -1;\n+  }\n+\n+  return 0;\n+}\n+\n+\n+/** Write to program flash using a stub function.  This only works\n+    when the MCU hasn't entered a fault state.  Once the MCU faults,\n+    this function will not succeed because the MCU will fault before\n+    executing a single instruction in the stub. */\n+static int stm32lx_nvm_prog_write_stubbed (struct target_s* target,\n+                                           uint32_t destination,\n+                                           const uint8_t* source,\n+                                           int size)\n+{\n+  struct stm32lx_nvm_stub_info info;\n+  const uint32_t nvm = stm32lx_nvm_phys (target);\n+  const size_t page_size = stm32lx_nvm_prog_page_size (target);\n+\n+  /* We can't handle unaligned destination or non-word writes. */\n+  /* *** FIXME: we should handle misaligned writes by padding with\n+     *** zeros.  Probably, the only real time we'd see something\n+     *** misaligned would be on a write to a final half-word.  Perhaps\n+     *** this could be handled with the stub?  In fact, aligning the\n+     *** start is going to be mandatory.  We will change the code to\n+     *** cope with a trailing half-word. */\n+  if ((destination & 3) || (size & 3))\n+    return -1;","path":"src/stm32l0.c","position":444,"original_position":444,"commit_id":"362884e279ab04b8a0cc761317cfb6247f5606ba","original_commit_id":"362884e279ab04b8a0cc761317cfb6247f5606ba","user":{"login":"beewoolie","id":319183,"avatar_url":"https://avatars.githubusercontent.com/u/319183?v=3","gravatar_id":"","url":"https://api.github.com/users/beewoolie","html_url":"https://github.com/beewoolie","followers_url":"https://api.github.com/users/beewoolie/followers","following_url":"https://api.github.com/users/beewoolie/following{/other_user}","gists_url":"https://api.github.com/users/beewoolie/gists{/gist_id}","starred_url":"https://api.github.com/users/beewoolie/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/beewoolie/subscriptions","organizations_url":"https://api.github.com/users/beewoolie/orgs","repos_url":"https://api.github.com/users/beewoolie/repos","events_url":"https://api.github.com/users/beewoolie/events{/privacy}","received_events_url":"https://api.github.com/users/beewoolie/received_events","type":"User","site_admin":false},"body":"\n\nOn 3/7/15 7:33 PM, zyp wrote:\n>\n> In src/stm32l0.c \n> <https://github.com/blacksphere/blackmagic/pull/75#discussion_r26001973>:\n>\n> > +                                           const uint8_t* source,\n> > +                                           int size)\n> > +{\n> > +  struct stm32lx_nvm_stub_info info;\n> > +  const uint32_t nvm = stm32lx_nvm_phys (target);\n> > +  const size_t page_size = stm32lx_nvm_prog_page_size (target);\n> > +\n> > +  /* We can't handle unaligned destination or non-word writes. */\n> > +  /* *** FIXME: we should handle misaligned writes by padding with\n> > +     *** zeros.  Probably, the only real time we'd see something\n> > +     *** misaligned would be on a write to a final half-word.  Perhaps\n> > +     *** this could be handled with the stub?  In fact, aligning the\n> > +     *** start is going to be mandatory.  We will change the code to\n> > +     *** cope with a trailing half-word. */\n> > +  if ((destination & 3) || (size & 3))\n> > +    return -1;\n>\n> Keep in mind that STM32L flash reads 0 when erased while STM32F flash \n> reads 1. The STM32F1 driver pads with ones, while this will have to \n> pad with zeros. You can also look to my old STM32L1 code for an example.\n>\n\nI know!  It's kinda strange that they changed this very long-standing \nconvention.\n","created_at":"2015-03-08T19:16:45Z","updated_at":"2015-03-08T19:16:45Z","html_url":"https://github.com/blacksphere/blackmagic/pull/75#discussion_r26007938","pull_request_url":"https://api.github.com/repos/blacksphere/blackmagic/pulls/75","_links":{"self":{"href":"https://api.github.com/repos/blacksphere/blackmagic/pulls/comments/26007938"},"html":{"href":"https://github.com/blacksphere/blackmagic/pull/75#discussion_r26007938"},"pull_request":{"href":"https://api.github.com/repos/blacksphere/blackmagic/pulls/75"}}},"pull_request":{"url":"https://api.github.com/repos/blacksphere/blackmagic/pulls/75","id":27979272,"html_url":"https://github.com/blacksphere/blackmagic/pull/75","diff_url":"https://github.com/blacksphere/blackmagic/pull/75.diff","patch_url":"https://github.com/blacksphere/blackmagic/pull/75.patch","issue_url":"https://api.github.com/repos/blacksphere/blackmagic/issues/75","number":75,"state":"open","locked":false,"title":"STM32Lx target support.","user":{"login":"beewoolie","id":319183,"avatar_url":"https://avatars.githubusercontent.com/u/319183?v=3","gravatar_id":"","url":"https://api.github.com/users/beewoolie","html_url":"https://github.com/beewoolie","followers_url":"https://api.github.com/users/beewoolie/followers","following_url":"https://api.github.com/users/beewoolie/following{/other_user}","gists_url":"https://api.github.com/users/beewoolie/gists{/gist_id}","starred_url":"https://api.github.com/users/beewoolie/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/beewoolie/subscriptions","organizations_url":"https://api.github.com/users/beewoolie/orgs","repos_url":"https://api.github.com/users/beewoolie/repos","events_url":"https://api.github.com/users/beewoolie/events{/privacy}","received_events_url":"https://api.github.com/users/beewoolie/received_events","type":"User","site_admin":false},"body":"Target support for stm32l0's and stm32l1's including option bytes and\r\ndata EEPROM.  This module will superceed the previous stm32l1 driver.\r\n\r\no Program flash write and erase.\r\no Options modification and interpretive status.\r\no Stubs for program flash writes and erases.  Stubs are modestly\r\n  faster than non-stub version.   The stm32l0 will not execute stubs\r\n  when the MCU has crashed.  A monitor option may be used to force\r\n  non-stub flash writes.\r\no Stubs generated from C++ code and converted to arrays of half-words.\r\no Writes to data EEPROM supoprted when loading segments.\r\no EEPROM data monitor command to write words.\r\no Stubs supported on stm32l1.","created_at":"2015-01-24T17:24:25Z","updated_at":"2015-03-08T19:16:45Z","closed_at":null,"merged_at":null,"merge_commit_sha":"10199c30329dc98ce5ce1ee73dc13082f87f39d4","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/blacksphere/blackmagic/pulls/75/commits","review_comments_url":"https://api.github.com/repos/blacksphere/blackmagic/pulls/75/comments","review_comment_url":"https://api.github.com/repos/blacksphere/blackmagic/pulls/comments{/number}","comments_url":"https://api.github.com/repos/blacksphere/blackmagic/issues/75/comments","statuses_url":"https://api.github.com/repos/blacksphere/blackmagic/statuses/362884e279ab04b8a0cc761317cfb6247f5606ba","head":{"label":"beewoolie:stm32lx-whole","ref":"stm32lx-whole","sha":"362884e279ab04b8a0cc761317cfb6247f5606ba","user":{"login":"beewoolie","id":319183,"avatar_url":"https://avatars.githubusercontent.com/u/319183?v=3","gravatar_id":"","url":"https://api.github.com/users/beewoolie","html_url":"https://github.com/beewoolie","followers_url":"https://api.github.com/users/beewoolie/followers","following_url":"https://api.github.com/users/beewoolie/following{/other_user}","gists_url":"https://api.github.com/users/beewoolie/gists{/gist_id}","starred_url":"https://api.github.com/users/beewoolie/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/beewoolie/subscriptions","organizations_url":"https://api.github.com/users/beewoolie/orgs","repos_url":"https://api.github.com/users/beewoolie/repos","events_url":"https://api.github.com/users/beewoolie/events{/privacy}","received_events_url":"https://api.github.com/users/beewoolie/received_events","type":"User","site_admin":false},"repo":{"id":12666199,"name":"blackmagic","full_name":"beewoolie/blackmagic","owner":{"login":"beewoolie","id":319183,"avatar_url":"https://avatars.githubusercontent.com/u/319183?v=3","gravatar_id":"","url":"https://api.github.com/users/beewoolie","html_url":"https://github.com/beewoolie","followers_url":"https://api.github.com/users/beewoolie/followers","following_url":"https://api.github.com/users/beewoolie/following{/other_user}","gists_url":"https://api.github.com/users/beewoolie/gists{/gist_id}","starred_url":"https://api.github.com/users/beewoolie/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/beewoolie/subscriptions","organizations_url":"https://api.github.com/users/beewoolie/orgs","repos_url":"https://api.github.com/users/beewoolie/repos","events_url":"https://api.github.com/users/beewoolie/events{/privacy}","received_events_url":"https://api.github.com/users/beewoolie/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/beewoolie/blackmagic","description":"In application debugger for ARM Cortex microcontrollers.","fork":true,"url":"https://api.github.com/repos/beewoolie/blackmagic","forks_url":"https://api.github.com/repos/beewoolie/blackmagic/forks","keys_url":"https://api.github.com/repos/beewoolie/blackmagic/keys{/key_id}","collaborators_url":"https://api.github.com/repos/beewoolie/blackmagic/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/beewoolie/blackmagic/teams","hooks_url":"https://api.github.com/repos/beewoolie/blackmagic/hooks","issue_events_url":"https://api.github.com/repos/beewoolie/blackmagic/issues/events{/number}","events_url":"https://api.github.com/repos/beewoolie/blackmagic/events","assignees_url":"https://api.github.com/repos/beewoolie/blackmagic/assignees{/user}","branches_url":"https://api.github.com/repos/beewoolie/blackmagic/branches{/branch}","tags_url":"https://api.github.com/repos/beewoolie/blackmagic/tags","blobs_url":"https://api.github.com/repos/beewoolie/blackmagic/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/beewoolie/blackmagic/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/beewoolie/blackmagic/git/refs{/sha}","trees_url":"https://api.github.com/repos/beewoolie/blackmagic/git/trees{/sha}","statuses_url":"https://api.github.com/repos/beewoolie/blackmagic/statuses/{sha}","languages_url":"https://api.github.com/repos/beewoolie/blackmagic/languages","stargazers_url":"https://api.github.com/repos/beewoolie/blackmagic/stargazers","contributors_url":"https://api.github.com/repos/beewoolie/blackmagic/contributors","subscribers_url":"https://api.github.com/repos/beewoolie/blackmagic/subscribers","subscription_url":"https://api.github.com/repos/beewoolie/blackmagic/subscription","commits_url":"https://api.github.com/repos/beewoolie/blackmagic/commits{/sha}","git_commits_url":"https://api.github.com/repos/beewoolie/blackmagic/git/commits{/sha}","comments_url":"https://api.github.com/repos/beewoolie/blackmagic/comments{/number}","issue_comment_url":"https://api.github.com/repos/beewoolie/blackmagic/issues/comments{/number}","contents_url":"https://api.github.com/repos/beewoolie/blackmagic/contents/{+path}","compare_url":"https://api.github.com/repos/beewoolie/blackmagic/compare/{base}...{head}","merges_url":"https://api.github.com/repos/beewoolie/blackmagic/merges","archive_url":"https://api.github.com/repos/beewoolie/blackmagic/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/beewoolie/blackmagic/downloads","issues_url":"https://api.github.com/repos/beewoolie/blackmagic/issues{/number}","pulls_url":"https://api.github.com/repos/beewoolie/blackmagic/pulls{/number}","milestones_url":"https://api.github.com/repos/beewoolie/blackmagic/milestones{/number}","notifications_url":"https://api.github.com/repos/beewoolie/blackmagic/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/beewoolie/blackmagic/labels{/name}","releases_url":"https://api.github.com/repos/beewoolie/blackmagic/releases{/id}","created_at":"2013-09-07T14:38:19Z","updated_at":"2015-01-24T06:11:43Z","pushed_at":"2015-01-24T17:23:29Z","git_url":"git://github.com/beewoolie/blackmagic.git","ssh_url":"git@github.com:beewoolie/blackmagic.git","clone_url":"https://github.com/beewoolie/blackmagic.git","svn_url":"https://github.com/beewoolie/blackmagic","homepage":"http://www.blacksphere.co.nz/main/blackmagic","size":1719,"stargazers_count":0,"watchers_count":0,"language":"C","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"blacksphere:master","ref":"master","sha":"a3ab9b24d1c3b4dd6678fc88289f0cf397e52c6c","user":{"login":"blacksphere","id":8303676,"avatar_url":"https://avatars.githubusercontent.com/u/8303676?v=3","gravatar_id":"","url":"https://api.github.com/users/blacksphere","html_url":"https://github.com/blacksphere","followers_url":"https://api.github.com/users/blacksphere/followers","following_url":"https://api.github.com/users/blacksphere/following{/other_user}","gists_url":"https://api.github.com/users/blacksphere/gists{/gist_id}","starred_url":"https://api.github.com/users/blacksphere/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/blacksphere/subscriptions","organizations_url":"https://api.github.com/users/blacksphere/orgs","repos_url":"https://api.github.com/users/blacksphere/repos","events_url":"https://api.github.com/users/blacksphere/events{/privacy}","received_events_url":"https://api.github.com/users/blacksphere/received_events","type":"Organization","site_admin":false},"repo":{"id":1335680,"name":"blackmagic","full_name":"blacksphere/blackmagic","owner":{"login":"blacksphere","id":8303676,"avatar_url":"https://avatars.githubusercontent.com/u/8303676?v=3","gravatar_id":"","url":"https://api.github.com/users/blacksphere","html_url":"https://github.com/blacksphere","followers_url":"https://api.github.com/users/blacksphere/followers","following_url":"https://api.github.com/users/blacksphere/following{/other_user}","gists_url":"https://api.github.com/users/blacksphere/gists{/gist_id}","starred_url":"https://api.github.com/users/blacksphere/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/blacksphere/subscriptions","organizations_url":"https://api.github.com/users/blacksphere/orgs","repos_url":"https://api.github.com/users/blacksphere/repos","events_url":"https://api.github.com/users/blacksphere/events{/privacy}","received_events_url":"https://api.github.com/users/blacksphere/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/blacksphere/blackmagic","description":"In application debugger for ARM Cortex microcontrollers.","fork":false,"url":"https://api.github.com/repos/blacksphere/blackmagic","forks_url":"https://api.github.com/repos/blacksphere/blackmagic/forks","keys_url":"https://api.github.com/repos/blacksphere/blackmagic/keys{/key_id}","collaborators_url":"https://api.github.com/repos/blacksphere/blackmagic/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/blacksphere/blackmagic/teams","hooks_url":"https://api.github.com/repos/blacksphere/blackmagic/hooks","issue_events_url":"https://api.github.com/repos/blacksphere/blackmagic/issues/events{/number}","events_url":"https://api.github.com/repos/blacksphere/blackmagic/events","assignees_url":"https://api.github.com/repos/blacksphere/blackmagic/assignees{/user}","branches_url":"https://api.github.com/repos/blacksphere/blackmagic/branches{/branch}","tags_url":"https://api.github.com/repos/blacksphere/blackmagic/tags","blobs_url":"https://api.github.com/repos/blacksphere/blackmagic/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/blacksphere/blackmagic/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/blacksphere/blackmagic/git/refs{/sha}","trees_url":"https://api.github.com/repos/blacksphere/blackmagic/git/trees{/sha}","statuses_url":"https://api.github.com/repos/blacksphere/blackmagic/statuses/{sha}","languages_url":"https://api.github.com/repos/blacksphere/blackmagic/languages","stargazers_url":"https://api.github.com/repos/blacksphere/blackmagic/stargazers","contributors_url":"https://api.github.com/repos/blacksphere/blackmagic/contributors","subscribers_url":"https://api.github.com/repos/blacksphere/blackmagic/subscribers","subscription_url":"https://api.github.com/repos/blacksphere/blackmagic/subscription","commits_url":"https://api.github.com/repos/blacksphere/blackmagic/commits{/sha}","git_commits_url":"https://api.github.com/repos/blacksphere/blackmagic/git/commits{/sha}","comments_url":"https://api.github.com/repos/blacksphere/blackmagic/comments{/number}","issue_comment_url":"https://api.github.com/repos/blacksphere/blackmagic/issues/comments{/number}","contents_url":"https://api.github.com/repos/blacksphere/blackmagic/contents/{+path}","compare_url":"https://api.github.com/repos/blacksphere/blackmagic/compare/{base}...{head}","merges_url":"https://api.github.com/repos/blacksphere/blackmagic/merges","archive_url":"https://api.github.com/repos/blacksphere/blackmagic/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/blacksphere/blackmagic/downloads","issues_url":"https://api.github.com/repos/blacksphere/blackmagic/issues{/number}","pulls_url":"https://api.github.com/repos/blacksphere/blackmagic/pulls{/number}","milestones_url":"https://api.github.com/repos/blacksphere/blackmagic/milestones{/number}","notifications_url":"https://api.github.com/repos/blacksphere/blackmagic/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/blacksphere/blackmagic/labels{/name}","releases_url":"https://api.github.com/repos/blacksphere/blackmagic/releases{/id}","created_at":"2011-02-06T21:57:26Z","updated_at":"2015-03-08T18:27:24Z","pushed_at":"2015-03-08T18:27:23Z","git_url":"git://github.com/blacksphere/blackmagic.git","ssh_url":"git@github.com:blacksphere/blackmagic.git","clone_url":"https://github.com/blacksphere/blackmagic.git","svn_url":"https://github.com/blacksphere/blackmagic","homepage":"http://www.blacksphere.co.nz/main/blackmagic","size":3590,"stargazers_count":67,"watchers_count":67,"language":"C","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":58,"mirror_url":null,"open_issues_count":12,"forks":58,"open_issues":12,"watchers":67,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/blacksphere/blackmagic/pulls/75"},"html":{"href":"https://github.com/blacksphere/blackmagic/pull/75"},"issue":{"href":"https://api.github.com/repos/blacksphere/blackmagic/issues/75"},"comments":{"href":"https://api.github.com/repos/blacksphere/blackmagic/issues/75/comments"},"review_comments":{"href":"https://api.github.com/repos/blacksphere/blackmagic/pulls/75/comments"},"review_comment":{"href":"https://api.github.com/repos/blacksphere/blackmagic/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/blacksphere/blackmagic/pulls/75/commits"},"statuses":{"href":"https://api.github.com/repos/blacksphere/blackmagic/statuses/362884e279ab04b8a0cc761317cfb6247f5606ba"}}}}