-#define AT91C_EFC_FCMD_GETD (0x0) // (EFC) Get Flash Descriptor
-#define AT91C_EFC_FCMD_WP (0x1) // (EFC) Write Page
-#define AT91C_EFC_FCMD_WPL (0x2) // (EFC) Write Page and Lock
-#define AT91C_EFC_FCMD_EWP (0x3) // (EFC) Erase Page and Write Page
-#define AT91C_EFC_FCMD_EWPL (0x4) // (EFC) Erase Page and Write Page then Lock
-#define AT91C_EFC_FCMD_EA (0x5) // (EFC) Erase All
-// cmd6 is not present int he at91sam3u4/2/1 data sheet table 17-2
-// #define AT91C_EFC_FCMD_EPL (0x6) // (EFC) Erase plane?
-// cmd7 is not present int he at91sam3u4/2/1 data sheet table 17-2
-// #define AT91C_EFC_FCMD_EPA (0x7) // (EFC) Erase pages?
-#define AT91C_EFC_FCMD_SLB (0x8) // (EFC) Set Lock Bit
-#define AT91C_EFC_FCMD_CLB (0x9) // (EFC) Clear Lock Bit
-#define AT91C_EFC_FCMD_GLB (0xA) // (EFC) Get Lock Bit
-#define AT91C_EFC_FCMD_SFB (0xB) // (EFC) Set Fuse Bit
-#define AT91C_EFC_FCMD_CFB (0xC) // (EFC) Clear Fuse Bit
-#define AT91C_EFC_FCMD_GFB (0xD) // (EFC) Get Fuse Bit
-#define AT91C_EFC_FCMD_STUI (0xE) // (EFC) Start Read Unique ID
-#define AT91C_EFC_FCMD_SPUI (0xF) // (EFC) Stop Read Unique ID
+#define AT91C_EFC_FCMD_GETD (0x0) /* (EFC) Get Flash Descriptor */
+#define AT91C_EFC_FCMD_WP (0x1) /* (EFC) Write Page */
+#define AT91C_EFC_FCMD_WPL (0x2) /* (EFC) Write Page and Lock */
+#define AT91C_EFC_FCMD_EWP (0x3) /* (EFC) Erase Page and Write Page */
+#define AT91C_EFC_FCMD_EWPL (0x4) /* (EFC) Erase Page and Write Page
+ * then Lock */
+#define AT91C_EFC_FCMD_EA (0x5) /* (EFC) Erase All */
+/* cmd6 is not present int he at91sam3u4/2/1 data sheet table 17-2 */
+/* #define AT91C_EFC_FCMD_EPL (0x6) // (EFC) Erase plane? */
+/* cmd7 is not present int he at91sam3u4/2/1 data sheet table 17-2 */
+/* #define AT91C_EFC_FCMD_EPA (0x7) // (EFC) Erase pages? */
+#define AT91C_EFC_FCMD_SLB (0x8) /* (EFC) Set Lock Bit */
+#define AT91C_EFC_FCMD_CLB (0x9) /* (EFC) Clear Lock Bit */
+#define AT91C_EFC_FCMD_GLB (0xA) /* (EFC) Get Lock Bit */
+#define AT91C_EFC_FCMD_SFB (0xB) /* (EFC) Set Fuse Bit */
+#define AT91C_EFC_FCMD_CFB (0xC) /* (EFC) Clear Fuse Bit */
+#define AT91C_EFC_FCMD_GFB (0xD) /* (EFC) Get Fuse Bit */
+#define AT91C_EFC_FCMD_STUI (0xE) /* (EFC) Start Read Unique ID */
+#define AT91C_EFC_FCMD_SPUI (0xF) /* (EFC) Stop Read Unique ID */
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK0_BASE_U,
- .controller_address = 0x400e0800,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 128 * 1024,
- .nsectors = 16,
- .sector_size = 8192,
- .page_size = 256,
- },
-
-// .bank[1] = {
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 1,
- .base_address = FLASH_BANK1_BASE_U,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 128 * 1024,
- .nsectors = 16,
- .sector_size = 8192,
- .page_size = 256,
- },
+ {
+ .probed = 0,
+ .pChip = NULL,
+ .pBank = NULL,
+ .bank_number = 0,
+ .base_address = FLASH_BANK0_BASE_U,
+ .controller_address = 0x400e0800,
+ .flash_wait_states = 6, /* workaround silicon bug */
+ .present = 1,
+ .size_bytes = 128 * 1024,
+ .nsectors = 16,
+ .sector_size = 8192,
+ .page_size = 256,
+ },
+
+/* .bank[1] = { */
+ {
+ .probed = 0,
+ .pChip = NULL,
+ .pBank = NULL,
+ .bank_number = 1,
+ .base_address = FLASH_BANK1_BASE_U,
+ .controller_address = 0x400e0a00,
+ .flash_wait_states = 6, /* workaround silicon bug */
+ .present = 1,
+ .size_bytes = 128 * 1024,
+ .nsectors = 16,
+ .sector_size = 8192,
+ .page_size = 256,
+ },
- {
-// .bank[0] = {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 0,
- .base_address = FLASH_BANK0_BASE_U,
- .controller_address = 0x400e0800,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 128 * 1024,
- .nsectors = 16,
- .sector_size = 8192,
- .page_size = 256,
- },
-// .bank[1] = {
- {
- .probed = 0,
- .pChip = NULL,
- .pBank = NULL,
- .bank_number = 1,
- .base_address = FLASH_BANK1_BASE_U,
- .controller_address = 0x400e0a00,
- .flash_wait_states = 6, /* workaround silicon bug */
- .present = 1,
- .size_bytes = 128 * 1024,
- .nsectors = 16,
- .sector_size = 8192,
- .page_size = 256,
- },
+ {
+/* .bank[0] = { */
+ .probed = 0,
+ .pChip = NULL,
+ .pBank = NULL,
+ .bank_number = 0,
+ .base_address = FLASH_BANK0_BASE_U,
+ .controller_address = 0x400e0800,
+ .flash_wait_states = 6, /* workaround silicon bug */
+ .present = 1,
+ .size_bytes = 128 * 1024,
+ .nsectors = 16,
+ .sector_size = 8192,
+ .page_size = 256,
+ },
+/* .bank[1] = { */
+ {
+ .probed = 0,
+ .pChip = NULL,
+ .pBank = NULL,
+ .bank_number = 1,
+ .base_address = FLASH_BANK1_BASE_U,
+ .controller_address = 0x400e0a00,
+ .flash_wait_states = 6, /* workaround silicon bug */
+ .present = 1,
+ .size_bytes = 128 * 1024,
+ .nsectors = 16,
+ .sector_size = 8192,
+ .page_size = 256,
+ },
- do_retry:
-
- // Check command & argument
- switch (command) {
-
- case AT91C_EFC_FCMD_WP:
- case AT91C_EFC_FCMD_WPL:
- case AT91C_EFC_FCMD_EWP:
- case AT91C_EFC_FCMD_EWPL:
- // case AT91C_EFC_FCMD_EPL:
- // case AT91C_EFC_FCMD_EPA:
- case AT91C_EFC_FCMD_SLB:
- case AT91C_EFC_FCMD_CLB:
- n = (pPrivate->size_bytes / pPrivate->page_size);
- if (argument >= n) {
- LOG_ERROR("*BUG*: Embedded flash has only %u pages", (unsigned)(n));
- }
- break;
+do_retry:
+
+ /* Check command & argument */
+ switch (command) {
+
+ case AT91C_EFC_FCMD_WP:
+ case AT91C_EFC_FCMD_WPL:
+ case AT91C_EFC_FCMD_EWP:
+ case AT91C_EFC_FCMD_EWPL:
+ /* case AT91C_EFC_FCMD_EPL: */
+ /* case AT91C_EFC_FCMD_EPA: */
+ case AT91C_EFC_FCMD_SLB:
+ case AT91C_EFC_FCMD_CLB:
+ n = (pPrivate->size_bytes / pPrivate->page_size);
+ if (argument >= n)
+ LOG_ERROR("*BUG*: Embedded flash has only %u pages", (unsigned)(n));
+ break;
- case AT91C_EFC_FCMD_SFB:
- case AT91C_EFC_FCMD_CFB:
- if (argument >= pPrivate->pChip->details.n_gpnvms) {
- LOG_ERROR("*BUG*: Embedded flash has only %d GPNVMs",
- pPrivate->pChip->details.n_gpnvms);
- }
- break;
-
- case AT91C_EFC_FCMD_GETD:
- case AT91C_EFC_FCMD_EA:
- case AT91C_EFC_FCMD_GLB:
- case AT91C_EFC_FCMD_GFB:
- case AT91C_EFC_FCMD_STUI:
- case AT91C_EFC_FCMD_SPUI:
- if (argument != 0) {
- LOG_ERROR("Argument is meaningless for cmd: %d", command);
- }
- break;
- default:
- LOG_ERROR("Unknown command %d", command);
- break;
- }
+ case AT91C_EFC_FCMD_SFB:
+ case AT91C_EFC_FCMD_CFB:
+ if (argument >= pPrivate->pChip->details.n_gpnvms) {
+ LOG_ERROR("*BUG*: Embedded flash has only %d GPNVMs",
+ pPrivate->pChip->details.n_gpnvms);
+ }
+ break;
+
+ case AT91C_EFC_FCMD_GETD:
+ case AT91C_EFC_FCMD_EA:
+ case AT91C_EFC_FCMD_GLB:
+ case AT91C_EFC_FCMD_GFB:
+ case AT91C_EFC_FCMD_STUI:
+ case AT91C_EFC_FCMD_SPUI:
+ if (argument != 0)
+ LOG_ERROR("Argument is meaningless for cmd: %d", command);
+ break;
+ default:
+ LOG_ERROR("Unknown command %d", command);
+ break;
+ }
- { 0x19, "AT91SAM9xx Series" },
- { 0x29, "AT91SAM9XExx Series" },
- { 0x34, "AT91x34 Series" },
- { 0x37, "CAP7 Series" },
- { 0x39, "CAP9 Series" },
- { 0x3B, "CAP11 Series" },
- { 0x40, "AT91x40 Series" },
- { 0x42, "AT91x42 Series" },
- { 0x55, "AT91x55 Series" },
- { 0x60, "AT91SAM7Axx Series" },
- { 0x61, "AT91SAM7AQxx Series" },
- { 0x63, "AT91x63 Series" },
- { 0x70, "AT91SAM7Sxx Series" },
- { 0x71, "AT91SAM7XCxx Series" },
- { 0x72, "AT91SAM7SExx Series" },
- { 0x73, "AT91SAM7Lxx Series" },
- { 0x75, "AT91SAM7Xxx Series" },
- { 0x76, "AT91SAM7SLxx Series" },
- { 0x80, "ATSAM3UxC Series (100-pin version)" },
- { 0x81, "ATSAM3UxE Series (144-pin version)" },
- { 0x83, "ATSAM3AxC Series (100-pin version)" },
- { 0x84, "ATSAM3XxC Series (100-pin version)" },
- { 0x85, "ATSAM3XxE Series (144-pin version)" },
- { 0x86, "ATSAM3XxG Series (208/217-pin version)" },
- { 0x88, "ATSAM3SxA Series (48-pin version)" },
- { 0x89, "ATSAM3SxB Series (64-pin version)" },
- { 0x8A, "ATSAM3SxC Series (100-pin version)" },
- { 0x92, "AT91x92 Series" },
- { 0xF0, "AT75Cxx Series" },
+ { 0x19, "AT91SAM9xx Series" },
+ { 0x29, "AT91SAM9XExx Series" },
+ { 0x34, "AT91x34 Series" },
+ { 0x37, "CAP7 Series" },
+ { 0x39, "CAP9 Series" },
+ { 0x3B, "CAP11 Series" },
+ { 0x40, "AT91x40 Series" },
+ { 0x42, "AT91x42 Series" },
+ { 0x55, "AT91x55 Series" },
+ { 0x60, "AT91SAM7Axx Series" },
+ { 0x61, "AT91SAM7AQxx Series" },
+ { 0x63, "AT91x63 Series" },
+ { 0x70, "AT91SAM7Sxx Series" },
+ { 0x71, "AT91SAM7XCxx Series" },
+ { 0x72, "AT91SAM7SExx Series" },
+ { 0x73, "AT91SAM7Lxx Series" },
+ { 0x75, "AT91SAM7Xxx Series" },
+ { 0x76, "AT91SAM7SLxx Series" },
+ { 0x80, "ATSAM3UxC Series (100-pin version)" },
+ { 0x81, "ATSAM3UxE Series (144-pin version)" },
+ { 0x83, "ATSAM3AxC Series (100-pin version)" },
+ { 0x84, "ATSAM3XxC Series (100-pin version)" },
+ { 0x85, "ATSAM3XxE Series (144-pin version)" },
+ { 0x86, "ATSAM3XxG Series (208/217-pin version)" },
+ { 0x88, "ATSAM3SxA Series (48-pin version)" },
+ { 0x89, "ATSAM3SxB Series (64-pin version)" },
+ { 0x8A, "ATSAM3SxC Series (100-pin version)" },
+ { 0x92, "AT91x92 Series" },
+ { 0xF0, "AT75Cxx Series" },
- SAM3_ENTRY(CKGR_MOR , sam3_explain_ckgr_mor),
- SAM3_ENTRY(CKGR_MCFR , sam3_explain_ckgr_mcfr),
- SAM3_ENTRY(CKGR_PLLAR , sam3_explain_ckgr_plla),
- SAM3_ENTRY(CKGR_UCKR , NULL),
- SAM3_ENTRY(PMC_FSMR , NULL),
- SAM3_ENTRY(PMC_FSPR , NULL),
- SAM3_ENTRY(PMC_IMR , NULL),
- SAM3_ENTRY(PMC_MCKR , sam3_explain_mckr),
- SAM3_ENTRY(PMC_PCK0 , NULL),
- SAM3_ENTRY(PMC_PCK1 , NULL),
- SAM3_ENTRY(PMC_PCK2 , NULL),
- SAM3_ENTRY(PMC_PCSR , NULL),
- SAM3_ENTRY(PMC_SCSR , NULL),
- SAM3_ENTRY(PMC_SR , NULL),
- SAM3_ENTRY(CHIPID_CIDR , sam3_explain_chipid_cidr),
- SAM3_ENTRY(CHIPID_EXID , NULL),
+ SAM3_ENTRY(CKGR_MOR, sam3_explain_ckgr_mor),
+ SAM3_ENTRY(CKGR_MCFR, sam3_explain_ckgr_mcfr),
+ SAM3_ENTRY(CKGR_PLLAR, sam3_explain_ckgr_plla),
+ SAM3_ENTRY(CKGR_UCKR, NULL),
+ SAM3_ENTRY(PMC_FSMR, NULL),
+ SAM3_ENTRY(PMC_FSPR, NULL),
+ SAM3_ENTRY(PMC_IMR, NULL),
+ SAM3_ENTRY(PMC_MCKR, sam3_explain_mckr),
+ SAM3_ENTRY(PMC_PCK0, NULL),
+ SAM3_ENTRY(PMC_PCK1, NULL),
+ SAM3_ENTRY(PMC_PCK2, NULL),
+ SAM3_ENTRY(PMC_PCSR, NULL),
+ SAM3_ENTRY(PMC_SCSR, NULL),
+ SAM3_ENTRY(PMC_SR, NULL),
+ SAM3_ENTRY(CHIPID_CIDR, sam3_explain_chipid_cidr),
+ SAM3_ENTRY(CHIPID_EXID, NULL),
- default:
- LOG_ERROR("Address 0x%08x invalid bank address (try 0x%08x or 0x%08x \
- [at91sam3u series] or 0x%08x [at91sam3s series] or \
- 0x%08x [at91sam3n series])",
- ((unsigned int)(bank->base)),
- ((unsigned int)(FLASH_BANK0_BASE_U)),
- ((unsigned int)(FLASH_BANK1_BASE_U)),
- ((unsigned int)(FLASH_BANK_BASE_S)),
- ((unsigned int)(FLASH_BANK_BASE_N)));
- return ERROR_FAIL;
- break;
-
- // at91sam3u series
- case FLASH_BANK0_BASE_U:
- bank->driver_priv = &(pChip->details.bank[0]);
- bank->bank_number = 0;
- pChip->details.bank[0].pChip = pChip;
- pChip->details.bank[0].pBank = bank;
- break;
- case FLASH_BANK1_BASE_U:
- bank->driver_priv = &(pChip->details.bank[1]);
- bank->bank_number = 1;
- pChip->details.bank[1].pChip = pChip;
- pChip->details.bank[1].pBank = bank;
- break;
-
- /* at91sam3s and at91sam3n series */
- case FLASH_BANK_BASE_S:
- bank->driver_priv = &(pChip->details.bank[0]);
- bank->bank_number = 0;
- pChip->details.bank[0].pChip = pChip;
- pChip->details.bank[0].pBank = bank;
- break;
- }
-
- // we initialize after probing.
+ default:
+ LOG_ERROR("Address 0x%08x invalid bank address (try 0x%08x or 0x%08x "
+ "[at91sam3u series] or 0x%08x [at91sam3s series] or "
+ "0x%08x [at91sam3n series])",
+ ((unsigned int)(bank->base)),
+ ((unsigned int)(FLASH_BANK0_BASE_U)),
+ ((unsigned int)(FLASH_BANK1_BASE_U)),
+ ((unsigned int)(FLASH_BANK_BASE_S)),
+ ((unsigned int)(FLASH_BANK_BASE_N)));
+ return ERROR_FAIL;
+ break;
+
+ /* at91sam3u series */
+ case FLASH_BANK0_BASE_U:
+ bank->driver_priv = &(pChip->details.bank[0]);
+ bank->bank_number = 0;
+ pChip->details.bank[0].pChip = pChip;
+ pChip->details.bank[0].pBank = bank;
+ break;
+ case FLASH_BANK1_BASE_U:
+ bank->driver_priv = &(pChip->details.bank[1]);
+ bank->bank_number = 1;
+ pChip->details.bank[1].pChip = pChip;
+ pChip->details.bank[1].pBank = bank;
+ break;
+
+ /* at91sam3s and at91sam3n series */
+ case FLASH_BANK_BASE_S:
+ bank->driver_priv = &(pChip->details.bank[0]);
+ bank->bank_number = 0;
+ pChip->details.bank[0].pChip = pChip;
+ pChip->details.bank[0].pBank = bank;
+ break;
+ }
+
+ /* we initialize after probing. */
-// The code below is basically this:
-// compiled with
-// arm-none-eabi-gcc -mthumb -mcpu = cortex-m3 -O9 -S ./foobar.c -o foobar.s
-//
-// Only the *CPU* can write to the flash buffer.
-// the DAP cannot... so - we download this 28byte thing
-// Run the algorithm - (below)
-// to program the device
-//
-// ========================================
-// #include <stdint.h>
-//
-// struct foo {
-// uint32_t *dst;
-// const uint32_t *src;
-// int n;
-// volatile uint32_t *base;
-// uint32_t cmd;
-// };
-//
-//
-// uint32_t sam3_function(struct foo *p)
-// {
-// volatile uint32_t *v;
-// uint32_t *d;
-// const uint32_t *s;
-// int n;
-// uint32_t r;
-//
-// d = p->dst;
-// s = p->src;
-// n = p->n;
-//
-// do {
-// *d++ = *s++;
-// } while (--n)
-// ;
-//
-// v = p->base;
-//
-// v[ 1 ] = p->cmd;
-// do {
-// r = v[8/4];
-// } while (!(r&1))
-// ;
-// return r;
-// }
-// ========================================
-
-
+/* The code below is basically this: */
+/* compiled with */
+/* arm-none-eabi-gcc -mthumb -mcpu = cortex-m3 -O9 -S ./foobar.c -o foobar.s */
+/* */
+/* Only the *CPU* can write to the flash buffer. */
+/* the DAP cannot... so - we download this 28byte thing */
+/* Run the algorithm - (below) */
+/* to program the device */
+/* */
+/* ======================================== */
+/* #include <stdint.h> */
+/* */
+/* struct foo { */
+/* uint32_t *dst; */
+/* const uint32_t *src; */
+/* int n; */
+/* volatile uint32_t *base; */
+/* uint32_t cmd; */
+/* }; */
+/* */
+/* */
+/* uint32_t sam3_function(struct foo *p) */
+/* { */
+/* volatile uint32_t *v; */
+/* uint32_t *d; */
+/* const uint32_t *s; */
+/* int n; */
+/* uint32_t r; */
+/* */
+/* d = p->dst; */
+/* s = p->src; */
+/* n = p->n; */
+/* */
+/* do { */
+/* *d++ = *s++; */
+/* } while (--n) */
+/* ; */
+/* */
+/* v = p->base; */
+/* */
+/* v[ 1 ] = p->cmd; */
+/* do { */
+/* r = v[8/4]; */
+/* } while (!(r&1)) */
+/* ; */
+/* return r; */
+/* } */
+/* ======================================== */
-sam3_page_write_opcodes[] = {
- // 24 0000 0446 mov r4, r0
- 0x04,0x46,
- // 25 0002 6168 ldr r1, [r4, #4]
- 0x61,0x68,
- // 26 0004 0068 ldr r0, [r0, #0]
- 0x00,0x68,
- // 27 0006 A268 ldr r2, [r4, #8]
- 0xa2,0x68,
- // 28 @ lr needed for prologue
- // 29 .L2:
- // 30 0008 51F8043B ldr r3, [r1], #4
- 0x51,0xf8,0x04,0x3b,
- // 31 000c 12F1FF32 adds r2, r2, #-1
- 0x12,0xf1,0xff,0x32,
- // 32 0010 40F8043B str r3, [r0], #4
- 0x40,0xf8,0x04,0x3b,
- // 33 0014 F8D1 bne .L2
- 0xf8,0xd1,
- // 34 0016 E268 ldr r2, [r4, #12]
- 0xe2,0x68,
- // 35 0018 2369 ldr r3, [r4, #16]
- 0x23,0x69,
- // 36 001a 5360 str r3, [r2, #4]
- 0x53,0x60,
- // 37 001c 0832 adds r2, r2, #8
- 0x08,0x32,
- // 38 .L4:
- // 39 001e 1068 ldr r0, [r2, #0]
- 0x10,0x68,
- // 40 0020 10F0010F tst r0, #1
- 0x10,0xf0,0x01,0x0f,
- // 41 0024 FBD0 beq .L4
- 0xfb,0xd0,
- 0x00,0xBE /* bkpt #0 */
+ sam3_page_write_opcodes[] = {
+ /* 24 0000 0446 mov r4, r0 */
+ 0x04, 0x46,
+ /* 25 0002 6168 ldr r1, [r4, #4] */
+ 0x61, 0x68,
+ /* 26 0004 0068 ldr r0, [r0, #0] */
+ 0x00, 0x68,
+ /* 27 0006 A268 ldr r2, [r4, #8] */
+ 0xa2, 0x68,
+ /* 28 @ lr needed for prologue */
+ /* 29 .L2: */
+ /* 30 0008 51F8043B ldr r3, [r1], #4 */
+ 0x51, 0xf8, 0x04, 0x3b,
+ /* 31 000c 12F1FF32 adds r2, r2, #-1 */
+ 0x12, 0xf1, 0xff, 0x32,
+ /* 32 0010 40F8043B str r3, [r0], #4 */
+ 0x40, 0xf8, 0x04, 0x3b,
+ /* 33 0014 F8D1 bne .L2 */
+ 0xf8, 0xd1,
+ /* 34 0016 E268 ldr r2, [r4, #12] */
+ 0xe2, 0x68,
+ /* 35 0018 2369 ldr r3, [r4, #16] */
+ 0x23, 0x69,
+ /* 36 001a 5360 str r3, [r2, #4] */
+ 0x53, 0x60,
+ /* 37 001c 0832 adds r2, r2, #8 */
+ 0x08, 0x32,
+ /* 38 .L4: */
+ /* 39 001e 1068 ldr r0, [r2, #0] */
+ 0x10, 0x68,
+ /* 40 0020 10F0010F tst r0, #1 */
+ 0x10, 0xf0, 0x01, 0x0f,
+ /* 41 0024 FBD0 beq .L4 */
+ 0xfb, 0xd0,
+ 0x00, 0xBE /* bkpt #0 */