Correct page sizes for Chipcon.
[goodfet] / firmware / apps / chipcon / chipcon.c
index bbc751a..1790526 100644 (file)
@@ -7,8 +7,8 @@
 //This is like SPI, except that you read or write, not both.
 
 /* N.B. The READ verb performs a write of all (any) supplied data,
-    then reads a single byte reply from the target.  The WRITE verb
-    only writes.
+   then reads a single byte reply from the target.  The WRITE verb
+   only writes.
 */
 
 #include "platform.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?
+   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
@@ -125,6 +125,9 @@ void ccread(unsigned char len){
 void cchandle(unsigned char app,
               unsigned char verb,
               unsigned long len){
+  //Always init.  Might help with buggy lines.
+  ccdebuginit();
+  
   switch(verb){
     //CC_PEEK and CC_POKE will come later.
   case READ:  //Write a command and return 1-byte reply.
@@ -216,41 +219,55 @@ void cchandle(unsigned char app,
     txdata(app,verb,1);
     break;
   case CC_SET_PC:
-  case CC_CLOCK_INIT:
+    cc_set_pc(cmddatalong[0]);
+    txdata(app,verb,0);
+    break;
   case CC_WRITE_FLASH_PAGE:
+    cc_write_flash_page(cmddatalong[0]);
+    txdata(app,verb,0);
+    break;
   case CC_MASS_ERASE_FLASH:
+  case CC_CLOCK_INIT:
   case CC_PROGRAM_FLASH:
+    debugstr("This Chipcon command is not yet implemented.");
     txdata(app,NOK,0);//TODO implement me.
     break;
   }
 }
 
+//! 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
+  return;
+}
+
 //! Erase all of a Chipcon's memory.
 void cc_chip_erase(){
-  cmddata[0]=0x14;
+  cmddata[0]=CCCMD_CHIP_ERASE; //0x14
   cccmd(1);
   ccread(1);
 }
 //! Write the configuration byte.
 void cc_wr_config(unsigned char config){
-  cmddata[0]=0x1d;
+  cmddata[0]=CCCMD_WR_CONFIG; //0x1D
   cmddata[1]=config;
   cccmd(2);
   ccread(1);
 }
 //! Read the configuration byte.
 unsigned char cc_rd_config(){
-  cmddata[0]=0x24;
+  cmddata[0]=CCCMD_RD_CONFIG; //0x24
   cccmd(1);
   ccread(1);
   return cmddata[0];
 }
 
 
-
 //! Read the status register
 unsigned char cc_read_status(){
-  cmddata[0]=0x34;
+  cmddata[0]=CCCMD_READ_STATUS; //0x3f
   cccmd(1);
   ccread(1);
   return cmddata[0];
@@ -259,7 +276,7 @@ unsigned char cc_read_status(){
 //! Read the CHIP ID bytes.
 unsigned short cc_get_chip_id(){
   unsigned short toret;
-  cmddata[0]=0x68;
+  cmddata[0]=CCCMD_GET_CHIP_ID; //0x68
   cccmd(1);
   ccread(2);
   
@@ -269,10 +286,87 @@ unsigned short cc_get_chip_id(){
   return toret;
 }
 
+//! Populates flash buffer in xdata.
+void cc_write_flash_buffer(u8 *data, u16 len){
+  cc_write_xdata(0xf000, data, len);
+}
+//! Populates flash buffer in xdata.
+void cc_write_xdata(u16 adr, u8 *data, u16 len){
+  u16 i;
+  for(i=0; i<len; i++){
+    cc_pokedatabyte(adr+i,
+                   data[i]);
+  }
+}
+
+
+//32-bit words, 2KB pages
+#define HIBYTE_WORDS_PER_FLASH_PAGE 0x02
+#define LOBYTE_WORDS_PER_FLASH_PAGE 0x00
+#define FLASHPAGE_SIZE 0x800
+
+//2 bytes/word
+#define FLASH_WORD_SIZE 0x4
+
+const u8 flash_routine[] = {
+  //MOV FADDRH, #imm; 
+  0x75, 0xAD,
+  0x00,//#imm=((address >> 8) / FLASH_WORD_SIZE) & 0x7E,
+  
+  0x75, 0xAC, 0x00,                                          //                 MOV FADDRL, #00; 
+  /* 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; 
+  */
+                                                             //                 ; Initialize the data pointer 
+  0x90, 0xF0, 0x00,                                          //                 MOV DPTR, #0F000H; 
+                                                             //                 ; Outer loops 
+  0x7F, HIBYTE_WORDS_PER_FLASH_PAGE,                         //                 MOV R7, #imm; 
+  0x7E, LOBYTE_WORDS_PER_FLASH_PAGE,                         //                 MOV R6, #imm; 
+  0x75, 0xAE, 0x02,                                          //                 MOV FLC, #02H; // WRITE 
+                                                             //                     ; Inner loops 
+  0x7D, FLASH_WORD_SIZE,                                     // writeLoop:          MOV R5, #imm; 
+  0xE0,                                                      // writeWordLoop:          MOVX A, @DPTR; 
+  0xA3,                                                      //                         INC DPTR; 
+  0xF5, 0xAF,                                                //                         MOV FWDATA, A;  
+  0xDD, 0xFA,                                                //                     DJNZ R5, writeWordLoop; 
+                                                             //                     ; Wait for completion 
+  0xE5, 0xAE,                                                // writeWaitLoop:      MOV A, FLC; 
+  0x20, 0xE6, 0xFB,                                          //                     JB ACC_SWBSY, writeWaitLoop; 
+  0xDE, 0xF1,                                                //                 DJNZ R6, writeLoop; 
+  0xDF, 0xEF,                                                //                 DJNZ R7, writeLoop; 
+                                                             //                 ; Done, fake a breakpoint 
+  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
+  
+  //Routine comes next
+  //WRITE_XDATA_MEMORY(IN: 0xF000 + FLASH_PAGE_SIZE, sizeof(routine), routine);
+  cc_write_xdata(0xF000+FLASHPAGE_SIZE,
+                (u8*) flash_routine, sizeof(flash_routine));
+  //Patch routine's third byte with
+  //((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);
+  cc_set_pc(0xf000+FLASHPAGE_SIZE);//execute code fragment
+  cc_resume();
+  while(!(cc_read_status()&CC_STATUS_CPUHALTED)){
+    P1OUT^=1;//blink LED
+  }
+  
+  P1OUT&=~1;//clear LED
+}
 
 //! Read the PC
 unsigned short cc_get_pc(){
-  cmddata[0]=0x28;
+  cmddata[0]=CCCMD_GET_PC; //0x28
   cccmd(1);
   ccread(2);
   
@@ -282,6 +376,7 @@ unsigned short cc_get_pc(){
 
 //! Set a hardware breakpoint.
 void cc_set_hw_brkpnt(unsigned short adr){
+  debugstr("FIXME: This certainly won't work.");
   cmddataword[0]=adr;
   cccmd(2);
   ccread(1);
@@ -291,14 +386,14 @@ void cc_set_hw_brkpnt(unsigned short adr){
 
 //! Halt the CPU.
 void cc_halt(){
-  cmddata[0]=0x44;
+  cmddata[0]=CCCMD_HALT; //0x44
   cccmd(1);
   ccread(1);
   return;
 }
 //! Resume the CPU.
 void cc_resume(){
-  cmddata[0]=0x4C;
+  cmddata[0]=CCCMD_RESUME; //0x4C
   cccmd(1);
   ccread(1);
   return;
@@ -307,7 +402,7 @@ void cc_resume(){
 
 //! Step an instruction
 void cc_step_instr(){
-  cmddata[0]=0x5C;
+  cmddata[0]=CCCMD_STEP_INSTR; //0x5C
   cccmd(1);
   ccread(1);
   return;
@@ -316,7 +411,7 @@ void cc_step_instr(){
 //! Debug an instruction.
 void cc_debug_instr(unsigned char len){
   //Bottom two bits of command indicate length.
-  unsigned char cmd=0x54+(len&0x3);
+  unsigned char cmd=CCCMD_DEBUG_INSTR+(len&0x3); //0x54+len
   CCWRITE;
   cctrans8(cmd);  //Second command code
   cccmd(len&0x3); //Command itself.
@@ -329,13 +424,8 @@ unsigned char cc_debug(unsigned char len,
              unsigned char a,
              unsigned char b,
              unsigned char c){
-  unsigned char cmd=0x54+(len&0x3);//(len&0x3);
+  unsigned char cmd=CCCMD_DEBUG_INSTR+(len&0x3);//0x54+len
   CCWRITE;
-  cctrans8(0xFF);//resync
-  cctrans8(0xFF);//resync
-  cctrans8(0xFF);//resync
-  cctrans8(0xFF);//resync
-  cctrans8(0xFF);//resync
   cctrans8(cmd);
   if(len--)
     cctrans8(a);