/*********************************************************************** Copyright © 2019 Jean Michault. This program 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 of the License, or (at your option) any later version. This program 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 program. If not, see . *************************************************************************/ #include #include #include #include #include #include #include #include "CCDebugger.h" uint8_t buffer[601]; uint8_t data[260]; uint8_t buf1[1024]; uint8_t buf2[1024]; struct page { uint32_t minoffset,maxoffset; uint8_t datas[2048]; } Pages[128]; void readXDATA(uint16_t offset,uint8_t *bytes, int len) { cc_execi(0x90, offset ); //MOV DPTR,#data16 for ( int i=0 ; i>4; // get FMAP uint8_t res = cc_exec2(0xE5, 0xC7); // select bank res = (res & 0xF8) | (bank & 0x07); res = cc_exec3(0x75, 0xC7, res); // MOV direct,#data // calculer l'adresse de destination uint32_t offset = ((page&0xf)<<11) + Pages[page].minoffset; // Setup DPTR cc_execi( 0x90, 0x8000+offset ); // MOV DPTR,#data16 for(int i=Pages[page].minoffset ; i<=Pages[page].maxoffset ;i++) { res = cc_exec ( 0xE0 ); // MOVX A,@DPTR buf[i] = res; res = cc_exec ( 0xA3 ); // INC DPTR } } uint8_t verif1[2048]; uint8_t verif2[2048]; int verifPage(int page) { do { readPage(page,verif1); readPage(page,verif2); } while (memcmp(verif1,verif2,2048)); for(int i=Pages[page].minoffset ; i<=Pages[page].maxoffset ;i++) { if(verif1[i] != Pages[page].datas[i]) { printf("\nerror at 0x%x, 0x%x instead of 0x%x\n",i,verif1[i],Pages[page].datas[i]); return 1; } } return 0; } int writePage(int page) { uint8_t bank=page>>4; // get FMAP uint8_t res = cc_exec2(0xE5, 0xC7); // select bank res = (res & 0xF8) | (bank & 0x07); res = cc_exec3(0x75, 0xC7, res); // MOV direct,#data // calculer l'adresse de destination // round minoffset because FADDR is a word address Pages[page].minoffset = (Pages[page].minoffset & 0xfffffffc); // round maxoffset to write entire words Pages[page].maxoffset = (Pages[page].maxoffset |0x3); uint32_t offset = ((page&0xf)<<11) + Pages[page].minoffset; uint32_t len = Pages[page].maxoffset-Pages[page].minoffset+1; //FIXME : sometimes incorrect length is wrote //if(len&0xf && (Pages[page].minoffset+len<2032)) len= (len&0x7f0)+16; // configure DMA-0 pour DEBUG --> RAM uint8_t dma_desc0[8]; dma_desc0[0] = 0x62;// src[15:8] dma_desc0[1] = 0x60;// src[7:0] dma_desc0[2] = 0x00;// dest[15:8] dma_desc0[3] = 0x00;// dest[7:0] dma_desc0[4] = (len>>8)&0xff; dma_desc0[5] = (len&0xff); dma_desc0[6] = 0x1f; //wordsize=0,tmode=0,trig=0x1F dma_desc0[7] = 0x19;//srcinc=0,destinc=1,irqmask=1,m8=0,priority=1 writeXDATA( 0x1000, dma_desc0, 8 ); cc_exec3( 0x75, 0xD4, 0x00); cc_exec3( 0x75, 0xD5, 0x10); // configure DMA-1 pour RAM --> FLASH uint8_t dma_desc1[8]; dma_desc1[0] = 0x00;// src[15:8] dma_desc1[1] = 0x00;// src[7:0] dma_desc1[2] = 0x62;// dest[15:8] dma_desc1[3] = 0x73;// dest[7:0] dma_desc1[4] = (len>>8)&0xff; dma_desc1[5] = (len&0xff); dma_desc1[6] = 0x12; //wordsize=0,tmode=0,trig=0x12 dma_desc1[7] = 0x42;//srcinc=1,destinc=0,irqmask=1,m8=0,priority=2 writeXDATA( 0x1008, dma_desc1, 8 ); cc_exec3( 0x75, 0xD2, 0x08); cc_exec3( 0x75, 0xD3, 0x10); // clear flash status readXDATA(0x6270, &res, 1); res &=0x1F; writeXDATA(0x6270, &res, 1); // clear DMAIRQ 0 et 1 res = cc_exec2(0xE5, 0xD1); res &= ~1; res &= ~2; cc_exec3(0x75,0xD1,res); // disarm DMA Channel 0 et 1 res = cc_exec2(0xE5, 0xD6); res &= ~1; res &= ~2; cc_exec3(0x75,0xD6,res); // Upload to RAM through DMA-0 // arm DMA channel 0 : res = cc_exec2(0xE5, 0xD6); res |= 1; cc_exec3(0x75,0xD6,res); cc_delay(200); // transfert de données en mode burst cc_write(0x80|( (len>>8)&0x7) ); cc_write(len&0xff); for(int i=0 ; i>2)&0xff; writeXDATA( 0x6271, &res,1); res=(offset>>10)&0xff; writeXDATA( 0x6272, &res,1); // arm DMA channel 1 : res = cc_exec2(0xE5, 0xD6); res |= 2; cc_exec3(0x75,0xD6,res); cc_delay(200); // lancer la copie vers la FLASH readXDATA(0x6270, &res, 1); res |= 2; writeXDATA(0x6270, &res, 1); // wait DMA end : do { sleep(1); res = cc_exec2(0xE5, 0xD1); res &= 2; } while (res==0); // vérifie qu'il n'y a pas eu de flash abort readXDATA(0x6270, &res, 1); if (res&0x20) { fprintf(stderr," flash error !!!\n"); exit(1); } } void helpo() { fprintf(stderr,"usage : cc_write [-d pin_DD] [-c pin_DC] [-r pin_reset] file_to_flash\n"); fprintf(stderr," -c : change pin_DC (default 27)\n"); fprintf(stderr," -d : change pin_DD (default 28)\n"); fprintf(stderr," -r : change reset pin (default 24)\n"); fprintf(stderr," -m : change multiplier for time delay (default auto)\n"); } int main(int argc,char *argv[]) { int opt; int rePin=24; int dcPin=27; int ddPin=28; int setMult=-1; while( (opt=getopt(argc,argv,"m:d:c:r:h?")) != -1) { switch(opt) { case 'm' : setMult=atoi(optarg); break; case 'd' : // DD pinglo ddPin=atoi(optarg); break; case 'c' : // DC pinglo dcPin=atoi(optarg); break; case 'r' : // restarigi pinglo rePin=atoi(optarg); break; case 'h' : // helpo case '?' : // helpo helpo(); exit(0); break; } } if( optind >= argc ) { helpo(); exit(1); } FILE * ficin = fopen(argv[optind],"r"); if(!ficin) { fprintf(stderr," Can't open file %s.\n",argv[optind]); exit(1); } // on initialise les ports GPIO et le debugger cc_init(rePin,dcPin,ddPin); if(setMult>0) cc_setmult(setMult); // entrée en mode debug cc_enter(); // envoi de la commande getChipID : uint16_t ID; ID = cc_getChipID(); printf(" ID = %04x.\n",ID); for (int page=0 ; page<128 ; page++) { memset(Pages[page].datas,0xff,2048); Pages[page].minoffset=0xffff; Pages[page].maxoffset=0; } uint16_t ela=0; // extended linear address uint32_t sla=0; // start linear address // read hex file int line=0; int maxpage=0; while(fgets(buffer,600,ficin)) { int sum=0,cksum,type; uint32_t addr,len; line++; if(line%10==0) { printf("\r reading line %d.");fflush(stdout); } if(buffer[0] != ':') { fprintf(stderr,"incorrect hex file ( : missing)\n"); exit(1); } if(strlen(buffer)<3 ) { fprintf(stderr,"incorrect hex file ( incomplete line)\n"); exit(1); } if(!sscanf(buffer+1,"%02x",&len)) { fprintf(stderr,"incorrect hex file (incorrect length\n"); exit(1); } if(strlen(buffer)<(11 + (len * 2))) { fprintf(stderr,"incorrect hex file ( incomplete line)\n"); exit(1); } if(!sscanf(buffer+3,"%04x",&addr)) { fprintf(stderr,"incorrect hex file (incorrect addr)\n"); exit(1); } if(!sscanf(buffer+7,"%02x",&type)) { fprintf(stderr,"incorrect hex file (incorrect record type\n"); exit(1); } if(type == 4) { if(!sscanf(buffer+9,"%04x",&ela)) { fprintf(stderr,"incorrect hex file (incorrect extended addr)\n"); exit(1); } sla=ela<<16; continue; } if(type == 5) { if(!sscanf(buffer+9,"%08x",&sla)) { fprintf(stderr,"incorrect hex file (incorrect extended addr)\n"); exit(1); } ela = sla>>16; continue; } if(type==1) // EOF { break; } if(type) { fprintf(stderr,"incorrect hex file (record type %d not implemented\n",type); exit(1); } sum = (len & 255) + ((addr >> 8) & 255) + (addr & 255) + (type & 255); int i; for( i=0 ; i>11; if (page>maxpage) maxpage=page; uint16_t start=(sla+addr)&0x7ff; if(start+len> 2048) // some datas are for next page { //copy end of datas to next page if (page+1>maxpage) maxpage=page+1; memcpy(&Pages[page+1].datas[0] ,data+2048-start,(start+len-2048)); if(0 < Pages[page+1].minoffset) Pages[page+1].minoffset=0; if( (start+len-2048-1) > Pages[page].maxoffset) Pages[page].maxoffset=start+len-2048-1; len=2048-start; } memcpy(&Pages[page].datas[start] ,data,len); if(start < Pages[page].minoffset) Pages[page].minoffset=start; if( (start+len-1) > Pages[page].maxoffset) Pages[page].maxoffset=start+len-1; } printf("\n file loaded (%d lines read).\n",line); // activer DMA uint8_t conf=cc_getConfig(); conf &= ~0x4; cc_setConfig(conf); for (int page=0 ; page <= maxpage ; page++) { if(Pages[page].maxoffset