Port of flash_cc2531 to FreeBSD. This is likely more just include a wiringPi compatible library for FreeBSD. Any new files are BSD licensed and NOT GPLv3 license.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

379 lines
11 KiB

  1. /***********************************************************************
  2. Copyright © 2019 Jean Michault.
  3. This program is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 3 of the License, or
  6. (at your option) any later version.
  7. This program is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with this program. If not, see <https://www.gnu.org/licenses/>.
  13. *************************************************************************/
  14. #include <wiringPi.h>
  15. #include <stdlib.h>
  16. #include <stdio.h>
  17. #include <stdbool.h>
  18. #include <string.h>
  19. #include <stdint.h>
  20. #include <unistd.h>
  21. #include "CCDebugger.h"
  22. uint8_t buffer[601];
  23. uint8_t data[260];
  24. uint8_t buf1[1024];
  25. uint8_t buf2[1024];
  26. struct page
  27. {
  28. uint32_t minoffset,maxoffset;
  29. uint8_t datas[2048];
  30. } Pages[128];
  31. void readXDATA(uint16_t offset,uint8_t *bytes, int len)
  32. {
  33. cc_execi(0x90, offset ); //MOV DPTR,#data16
  34. for ( int i=0 ; i<len;i++)
  35. {
  36. bytes[i] = cc_exec(0xE0); //MOVX A,@DPTR
  37. cc_exec(0xA3); // INC DPTR
  38. }
  39. }
  40. void writeXDATA(uint16_t offset,uint8_t *bytes, int len)
  41. {
  42. cc_execi(0x90,offset); //MOV DPTR,#data16
  43. for ( int i=0 ; i<len;i++)
  44. {
  45. cc_exec2(0x74,bytes[i]); // MOV A,#data
  46. cc_exec(0xF0); //MOVX @DPTR,A
  47. cc_exec(0xA3); // INC DPTR
  48. }
  49. }
  50. void readPage(int page,uint8_t *buf)
  51. {
  52. uint8_t bank=page>>4;
  53. // get FMAP
  54. uint8_t res = cc_exec2(0xE5, 0xC7);
  55. // select bank
  56. res = (res & 0xF8) | (bank & 0x07);
  57. res = cc_exec3(0x75, 0xC7, res); // MOV direct,#data
  58. // calculer l'adresse de destination
  59. uint32_t offset = ((page&0xf)<<11) + Pages[page].minoffset;
  60. // Setup DPTR
  61. cc_execi( 0x90, 0x8000+offset ); // MOV DPTR,#data16
  62. for(int i=Pages[page].minoffset ; i<=Pages[page].maxoffset ;i++)
  63. {
  64. res = cc_exec ( 0xE0 ); // MOVX A,@DPTR
  65. buf[i] = res;
  66. res = cc_exec ( 0xA3 ); // INC DPTR
  67. }
  68. }
  69. uint8_t verif1[2048];
  70. uint8_t verif2[2048];
  71. int verifPage(int page)
  72. {
  73. do
  74. {
  75. readPage(page,verif1);
  76. readPage(page,verif2);
  77. } while (memcmp(verif1,verif2,2048));
  78. for(int i=Pages[page].minoffset ; i<=Pages[page].maxoffset ;i++)
  79. {
  80. if(verif1[i] != Pages[page].datas[i])
  81. {
  82. printf("\nerror at 0x%x, 0x%x instead of 0x%x\n",i,verif1[i],Pages[page].datas[i]);
  83. return 1;
  84. }
  85. }
  86. return 0;
  87. }
  88. int writePage(int page)
  89. {
  90. uint8_t bank=page>>4;
  91. // get FMAP
  92. uint8_t res = cc_exec2(0xE5, 0xC7);
  93. // select bank
  94. res = (res & 0xF8) | (bank & 0x07);
  95. res = cc_exec3(0x75, 0xC7, res); // MOV direct,#data
  96. // calculer l'adresse de destination
  97. // round minoffset because FADDR is a word address
  98. Pages[page].minoffset = (Pages[page].minoffset & 0xfffffffc);
  99. // round maxoffset to write entire words
  100. Pages[page].maxoffset = (Pages[page].maxoffset |0x3);
  101. uint32_t offset = ((page&0xf)<<11) + Pages[page].minoffset;
  102. uint32_t len = Pages[page].maxoffset-Pages[page].minoffset+1;
  103. //FIXME : sometimes incorrect length is wrote
  104. //if(len&0xf && (Pages[page].minoffset+len<2032)) len= (len&0x7f0)+16;
  105. // configure DMA-0 pour DEBUG --> RAM
  106. uint8_t dma_desc0[8];
  107. dma_desc0[0] = 0x62;// src[15:8]
  108. dma_desc0[1] = 0x60;// src[7:0]
  109. dma_desc0[2] = 0x00;// dest[15:8]
  110. dma_desc0[3] = 0x00;// dest[7:0]
  111. dma_desc0[4] = (len>>8)&0xff;
  112. dma_desc0[5] = (len&0xff);
  113. dma_desc0[6] = 0x1f; //wordsize=0,tmode=0,trig=0x1F
  114. dma_desc0[7] = 0x19;//srcinc=0,destinc=1,irqmask=1,m8=0,priority=1
  115. writeXDATA( 0x1000, dma_desc0, 8 );
  116. cc_exec3( 0x75, 0xD4, 0x00);
  117. cc_exec3( 0x75, 0xD5, 0x10);
  118. // configure DMA-1 pour RAM --> FLASH
  119. uint8_t dma_desc1[8];
  120. dma_desc1[0] = 0x00;// src[15:8]
  121. dma_desc1[1] = 0x00;// src[7:0]
  122. dma_desc1[2] = 0x62;// dest[15:8]
  123. dma_desc1[3] = 0x73;// dest[7:0]
  124. dma_desc1[4] = (len>>8)&0xff;
  125. dma_desc1[5] = (len&0xff);
  126. dma_desc1[6] = 0x12; //wordsize=0,tmode=0,trig=0x12
  127. dma_desc1[7] = 0x42;//srcinc=1,destinc=0,irqmask=1,m8=0,priority=2
  128. writeXDATA( 0x1008, dma_desc1, 8 );
  129. cc_exec3( 0x75, 0xD2, 0x08);
  130. cc_exec3( 0x75, 0xD3, 0x10);
  131. // clear flash status
  132. readXDATA(0x6270, &res, 1);
  133. res &=0x1F;
  134. writeXDATA(0x6270, &res, 1);
  135. // clear DMAIRQ 0 et 1
  136. res = cc_exec2(0xE5, 0xD1);
  137. res &= ~1;
  138. res &= ~2;
  139. cc_exec3(0x75,0xD1,res);
  140. // disarm DMA Channel 0 et 1
  141. res = cc_exec2(0xE5, 0xD6);
  142. res &= ~1;
  143. res &= ~2;
  144. cc_exec3(0x75,0xD6,res);
  145. // Upload to RAM through DMA-0
  146. // arm DMA channel 0 :
  147. res = cc_exec2(0xE5, 0xD6);
  148. res |= 1;
  149. cc_exec3(0x75,0xD6,res);
  150. cc_delay(200);
  151. // transfert de données en mode burst
  152. cc_write(0x80|( (len>>8)&0x7) );
  153. cc_write(len&0xff);
  154. for(int i=0 ; i<len ;i++)
  155. cc_write(Pages[page].datas[i+Pages[page].minoffset]);
  156. // wait DMA end :
  157. do
  158. {
  159. cc_delay(100);
  160. res = cc_exec2(0xE5, 0xD1);
  161. res &= 1;
  162. } while (res==0);
  163. // Clear DMA IRQ flag
  164. res = cc_exec2(0xE5, 0xD1);
  165. res &= ~1;
  166. cc_exec3(0x75,0xD1,res);
  167. // disarm DMA Channel 1
  168. res = cc_exec2(0xE5, 0xD6);
  169. res &= ~2;
  170. cc_exec3(0x75,0xD6,res);
  171. // écrire l'adresse de destination dans FADDRH FADDRL
  172. offset = ((page&0xff)<<11) + Pages[page].minoffset;
  173. res=(offset>>2)&0xff;
  174. writeXDATA( 0x6271, &res,1);
  175. res=(offset>>10)&0xff;
  176. writeXDATA( 0x6272, &res,1);
  177. // arm DMA channel 1 :
  178. res = cc_exec2(0xE5, 0xD6);
  179. res |= 2;
  180. cc_exec3(0x75,0xD6,res);
  181. cc_delay(200);
  182. // lancer la copie vers la FLASH
  183. readXDATA(0x6270, &res, 1);
  184. res |= 2;
  185. writeXDATA(0x6270, &res, 1);
  186. // wait DMA end :
  187. do
  188. {
  189. sleep(1);
  190. res = cc_exec2(0xE5, 0xD1);
  191. res &= 2;
  192. } while (res==0);
  193. // vérifie qu'il n'y a pas eu de flash abort
  194. readXDATA(0x6270, &res, 1);
  195. if (res&0x20)
  196. {
  197. fprintf(stderr," flash error !!!\n");
  198. exit(1);
  199. }
  200. }
  201. void helpo()
  202. {
  203. fprintf(stderr,"usage : cc_write [-d pin_DD] [-c pin_DC] [-r pin_reset] file_to_flash\n");
  204. fprintf(stderr," -c : change pin_DC (default 27)\n");
  205. fprintf(stderr," -d : change pin_DD (default 28)\n");
  206. fprintf(stderr," -r : change reset pin (default 24)\n");
  207. fprintf(stderr," -m : change multiplier for time delay (default auto)\n");
  208. }
  209. int main(int argc,char *argv[])
  210. {
  211. int opt;
  212. int rePin=24;
  213. int dcPin=27;
  214. int ddPin=28;
  215. int setMult=-1;
  216. while( (opt=getopt(argc,argv,"m:d:c:r:h?")) != -1)
  217. {
  218. switch(opt)
  219. {
  220. case 'm' :
  221. setMult=atoi(optarg);
  222. break;
  223. case 'd' : // DD pinglo
  224. ddPin=atoi(optarg);
  225. break;
  226. case 'c' : // DC pinglo
  227. dcPin=atoi(optarg);
  228. break;
  229. case 'r' : // restarigi pinglo
  230. rePin=atoi(optarg);
  231. break;
  232. case 'h' : // helpo
  233. case '?' : // helpo
  234. helpo();
  235. exit(0);
  236. break;
  237. }
  238. }
  239. if( optind >= argc ) { helpo(); exit(1); }
  240. FILE * ficin = fopen(argv[optind],"r");
  241. if(!ficin) { fprintf(stderr," Can't open file %s.\n",argv[optind]); exit(1); }
  242. // on initialise les ports GPIO et le debugger
  243. cc_init(rePin,dcPin,ddPin);
  244. if(setMult>0) cc_setmult(setMult);
  245. // entrée en mode debug
  246. cc_enter();
  247. // envoi de la commande getChipID :
  248. uint16_t ID;
  249. ID = cc_getChipID();
  250. printf(" ID = %04x.\n",ID);
  251. for (int page=0 ; page<128 ; page++)
  252. {
  253. memset(Pages[page].datas,0xff,2048);
  254. Pages[page].minoffset=0xffff;
  255. Pages[page].maxoffset=0;
  256. }
  257. uint16_t ela=0; // extended linear address
  258. uint32_t sla=0; // start linear address
  259. // read hex file
  260. int line=0;
  261. int maxpage=0;
  262. while(fgets(buffer,600,ficin))
  263. {
  264. int sum=0,cksum,type;
  265. uint32_t addr,len;
  266. line++;
  267. if(line%10==0) { printf("\r reading line %d.");fflush(stdout); }
  268. if(buffer[0] != ':') { fprintf(stderr,"incorrect hex file ( : missing)\n"); exit(1); }
  269. if(strlen(buffer)<3 ) { fprintf(stderr,"incorrect hex file ( incomplete line)\n"); exit(1); }
  270. if(!sscanf(buffer+1,"%02x",&len)) { fprintf(stderr,"incorrect hex file (incorrect length\n"); exit(1); }
  271. if(strlen(buffer)<(11 + (len * 2))) { fprintf(stderr,"incorrect hex file ( incomplete line)\n"); exit(1); }
  272. if(!sscanf(buffer+3,"%04x",&addr)) { fprintf(stderr,"incorrect hex file (incorrect addr)\n"); exit(1); }
  273. if(!sscanf(buffer+7,"%02x",&type)) { fprintf(stderr,"incorrect hex file (incorrect record type\n"); exit(1); }
  274. if(type == 4)
  275. {
  276. if(!sscanf(buffer+9,"%04x",&ela)) { fprintf(stderr,"incorrect hex file (incorrect extended addr)\n"); exit(1); }
  277. sla=ela<<16;
  278. continue;
  279. }
  280. if(type == 5)
  281. {
  282. if(!sscanf(buffer+9,"%08x",&sla)) { fprintf(stderr,"incorrect hex file (incorrect extended addr)\n"); exit(1); }
  283. ela = sla>>16;
  284. continue;
  285. }
  286. if(type==1) // EOF
  287. {
  288. break;
  289. }
  290. if(type) { fprintf(stderr,"incorrect hex file (record type %d not implemented\n",type); exit(1); }
  291. sum = (len & 255) + ((addr >> 8) & 255) + (addr & 255) + (type & 255);
  292. int i;
  293. for( i=0 ; i<len ; i++)
  294. {
  295. if(!sscanf(buffer+9+2*i,"%02x",&data[i])) { fprintf(stderr,"incorrect hex file (incorrect data)\n"); exit(1); }
  296. sum+=data[i];
  297. }
  298. if(!sscanf(buffer+9+2*i,"%02x",&cksum)) { fprintf(stderr,"incorrect hex file line %d (incorrect checksum)\n",line); exit(1); }
  299. if ( ((sum & 255) + (cksum & 255)) & 255 ) { fprintf(stderr,"incorrect hex file line %d (bad checksum) %x %x\n",line,(-sum)&255,cksum); exit(1); }
  300. // stock datas
  301. int page= (sla+addr)>>11;
  302. if (page>maxpage) maxpage=page;
  303. uint16_t start=(sla+addr)&0x7ff;
  304. if(start+len> 2048) // some datas are for next page
  305. { //copy end of datas to next page
  306. if (page+1>maxpage) maxpage=page+1;
  307. memcpy(&Pages[page+1].datas[0]
  308. ,data+2048-start,(start+len-2048));
  309. if(0 < Pages[page+1].minoffset) Pages[page+1].minoffset=0;
  310. if( (start+len-2048-1) > Pages[page].maxoffset) Pages[page].maxoffset=start+len-2048-1;
  311. len=2048-start;
  312. }
  313. memcpy(&Pages[page].datas[start]
  314. ,data,len);
  315. if(start < Pages[page].minoffset) Pages[page].minoffset=start;
  316. if( (start+len-1) > Pages[page].maxoffset) Pages[page].maxoffset=start+len-1;
  317. }
  318. printf("\n file loaded (%d lines read).\n",line);
  319. // activer DMA
  320. uint8_t conf=cc_getConfig();
  321. conf &= ~0x4;
  322. cc_setConfig(conf);
  323. for (int page=0 ; page <= maxpage ; page++)
  324. {
  325. if(Pages[page].maxoffset<Pages[page].minoffset) continue;
  326. printf("\rwriting page %3d/%3d.",page+1,maxpage+1);
  327. fflush(stdout);
  328. writePage(page);
  329. }
  330. printf("\n");
  331. // lire les données et les vérifier
  332. int badPage=0;
  333. for (int page=0 ; page <= maxpage ; page++)
  334. {
  335. if(Pages[page].maxoffset<Pages[page].minoffset) continue;
  336. printf("\rverifying page %3d/%3d.",page+1,maxpage+1);
  337. fflush(stdout);
  338. badPage += verifPage(page);
  339. }
  340. printf("\n");
  341. if (!badPage)
  342. printf(" flash OK.\n");
  343. else
  344. printf(" Errors found in %d pages.\n",badPage);
  345. // sortie du mode debug et désactivation :
  346. cc_setActive(false);
  347. // reboot
  348. cc_reset();
  349. fclose(ficin);
  350. }