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)
# 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
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();
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;
+ }
}
}
#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
*/
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));
* functions
*/
+void display_init(void) {
+
+ BCFG1=0x00000c42;
+}
+
void bl_init(void) {
PINSEL0&=~(1<<9|(1<<8));
--- /dev/null
+/*
+ * 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<len/2;cnt++) {
+ if(flash_write_word(addr,*(buf+cnt))==0)
+ ret+=2;
+ addr+=2;
+ }
+
+ /* relock */
+ flash_unlock_bypass_reset(bank);
+
+ return ret;
+}
+
+void flash_read_buf(u32 addr,u16 *buf,int len) {
+
+ int cnt;
+
+ /* len must be a multiple of 2 */
+ if(len&0x1)
+ return;
+
+ for(cnt=0;cnt<len/2;cnt++)
+ flash_read_word(addr,buf+cnt);
+}
+
--- /dev/null
+/*
+ * flash.h - header file for the low level flash handling
+ *
+ * author: hackbard@hackdaworld.org
+ *
+ */
+
+#ifndef FLASH_H
+#define FLASH_H
+
+#include "lpc2xxx.h"
+#include "types.h"
+
+/*
+ * defines
+ */
+
+#define BANK0 '0'
+#define BANK2 '2'
+#define FLASH_BANK0 0x80000000
+#define FLASH_BANK2 0x82000000
+#define FLASH_SIZE 0x00100000
+
+/* cmd addresses (shifted to left!) */
+#define FLASH_B0F555 (*((volatile unsigned short *)(FLASH_BANK0|0xaaa)))
+#define FLASH_B0F2AA (*((volatile unsigned short *)(FLASH_BANK0|0x554)))
+#define FLASH_B0F (*((volatile unsigned short *)(FLASH_BANK0)))
+#define FLASH_B2F555 (*((volatile unsigned short *)(FLASH_BANK2|0xaaa)))
+#define FLASH_B2F2AA (*((volatile unsigned short *)(FLASH_BANK2|0x554)))
+#define FLASH_B2F (*((volatile unsigned short *)(FLASH_BANK2)))
+
+/*
+ * function prototypes
+ */
+
+void flash_init(void);
+void flash_reset(u8 bank);
+void flash_sector_erase(u8 flash,u8 sector);
+void flash_chip_erase(u8 bank);
+void flash_unlock_bypass(u8 bank);
+void flash_unlock_bypass_reset(u8 bank);
+int flash_write_word(u32 addr,u16 data);
+int flash_write_buf(u32 addr,u16 *buf,int len);
+void flash_read_buf(u32 addr,u16 *buf,int len);
+
+#endif
#define PINSEL0 (*((volatile unsigned long *) 0xE002C000))\r
#define PINSEL1 (*((volatile unsigned long *) 0xE002C004))\r
#define PINSEL2 (*((volatile unsigned long *) 0xE002C014))\r
+#define P2MASK 0x0FF3E9FC\r
\r
/* General Purpose Input/Output (GPIO) */\r
#define IOPIN (*((volatile unsigned long *) 0xE0028000))\r
continue;
}
-void pause(int cnt) {
+void pause(u32 cnt) {
while(cnt--)
+ //continue;
asm volatile ("nop");
}
/* function prototypes */
void mmap_init(u8 memtype);
void pll_init(void);
-void pause(int cnt);
+void pause(u32 cnt);
#endif
--- /dev/null
+/*
+ * type.h - type definitions
+ *
+ * author: hackbard@hackdaworld.org
+ *
+ */
+
+#ifndef TYPE_H
+#define TYPE_H
+
+typedef unsigned char u8;
+typedef unsigned short u16;
+typedef unsigned int u32;
+
+#endif
+