/* Copyright (C) 2011 DJ Delorie This file 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, or (at your option) any later version. This file 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 file; see the file COPYING3. If not see . */ #include #include #include #include #include #include "iodefine.h" #include "cprintf.h" #include "timer.h" #include "osboard.h" /* 30 16k blocks from 0xfff80000 through 0xffff7fff erase block EB08 through EB37 8 4k blocks from 0xffff8000 through 0xffffffff */ #define BLOCK (0xffff0000UL) #define word unsigned short unsigned char fstat_erase; unsigned char fstat_prog; static int __attribute__((section(".data"),noinline)) fail (int line, int val) { int i; while (1) { LED = line; for (i=10000000; i; i--) asm("nop"); LED = val; for (i=10000000; i; i--) asm("nop"); LED = 0; for (i=10000000; i; i--) asm("nop"); } } #define FAIL(x) fail(__LINE__,x) #define WAIT() while (FLASH.FSTATR0.BIT.FRDY == 0) ; \ if (FLASH.FSTATR0.BYTE != 0x80) FAIL (FLASH.FSTATR0.BYTE) int __attribute__((section(".data"),noinline)) program_block (uint16_t *buffer, volatile uint16_t *rom) { int i; int len; int rv = -1; volatile uint8_t *flash; volatile uint16_t *flashw; asm("clrpsw I"); rom = (volatile uint16_t *)((unsigned long)rom & 0x00ffffffUL); flash = (uint8_t *)rom; flashw = (uint16_t *)rom; FLASH.FENTRYR.WORD = 0xAA00; asm("nop"); asm("nop"); FLASH.FENTRYR.WORD = 0xAA01; asm("nop"); asm("nop"); FLASH.FWEPROR.BYTE = 0x01; i = FLASH.FENTRYR.WORD; if (!(i & 1)) FAIL (i); /* peripheral clock notification */ FLASH.PCKAR.WORD = 48; *flash = 0xe9; *flash = 0x03; *flashw = 0x0f0f; *flashw = 0x0f0f; *flashw = 0x0f0f; *flash = 0xd0; WAIT(); *flash = 0xff; /* disable lock bit protection */ FLASH.FPROTR.WORD = 0x5501; if (FLASH.FPROTR.WORD != 0x0001) FAIL (FLASH.FPROTR.WORD); /* Erase block */ *flash = 0x20; *flash = 0xd0; WAIT(); fstat_erase = FLASH.FSTATR1.BYTE; *flash = 0xff; len = 16384; while (len > 0) { /* Program block */ *flash = 0xe8; *flash = 0x80; for (i=0; i<256/sizeof(uint16_t); i++) { *rom = *buffer; rom ++; buffer ++; } *flash = 0xd0; len -= 256; WAIT(); fstat_prog = FLASH.FSTATR1.BYTE; *flash = 0xff; } *flash = 0x70; rv = *flash; *flash = 0xff; FLASH.FENTRYR.WORD = 0x0000; FLASH.FWEPROR.BYTE = 0x02; asm("setpsw I"); return rv; } static uint8_t buf[16384]; dump_rom (uint8_t *ptr, char *msg) { int i; printf("ROM dump of %08p: %s:", ptr, msg); for (i=0; i<16; i++) printf(" %02x", ptr[i]); printf("\n"); } main() { int i = 0; int j; int fstatus; osboard_init (); wait_ms (10); tty_puts("OSBoard FLASH tests\n"); /* Disable FCU interrupts */ FLASH.FRDYIE.BIT.FRDYIE = 0; /* Disable FCU interrupts in FCU block */ FLASH.FAEINT.BIT.ROMAEIE = 0; FLASH.FAEINT.BIT.CMDLKIE = 0; FLASH.FAEINT.BIT.DFLAEIE = 0; FLASH.FAEINT.BIT.DFLRPEIE = 0; FLASH.FAEINT.BIT.DFLWPEIE = 0; /* Disable FCU interrupts in ICU */ /* Disable flash interface error (FIFERR) */ IPR(FCU, FIFERR) = 0; IEN(FCU, FIFERR) = 0; /* Disable flash ready interrupt (FRDYI) */ IPR(FCU, FRDYI) = 0; IEN(FCU, FRDYI) = 0; /* Copy FCU firmware to FCU ram */ FLASH.FENTRYR.WORD = 0x0000; FLASH.FCURAME.WORD = 0xc401; { volatile uint32_t *src = (volatile uint32_t *)0xfeffe000UL; volatile uint32_t *end = (volatile uint32_t *)0xfeffffffUL; volatile uint32_t *dest = (volatile uint32_t *)0x007f8000UL; while (src < end) *dest++ = *src++; } for (i=0; i<255; i++) buf[i] = i; dump_rom ((uint8_t *)BLOCK, "before"); /* Here we program 16k of data in BUF to the flash at address BLOCK. */ fstatus = program_block ((uint16_t *)buf, (uint16_t *)BLOCK); printf("fstatus = 0x%x %02x %02x\n", fstatus, fstat_erase, fstat_prog); dump_rom ((uint8_t *)BLOCK, "after "); /* This is "exit" for uflash. */ tty_putc(3); tty_putc(3); tty_putc(0); i = 0; while (1) { LED = i; i <<= 1; if (i == 0) i = 0xfe; } }