]> git.sur5r.net Git - openocd/blobdiff - contrib/loaders/flash/bluenrg-x/bluenrg-x_write.c
Added support for STMicroelectronics BlueNRG-1 and BlueNRG-2 SoC
[openocd] / contrib / loaders / flash / bluenrg-x / bluenrg-x_write.c
diff --git a/contrib/loaders/flash/bluenrg-x/bluenrg-x_write.c b/contrib/loaders/flash/bluenrg-x/bluenrg-x_write.c
new file mode 100644 (file)
index 0000000..3dd17b2
--- /dev/null
@@ -0,0 +1,132 @@
+/* To be built with arm-none-eabi-gcc -c -mthumb -mcpu=cortex-m0 -O3 bluenrgx.c */
+/* Then postprocess output of command "arm-none-eabi-objdump -d bluenrgx.o" to make a C array of bytes */
+
+#include <stdint.h>
+
+/* Status Values ----------------------------------------------------------*/
+#define SUCCESS             0
+#define ERR_UNALIGNED       1
+#define ERR_INVALID_ADDRESS 2
+#define ERR_INVALID_TYPE    3
+#define ERR_WRITE_PROTECTED 4
+#define ERR_WRITE_FAILED    5
+#define ERR_ERASE_REQUIRED  6
+#define ERR_VERIFY_FAILED   7
+
+/* Flash Controller defines ---------------------------------------------------*/
+#define FLASH_REG_COMMAND ((volatile uint32_t *)0x40100000)
+#define FLASH_REG_CONFIG  ((volatile uint32_t *)0x40100004)
+#define FLASH_REG_IRQSTAT ((volatile uint32_t *)0x40100008)
+#define FLASH_REG_IRQMASK ((volatile uint32_t *)0x4010000C)
+#define FLASH_REG_IRQRAW  ((volatile uint32_t *)0x40100010)
+#define FLASH_REG_ADDRESS ((volatile uint32_t *)0x40100018)
+#define FLASH_REG_UNLOCKM ((volatile uint32_t *)0x4010001C)
+#define FLASH_REG_UNLOCKL ((volatile uint32_t *)0x40100020)
+#define FLASH_REG_DATA0    ((volatile uint32_t *)0x40100040)
+#define FLASH_REG_DATA1    ((volatile uint32_t *)0x40100044)
+#define FLASH_REG_DATA2    ((volatile uint32_t *)0x40100048)
+#define FLASH_REG_DATA3    ((volatile uint32_t *)0x4010004C)
+#define FLASH_SIZE_REG 0x40100014
+
+#define MFB_MASS_ERASE 0x01
+#define MFB_PAGE_ERASE 0x02
+
+#define DO_ERASE  0x0100
+#define DO_VERIFY 0x0200
+#define FLASH_CMD_ERASE_PAGE 0x11
+#define FLASH_CMD_MASSERASE  0x22
+#define FLASH_CMD_WRITE      0x33
+#define FLASH_CMD_BURSTWRITE 0xCC
+#define FLASH_INT_CMDDONE    0x01
+#define MFB_BOTTOM          (0x10040000)
+#define MFB_SIZE_B          ((16 * (((*(uint32_t *) FLASH_SIZE_REG) + 1) >> 12)) * 1024)
+#define MFB_SIZE_W          (MFB_SIZE_B/4)
+#define MFB_TOP             (MFB_BOTTOM+MFB_SIZE_B-1)
+#define MFB_PAGE_SIZE_B     (2048)
+#define MFB_PAGE_SIZE_W     (MFB_PAGE_SIZE_B/4)
+
+#define AREA_ERROR 0x01
+#define AREA_MFB   0x04
+
+#define FLASH_WORD_LEN       4
+
+typedef struct {
+       volatile uint8_t *wp;
+       uint8_t *rp;
+} work_area_t;
+
+/* Flash Commands --------------------------------------------------------*/
+static inline __attribute__((always_inline)) uint32_t flashWrite(uint32_t address, uint8_t **data,
+                                                                uint32_t writeLength)
+{
+       uint32_t index, flash_word[4];
+       uint8_t i;
+
+       *FLASH_REG_IRQMASK = 0;
+       for (index = 0; index < writeLength; index += (FLASH_WORD_LEN*4)) {
+               for (i = 0; i < 4; i++)
+                       flash_word[i] = (*(uint32_t *) (*data + i*4));
+
+               /* Clear the IRQ flags */
+               *FLASH_REG_IRQRAW = 0x0000003F;
+               /* Load the flash address to write */
+               *FLASH_REG_ADDRESS = (uint16_t)((address + index) >> 2);
+               /* Prepare and load the data to flash */
+               *FLASH_REG_DATA0 = flash_word[0];
+               *FLASH_REG_DATA1 = flash_word[1];
+               *FLASH_REG_DATA2 = flash_word[2];
+               *FLASH_REG_DATA3 = flash_word[3];
+               /* Flash write command */
+               *FLASH_REG_COMMAND = FLASH_CMD_BURSTWRITE;
+               /* Wait the end of the flash write command */
+               while ((*FLASH_REG_IRQRAW & FLASH_INT_CMDDONE) == 0)
+                       ;
+               *data += (FLASH_WORD_LEN * 4);
+       }
+
+       return SUCCESS;
+}
+
+__attribute__((naked)) __attribute__((noreturn)) void write(uint8_t *work_area_p,
+                                                           uint8_t *fifo_end,
+                                                           uint8_t *target_address,
+                                                           uint32_t count)
+{
+       uint32_t retval;
+       volatile work_area_t *work_area = (work_area_t *) work_area_p;
+       uint8_t *fifo_start = (uint8_t *) work_area->rp;
+
+       while (count) {
+               volatile int32_t fifo_linear_size;
+
+               /* Wait for some data in the FIFO */
+               while (work_area->rp == work_area->wp)
+                       ;
+               if (work_area->wp == 0) {
+                       /* Aborted by other party */
+                       break;
+               }
+               if (work_area->rp > work_area->wp) {
+                       fifo_linear_size = fifo_end-work_area->rp;
+               } else {
+                       fifo_linear_size = (work_area->wp - work_area->rp);
+                       if (fifo_linear_size < 0)
+                               fifo_linear_size = 0;
+               }
+               if (fifo_linear_size < 16) {
+                       /* We should never get here */
+                       continue;
+               }
+
+               retval = flashWrite((uint32_t) target_address, (uint8_t **) &work_area->rp, fifo_linear_size);
+               if (retval != SUCCESS) {
+                       work_area->rp = (uint8_t *)retval;
+                       break;
+               }
+               target_address += fifo_linear_size;
+               if (work_area->rp >= fifo_end)
+                       work_area->rp = fifo_start;
+               count -= fifo_linear_size;
+       }
+       __asm("bkpt 0");
+}