From 5da509dc909c60d63c5fba98e7ced43040eb6827 Mon Sep 17 00:00:00 2001 From: hackbard Date: Sat, 8 Sep 2007 22:15:31 +0200 Subject: [PATCH] added low level flash support --- betty/Makefile | 4 +- betty/betty.c | 23 ++++- betty/betty.h | 21 +---- betty/buttons.c | 4 +- betty/display.c | 5 ++ betty/flash.c | 230 ++++++++++++++++++++++++++++++++++++++++++++++++ betty/flash.h | 46 ++++++++++ betty/lpc2xxx.h | 1 + betty/system.c | 3 +- betty/system.h | 2 +- betty/types.h | 16 ++++ 11 files changed, 326 insertions(+), 29 deletions(-) create mode 100644 betty/flash.c create mode 100644 betty/flash.h create mode 100644 betty/types.h diff --git a/betty/Makefile b/betty/Makefile index f740401..3883fce 100644 --- a/betty/Makefile +++ b/betty/Makefile @@ -19,7 +19,7 @@ HOST_TARGET = lpcload fwdump CROSS_TARGET = fwbc.hex fwflash.hex betty.hex # betty deps -BETTY_DEPS = system.o uart.o buttons.o spi.o display.o +BETTY_DEPS = system.o uart.o buttons.o spi.o display.o flash.o # all projects all: $(HOST_TARGET) $(CROSS_TARGET) @@ -41,7 +41,7 @@ arm: arm_clean $(CROSS_TARGET) # betty is special ;) betty.elf: betty.o startup.o $(BETTY_DEPS) - #$(CROSS_LD) $(CROSS_ROM_LDFLAGS) startup.o -o $@ $< + #$(CROSS_LD) $(CROSS_ROM_LDFLAGS) startup.o $(BETTY_DEPS) -o $@ $< $(CROSS_LD) $(CROSS_RAM_LDFLAGS) startup.o $(BETTY_DEPS) -o $@ $< # .hex out of .elf diff --git a/betty/betty.c b/betty/betty.c index 31bc5a2..45e6ae7 100644 --- a/betty/betty.c +++ b/betty/betty.c @@ -20,8 +20,9 @@ int main() { - char buf[]="betty - live from flash at 0x80000000! ;)\r\n"; + char announce[]="betty - live from flash at 0x80000000! ;)\r\n"; t_button button; + u32 addr; /* system init */ pll_init(); @@ -36,21 +37,37 @@ int main() { button_init(&button); button_set_retries(&button,100); + /* flash init */ + flash_init(); + /* * start it ... */ + /* pause - seems to not work if running from flash! (?) */ pause(0xffffff); + + /* announce */ + uart0_send_string(announce); + + /* toggle backlight */ bl_toggle(); + //addr=0x82000000; + flash_sector_erase(BANK2,0); + addr=FLASH_BANK2; + while(1) { pause(0x0fffff); /* button test! */ if(button_get_event(&button)) { - uart0_send_string(buf); - if(button.key[0]==BUTTON_POWER) + uart0_send_string(announce); + if(button.key[0]==BUTTON_POWER) { bl_toggle(); + flash_write_buf(addr,(u16 *)announce,42); + addr+=64; + } } } diff --git a/betty/betty.h b/betty/betty.h index 41b3687..33e64d5 100644 --- a/betty/betty.h +++ b/betty/betty.h @@ -24,31 +24,12 @@ #include "buttons.h" #include "spi.h" #include "display.h" +#include "flash.h" /* * defines */ -/* bank 0/2 and boootloader addr/size */ -#define BANK0 0x80000000 -#define BANK1 0x81000000 -#define BANK2 0x82000000 -#define BANK_SIZE 0x00100000 -#define BOOTLOADER 0x7fffe000 -#define BL_SIZE 0x00002000 - -/* flash cmd addresses - flash[0-18] <--> arm[1-19]*/ -#define B0F555 (*((volatile unsigned short *)(BANK0|0xaaa))) // 0x555 -#define B0F2AA (*((volatile unsigned short *)(BANK0|0x554))) // 0x2aa -#define B0F (*((volatile unsigned short *)(BANK0))) -#define B2F555 (*((volatile unsigned short *)(BANK2|0xaaa))) // 0x555 -#define B2F2AA (*((volatile unsigned short *)(BANK2|0x554))) // 0x2aa -#define B2F (*((volatile unsigned short *)(BANK2))) - -/* lcd command and data addresses */ -#define LCD_CMD (*((volatile unsigned char *)(BANK1))) -#define LCD_DATA (*((volatile unsigned char *)(BANK1+1))) - /* * function prototypes */ diff --git a/betty/buttons.c b/betty/buttons.c index 9eb99b5..21efe01 100644 --- a/betty/buttons.c +++ b/betty/buttons.c @@ -26,10 +26,10 @@ void button_init(t_button *button) { PINSEL0&=~((1<<27)|(1<<26)); // p0.13 // ctrl databus for p2.18 - p2.24 - PINSEL2&=(PINSEL2&(~((1<<5)|(1<<4))))|(1<<4); + PINSEL2=(PINSEL2&P2MASK&~((1<<5)|(1<<4)))|(1<<4); // ctrl addr bus for p3.20, p3.21 - PINSEL2=(PINSEL2&(~((1<<27)|(1<<26)|(1<<25))))|(1<<27)|(1<<26); + PINSEL2=(PINSEL2&P2MASK&~((1<<27)|(1<<26)|(1<<25)))|(1<<27)|(1<<26); // input IODIR0&=~((1<<30)|(1<<28)|(1<<27)|(1<<22)|(1<<13)); diff --git a/betty/display.c b/betty/display.c index a5db338..07fb923 100644 --- a/betty/display.c +++ b/betty/display.c @@ -11,6 +11,11 @@ * functions */ +void display_init(void) { + + BCFG1=0x00000c42; +} + void bl_init(void) { PINSEL0&=~(1<<9|(1<<8)); diff --git a/betty/flash.c b/betty/flash.c new file mode 100644 index 0000000..8d9c02a --- /dev/null +++ b/betty/flash.c @@ -0,0 +1,230 @@ +/* + * flash.c - low level flash handling + * + * author: hackbard@hackdaworld.org + * + */ + +#include "flash.h" + +/* + * sector addresses + */ +static unsigned long sector_address[19]={ + 0x00000,0x02000,0x03000,0x04000,0x08000, + 0x10000,0x18000, + 0x20000,0x28000, + 0x30000,0x38000, + 0x40000,0x48000, + 0x50000,0x58000, + 0x60000,0x68000, + 0x70000,0x78000 +}; + +/* + * functions + */ + +void flash_init(void) { + + /* + * idle clocks between rad & write: 0+1 + * length of read access: 1+3 + * bls lines high during write access + * length of write access: 0+1 + * no write protect, no burst-rom + * 16 bit data width + */ + + BCFG0=0x10000420; // flash 1 + BCFG2=0x10000420; // flash 2 + + /* + * p3.27: write enable + * p3.25: chip select 2 + * p2.15 - p2.8: data bus + * a[1:15] -> address lines + */ + + PINSEL2=(PINSEL2&P2MASK)|(1<<8); + PINSEL2=(PINSEL2&P2MASK&~((1<<15)|(1<<14)))|(1<<14); + PINSEL2=(PINSEL2&P2MASK&~((1<<5)|(1<<4)))|(1<<4); + PINSEL2=(PINSEL2&P2MASK)|(1<<24); + PINSEL2=(PINSEL2&P2MASK&~((1<<27)|(1<<26)|(1<<25)))|(1<<27)|(1<<26); +} + +void flash_reset(u8 bank) { + + if((bank!='0')&(bank!='2')) + return; + + if(bank=='0') + FLASH_B0F=0xf0; + else + FLASH_B2F=0xf0; +} + +void flash_sector_erase(u8 bank,u8 sector) { + + u32 a18_12; + + if(sector>18) + return; + a18_12=sector_address[sector]<<1; + + switch(bank) { + case '0': + FLASH_B0F555=0xaa; + FLASH_B0F2AA=0x55; + FLASH_B0F555=0x80; + FLASH_B0F555=0xaa; + FLASH_B0F2AA=0x55; + *((volatile u16 *)(FLASH_BANK0|a18_12))=0x30; + break; + case '2': + FLASH_B2F555=0xaa; + FLASH_B2F2AA=0x55; + FLASH_B2F555=0x80; + FLASH_B2F555=0xaa; + FLASH_B2F2AA=0x55; + *((volatile u16 *)(FLASH_BANK2|a18_12))=0x30; + break; + default: + return; + } + + return; +} + +void flash_chip_erase(u8 bank) { + + u8 status; + + if((bank!='0')&(bank!='2')) + return; + + if(bank=='0') { + FLASH_B0F555=0xaa; + FLASH_B0F2AA=0x55; + FLASH_B0F555=0x80; + FLASH_B0F555=0xaa; + FLASH_B0F2AA=0x55; + FLASH_B0F555=0x10; + } + else { + FLASH_B2F555=0xaa; + FLASH_B2F2AA=0x55; + FLASH_B2F555=0x80; + FLASH_B2F555=0xaa; + FLASH_B2F2AA=0x55; + FLASH_B2F555=0x10; + } + + while(1) { + if(bank=='0') + status=FLASH_B0F; + else + status=FLASH_B2F; + if(status&0x80) + break; + } +} + +void flash_unlock_bypass(u8 bank) { + + if((bank!='0')&(bank!='2')) + return; + + if(bank=='0') { + FLASH_B0F555=0xaa; + FLASH_B0F2AA=0x55; + FLASH_B0F555=0x20; + } + else { + FLASH_B2F555=0xaa; + FLASH_B2F2AA=0x55; + FLASH_B2F555=0x20; + } +} + +void flash_unlock_bypass_reset(u8 bank) { + + if((bank!='0')&(bank!='2')) + return; + + if(bank=='0') { + FLASH_B0F=0x90; + FLASH_B0F=0x00; + } + else { + FLASH_B2F=0x90; + FLASH_B2F=0x00; + } +} + +int flash_write_word(u32 addr,u16 data) { + + u16 check; + + if(data==0xffff) + return 0; + + *((unsigned volatile short *)addr)=0xa0; + *((unsigned volatile short *)addr)=data; + while(1) { + check=*((unsigned short *)addr); + if((data&0x80)==(check&0x80)) + break; + } + if(data!=check) + return -1; + + return 0; +} + +#define flash_read_word(addr,data) *(data)=*((unsigned volatile short *)(addr)) + +int flash_write_buf(u32 addr,u16 *buf,int len) { + + int cnt,ret; + u8 bank; + + /* len must be a multiple of 2 */ + if(len&0x1) + return -1; + + /* decide the bank */ + if(addr<0x82000000) + bank='0'; + else + bank='2'; + + /* unlock */ + flash_unlock_bypass(bank); + + /* write the data */ + ret=0; + for(cnt=0;cnt