#include <iomacros.h>
-/* Concerning clock rates,
- the maximimum clock rates are defined on page 4 of the spec.
- They vary, but are roughly 30MHz. Raising this clock rate might
- allow for clock glitching, but the GoodFET isn't sufficient fast for that.
- Perhaps a 200MHz ARM or an FPGA in the BadassFET?
+/* Concerning clock rates, the maximimum clock rates are defined on
+ page 4 of the spec. They vary, but are roughly 30MHz. Raising
+ this clock rate might allow for clock glitching, but the GoodFET
+ isn't sufficient fast for that. Perhaps a 200MHz ARM or an FPGA in
+ the BadassFET?
*/
//Pins and I/O
unsigned char verb,
unsigned long len){
//Always init. Might help with buggy lines.
- ccdebuginit();
+ //Might hurt too.
+ //ccdebuginit();
+ long i;
switch(verb){
//CC_PEEK and CC_POKE will come later.
+ case PEEK:
+ cmddata[0]=cc_peekirambyte(cmddata[0]);
+ txdata(app,verb,1);
+ break;
+ case POKE:
+ cmddata[0]=cc_pokeirambyte(cmddata[0],cmddata[1]);
+ txdata(app,verb,0);
+ break;
case READ: //Write a command and return 1-byte reply.
cccmd(len);
ccread(1);
cc_get_pc();
txdata(app,verb,2);
break;
+ case CC_LOCKCHIP:
+ cc_lockchip();
+ //no break, return status
case CC_READ_STATUS:
cc_read_status();
txdata(app,verb,1);
cc_write_flash_page(cmddatalong[0]);
txdata(app,verb,0);
break;
+ case CC_WIPEFLASHBUFFER:
+ for(i=0xf000;i<0xf800;i++)
+ cc_pokedatabyte(i,0xFF);
+ txdata(app,verb,0);
+ break;
case CC_MASS_ERASE_FLASH:
case CC_CLOCK_INIT:
case CC_PROGRAM_FLASH:
//! Set the Chipcon's Program Counter
void cc_set_pc(u32 adr){
- cmddata[0]=0x02; //GetPC
- cmddata[1]=(adr>>8)&0xff; //HIBYTE
- cmddata[2]=adr&0xff; //LOBYTE
+ cmddata[0]=0x02; //SetPC
+ cmddata[1]=((adr>>8)&0xff); //HIBYTE
+ cmddata[2]=adr&0xff; //LOBYTE
+ cc_debug_instr(3);
return;
}
cccmd(2);
ccread(1);
}
+
+//! Locks the chip.
+void cc_lockchip(){
+ register int i;
+
+ debugstr("Locking chip.");
+ cc_wr_config(1);//Select Info Flash
+ if(!(cc_rd_config()&1))
+ debugstr("Config forgotten!");
+
+ //Clear config page.
+ for(i=0;i<2048;i++)
+ cc_pokedatabyte(0xf000+i,0);
+ cc_write_flash_page(0);
+ if(cc_peekcodebyte(0))
+ debugstr("Failed to clear info flash byte.");
+
+ cc_wr_config(0);
+ if(cc_rd_config()&1)
+ debugstr("Stuck in info flash mode!");
+}
+
//! Read the configuration byte.
unsigned char cc_rd_config(){
cmddata[0]=CCCMD_RD_CONFIG; //0x24
}
-//256 words/page
-#define HIBYTE_WORDS_PER_FLASH_PAGE 0x00
-#define LOBYTE_WORDS_PER_FLASH_PAGE 0x80
-#define FLASHPAGE_SIZE 0x100
-//2 bytes/word
-#define FLASH_WORD_SIZE 0x2
+//32-bit words, 2KB pages
+#define HIBYTE_WORDS_PER_FLASH_PAGE 0x02
+#define LOBYTE_WORDS_PER_FLASH_PAGE 0x00
+#define FLASHPAGE_SIZE 0x800
+
+//32 bit words
+#define FLASH_WORD_SIZE 0x4
const u8 flash_routine[] = {
//MOV FADDRH, #imm;
0x00,//#imm=((address >> 8) / FLASH_WORD_SIZE) & 0x7E,
0x75, 0xAC, 0x00, // MOV FADDRL, #00;
- /* Erase page. *
+ /* Erase page. */
0x75, 0xAE, 0x01, // MOV FLC, #01H; // ERASE
// ; Wait for flash erase to complete
0xE5, 0xAE, // eraseWaitLoop: MOV A, FLC;
0x20, 0xE7, 0xFB, // JB ACC_BUSY, eraseWaitLoop;
- */
+ /* End erase page. */
// ; Initialize the data pointer
0x90, 0xF0, 0x00, // MOV DPTR, #0F000H;
// ; Outer loops
0xA5 // DB 0xA5;
};
+
//! Copies flash buffer to flash.
void cc_write_flash_page(u32 adr){
//Assumes that page has already been written to XDATA 0xF000
+ //debugstr("Flashing 2kb at 0xF000 to given adr.");
+
+ if(adr&(FLASHPAGE_SIZE-1)){
+ debugstr("Flash page address is not on a multiple of 2kB. Aborting.");
+ return;
+ }
//Routine comes next
//WRITE_XDATA_MEMORY(IN: 0xF000 + FLASH_PAGE_SIZE, sizeof(routine), routine);
//((address >> 8) / FLASH_WORD_SIZE) & 0x7E
cc_pokedatabyte(0xF000+FLASHPAGE_SIZE+2,
((adr>>8)/FLASH_WORD_SIZE)&0x7E);
- cc_debug(3, //MOV MEMCTR, (bank * 16) + 1;
- 0x75, 0xc7, 0x51);
+ //debugstr("Wrote flash routine.");
+
+
+ //MOV MEMCTR, (bank * 16) + 1;
+ cmddata[0]=0x75;
+ cmddata[1]=0xc7;
+ cmddata[2]=0x51;
+ cc_debug_instr(3);
+ debugstr("Loaded bank info.");
+
cc_set_pc(0xf000+FLASHPAGE_SIZE);//execute code fragment
cc_resume();
+
+ debugstr("Executing.");
+
+
while(!(cc_read_status()&CC_STATUS_CPUHALTED)){
- P1OUT^=1;//blink LED
+ P1OUT^=1;//blink LED while flashing
}
+
+ debugstr("Done flashing.");
+
P1OUT&=~1;//clear LED
}
unsigned char cmd=CCCMD_DEBUG_INSTR+(len&0x3);//0x54+len
CCWRITE;
cctrans8(cmd);
- if(len--)
+ if(len>0)
cctrans8(a);
- if(len--)
+ if(len>1)
cctrans8(b);
- if(len--)
+ if(len>2)
cctrans8(c);
CCREAD;
return cctrans8(0x00);
unsigned char cc_peekdatabyte(unsigned int adr){
unsigned char
hb=(adr&0xFF00)>>8,
- lb=adr&0xFF,
- toret;
-
+ lb=adr&0xFF;
+
//MOV DPTR, adr
cc_debug(3, 0x90, hb, lb);
//MOVX A, @DPTR
//Must be 2, perhaps for clocking?
- toret=cc_debug(3, 0xE0, 0, 0);
- return toret;
-
- /*
-DEBUG_INSTR(IN: 0x90, HIBYTE(address), LOBYTE(address), OUT: Discard);
-for (n = 0; n < count; n++) {
- DEBUG_INSTR(IN: 0xE0, OUT: outputArray[n]);
- DEBUG_INSTR(IN: 0xA3, OUT: Discard);
+ return cc_debug(3, 0xE0, 0, 0);
}
- */
+
+
+//! Fetch a byte of IRAM.
+u8 cc_peekirambyte(u8 adr){
+ //CLR A
+ cc_debug(2, 0xE4, 0, 0);
+ //MOV A, #iram
+ return cc_debug(3, 0xE5, adr, 0);
+}
+
+//! Write a byte of IRAM.
+u8 cc_pokeirambyte(u8 adr, u8 val){
+ //CLR A
+ cc_debug(2, 0xE4, 0, 0);
+ //MOV #iram, #val
+ return cc_debug(3, 0x75, adr, val);
+ //return cc_debug(3, 0x75, val, adr);
}
+
+