Sophie Dexter
/
Just4Trionic
Just4Trionic - CAN and BDM FLASH programmer for Saab cars
Embed:
(wiki syntax)
Show/hide line numbers
bdmdriver.cpp
00001 /******************************************************************************* 00002 00003 bdmdriver.cpp 00004 (c) 2014 by Sophie Dexter 00005 00006 BD32 like 'syscall' processor for BDM resident driver functions 00007 00008 ******************************************************************************** 00009 00010 WARNING: Use at your own risk, sadly this software comes with no guarantees. 00011 This software is provided 'free' and in good faith, but the author does not 00012 accept liability for any damage arising from its use. 00013 00014 *******************************************************************************/ 00015 00016 #include "bdmdriver.h" 00017 00018 FILE *fp = NULL; 00019 00020 //private functions 00021 bool bdmSyscallPuts (void); 00022 bool bdmSyscallPutchar(void); 00023 bool bdmSyscallGets(void); 00024 bool bdmSyscallGetchar(void); 00025 bool bdmSyscallGetstat(void); 00026 bool bdmSyscallFopen(void); 00027 bool bdmSyscallFclose(void); 00028 bool bdmSyscallFread(void); 00029 bool bdmSyscallFwrite(void); 00030 bool bdmSyscallFtell(void); 00031 bool bdmSyscallFseek(void); 00032 bool bdmSyscallFgets(void); 00033 bool bdmSyscallFputs(void); 00034 bool bdmSyscallEval(void); 00035 bool bdmSyscallFreadsrec(void); 00036 00037 //----------------------------------------------------------------------------- 00038 /** 00039 Loads the contenst of a uint8_t array into the target's memory starting at the 00040 specified address 00041 00042 @param dataArray[] uint8_t array conataining data for BDM tartget 00043 @param startAddress Start address to load BDM memory to 00044 00045 @return succ / fail 00046 */ 00047 bool bdmLoadMemory(uint8_t dataArray[], uint32_t startAddress, uint32_t dataArraySize) 00048 { 00049 // for (uint32_t i = 0; i < sizeof(residentDriver); i++) { 00050 // if(memwrite_byte(&driverAddress, residentDriver[i]) != TERM_OK) return false; 00051 // driverAddress++; 00052 // } 00053 uint32_t driverSize = dataArraySize; 00054 uint32_t driverOffset = 0; 00055 uint32_t driverLong = 0; 00056 uint16_t driverWord = 0; 00057 uint8_t driverByte = 0; 00058 // Check that there is something to send 00059 if (driverSize == 0) return false; 00060 // Send the first 1-4 bytes as efficiently as possible over BDM 00061 switch (driverSize % 4) { 00062 case 3: 00063 driverWord = (dataArray[driverOffset++] << 8) | dataArray[driverOffset++]; 00064 if(memwrite_word(&startAddress, driverWord) != TERM_OK) return false; 00065 driverByte = dataArray[driverOffset++]; 00066 if(memfill_byte(driverByte) != TERM_OK) return false; 00067 break; 00068 case 2: 00069 driverWord = (dataArray[driverOffset++] << 8) | dataArray[driverOffset++]; 00070 if(memwrite_word(&startAddress, driverWord) != TERM_OK) return false; 00071 break; 00072 case 1: 00073 driverByte = dataArray[driverOffset++]; 00074 if(memwrite_byte(&startAddress, driverByte) != TERM_OK) return false; 00075 break; 00076 case 0: 00077 for (uint32_t i = 0; i < 4; i++) { 00078 driverLong <<= 8; 00079 driverLong |= dataArray[driverOffset++]; 00080 } 00081 if(memwrite_long(&startAddress, &driverLong) != TERM_OK) return false; 00082 break; 00083 // default: // There shouldn't be a default case 00084 } 00085 // transfer the rest as 'longs' to make best use of BDM transfer speed 00086 // printf("driverOffset 0x%08x, driverSize 0x%08x\r\n", driverOffset, driverSize); 00087 while (driverOffset < driverSize) { 00088 for (uint32_t i = 0; i < 4; i++) { 00089 driverLong <<= 8; 00090 driverLong |= dataArray[driverOffset++]; 00091 } 00092 if(memfill_long(&driverLong) != TERM_OK) return false; 00093 } 00094 // printf("driverOffset 0x%08x, driverSize 0x%08x\r\n", driverOffset, driverSize); 00095 return true; 00096 } 00097 00098 //----------------------------------------------------------------------------- 00099 /** 00100 Starts a BDM resident driver at the current PC (Program Counter) or a specified 00101 if given. The driver is allowed to run for a maximum period, maxtime, specified 00102 as milliseconds. 00103 00104 @param addr BDM driver address (0 to continue from current PC) 00105 @param maxtime how long to allow driver to execute (milliseconds) 00106 00107 @return succ / fail 00108 */ 00109 bool bdmRunDriver(uint32_t addr, uint32_t maxtime) 00110 { 00111 // Start BDM driver and allow it up to 200 milliseconds to update 256 Bytes 00112 // Upto 25 pulses per byte, 16us per pulse, 256 Bytes 00113 // 25 * 16 * 256 = 102,400us plus overhead for driver code execution time 00114 // Allowing up to 200 milliseconds seems like a good allowance. 00115 if (run_chip(&addr) != TERM_OK) { 00116 printf("Failed to start BDM driver.\r\n"); 00117 return false; 00118 } 00119 timeout.reset(); 00120 timeout.start(); 00121 // T5 ECUs' BDM interface seem to have problems when the running the CPU and 00122 // sometimes shows the CPU briefly switching between showing BDM mode or that 00123 // the CPU is running. 00124 // I 'debounce' the interface state to workaround this erratic bahaviour 00125 for (uint32_t debounce = 0; debounce < 5; debounce++) { 00126 while (IS_RUNNING) { 00127 debounce = 0; 00128 if (timeout.read_ms() > maxtime) { 00129 printf("Driver did not return to BDM mode.\r\n"); 00130 timeout.stop(); 00131 return false; 00132 } 00133 } 00134 wait_us(1); 00135 } 00136 timeout.stop(); 00137 return true; 00138 } 00139 00140 00141 //----------------------------------------------------------------------------- 00142 /** 00143 Starts a BDM resident driver at the current PC (Program Counter) or a specified 00144 if given. The driver is allowed to run for a maximum period, maxtime, specified 00145 as milliseconds. 00146 00147 @param addr BDM driver address (0 to continue from current PC) 00148 @param maxtime how long to allow driver to execute (milliseconds) 00149 00150 @return DONE, CONTINUE, ERROR 00151 00152 */ 00153 00154 uint8_t bdmProcessSyscall(void) 00155 { 00156 00157 uint32_t syscall = 0xFFFFFFFF; 00158 if (adreg_read(&syscall, 0x0) != TERM_OK) { 00159 printf("Failed to read BDM register.\r\n"); 00160 return ERROR; 00161 } 00162 syscall &= 0xFF; 00163 // printf("SYSCALL 0x%08x\r\n", syscall); 00164 switch (syscall) { 00165 case QUIT: 00166 if (adreg_read(&syscall, 0x1) != TERM_OK) { 00167 printf("Failed to read BDM register.\r\n"); 00168 return ERROR; 00169 } 00170 return DONE; 00171 case PUTS: 00172 if (!bdmSyscallPuts()) return ERROR; 00173 break; 00174 case PUTCHAR: 00175 if (!bdmSyscallPutchar()) return ERROR; 00176 break; 00177 case GETS: 00178 if (!bdmSyscallGets()) return ERROR; 00179 break; 00180 case GETCHAR: 00181 if (!bdmSyscallGetchar()) return ERROR; 00182 break; 00183 case GETSTAT: 00184 if (!bdmSyscallGetstat()) return ERROR; 00185 break; 00186 case FOPEN: 00187 if (!bdmSyscallFopen()) return ERROR; 00188 break; 00189 case FCLOSE: 00190 if (!bdmSyscallFclose()) return ERROR; 00191 break; 00192 case FREAD: 00193 if (!bdmSyscallFread()) return ERROR; 00194 break; 00195 case FWRITE: 00196 if (!bdmSyscallFwrite()) return ERROR; 00197 break; 00198 case FTELL: 00199 if (!bdmSyscallFtell()) return ERROR; 00200 break; 00201 case FSEEK: 00202 if (!bdmSyscallFseek()) return ERROR; 00203 break; 00204 case FGETS: 00205 if (!bdmSyscallFgets()) return ERROR; 00206 break; 00207 case FPUTS: 00208 if (!bdmSyscallFputs()) return ERROR; 00209 break; 00210 case EVAL: 00211 if (!bdmSyscallEval()) return ERROR; 00212 break; 00213 case FREADSREC: 00214 if (!bdmSyscallFreadsrec()) return ERROR; 00215 break; 00216 default: 00217 printf("!!! Unknown BDM Syscall !!!\r\n"); 00218 return ERROR; 00219 } 00220 return CONTINUE; 00221 } 00222 00223 00224 bool bdmSyscallPuts() 00225 { 00226 uint32_t bdm_string_address = 0, bdm_return = 0; 00227 if (adreg_read(&bdm_string_address, 0x8) != TERM_OK) { 00228 printf("Failed to read BDM register.\r\n"); 00229 return false; 00230 } 00231 // a loop to read chars from BDM into a string 00232 char bdm_string[256]; 00233 for (uint32_t i = 0; i < sizeof(bdm_string); i++) { 00234 bdm_string[i] = 0x0; 00235 } 00236 uint32_t i = 0; 00237 do { 00238 if (memread_byte((uint8_t*)(bdm_string+i), &bdm_string_address) != TERM_OK) { 00239 printf("Failed to read BDM memory at address 0x%08x.\r\n", bdm_string_address); 00240 return false; 00241 } 00242 bdm_string_address++; 00243 } while ( (bdm_string[i++] != 0x0) && (i < sizeof(bdm_string)) ); 00244 // print the string to stdout (USB virtual serial port) 00245 printf(bdm_string); 00246 // Send BDM return code in D0 (always 0x0 for PUTS) 00247 if (adreg_write(0x0, &bdm_return) != TERM_OK) { 00248 printf("Failed to write BDM register.\r\n"); 00249 return false; 00250 } 00251 return true; 00252 } 00253 00254 bool bdmSyscallPutchar() 00255 { 00256 uint32_t bdm_character = 0, bdm_return = 0; 00257 // read char from BDM 00258 if (adreg_read(&bdm_character, 0x1) != TERM_OK) { 00259 printf("Failed to read BDM register.\r\n"); 00260 return false; 00261 } 00262 // print the char to USB virtual serial port 00263 pc.putc((char)bdm_character); 00264 // Send BDM return code in D0 (always 0x0 for PUTCHAR) 00265 if (adreg_write(0x0, &bdm_return) != TERM_OK) { 00266 printf("Failed to write BDM register.\r\n"); 00267 return false; 00268 } 00269 return true; 00270 } 00271 00272 bool bdmSyscallGets() 00273 { 00274 printf("BDM GETS Syscall not supported.\r\n"); 00275 return ERROR; 00276 } 00277 00278 bool bdmSyscallGetchar() 00279 { 00280 // get a char from the USB virtual serial port 00281 uint32_t bdm_return = (uint32_t)pc.getc(); 00282 // Send the char to BDM in D0 00283 if (adreg_write(0x0, &bdm_return) != TERM_OK) { 00284 printf("Failed to write BDM register.\r\n"); 00285 return false; 00286 } 00287 return true; 00288 } 00289 00290 bool bdmSyscallGetstat(void) 00291 { 00292 printf("BDM GETSTAT Syscall not supported.\r\n"); 00293 return false; 00294 } 00295 00296 bool bdmSyscallFopen(void) 00297 { 00298 uint32_t bdm_filename_address = 0, bdm_filemode_address = 0; 00299 if (adreg_read(&bdm_filename_address, 0x8) != TERM_OK) { 00300 printf("Failed to read BDM register.\r\n"); 00301 return false; 00302 } 00303 if (adreg_read(&bdm_filemode_address, 0x9) != TERM_OK) { 00304 printf("Failed to read BDM register.\r\n"); 00305 return false; 00306 } 00307 // a loop to initialise the strings to 0x0 00308 char filename_string[80], filemode_string[5]; 00309 uint32_t i = 0; 00310 for (i = 0; i < sizeof(filename_string); i++) { 00311 filename_string[i] = 0x0; 00312 } 00313 for (i = 0; i < sizeof(filemode_string); i++) { 00314 filemode_string[i] = 0x0; 00315 } 00316 i = 0; 00317 // a loop to read chars from BDM into a string 00318 do { 00319 if (memread_byte((uint8_t*)filename_string[i], &bdm_filename_address) != TERM_OK) { 00320 printf("Failed to read BDM memory at address 0x%08x.\r\n", bdm_filename_address); 00321 return false; 00322 } 00323 bdm_filename_address++; 00324 } while ( (filename_string[i++] != 0x0) && (i < sizeof(filename_string)) ); 00325 do { 00326 if (memread_byte((uint8_t*)filemode_string[i], &bdm_filemode_address) != TERM_OK) { 00327 printf("Failed to read BDM memory at address 0x%08x.\r\n", bdm_filemode_address); 00328 return false; 00329 } 00330 bdm_filemode_address++; 00331 } while ( (filemode_string[i++] != 0x0) && (i < sizeof(filemode_string)) ); 00332 // Open the file 00333 fp = fopen(filename_string, filemode_string); // Open "modified.hex" on the local file system for reading 00334 // Send BDM return code in D0 00335 if (adreg_write(0x0, (uint32_t*)fp) != TERM_OK) { 00336 printf("Failed to write BDM register.\r\n"); 00337 return false; 00338 } 00339 return true; 00340 } 00341 00342 bool bdmSyscallFclose(void) 00343 { 00344 uint32_t close_result = fclose(fp); 00345 // Send BDM return code in D0 00346 if (adreg_write(0x0, &close_result) != TERM_OK) { 00347 printf("Failed to write BDM register.\r\n"); 00348 return false; 00349 } 00350 return true; 00351 } 00352 00353 bool bdmSyscallFread(void) 00354 { 00355 uint32_t bdm_byte_count, bdm_buffer_address, bdm_file_handle = NULL; 00356 if (adreg_read(&bdm_file_handle, 0x1) != TERM_OK) { 00357 printf("Failed to read BDM register.\r\n"); 00358 return false; 00359 } 00360 if (adreg_read(&bdm_byte_count, 0x2) != TERM_OK) { 00361 printf("Failed to read BDM register.\r\n"); 00362 return false; 00363 } 00364 if (adreg_read(&bdm_buffer_address, 0x9) != TERM_OK) { 00365 printf("Failed to read BDM register.\r\n"); 00366 return false; 00367 } 00368 uint32_t bytes_read = fread(&file_buffer[0],1,bdm_byte_count,fp); 00369 for (uint32_t byte_count = 0; byte_count < bytes_read; byte_count++) { 00370 if (byte_count == 0x0) { 00371 if(memwrite_byte(&bdm_buffer_address, file_buffer[byte_count]) != TERM_OK) return false; 00372 } else { 00373 if(memfill_byte(file_buffer[byte_count]) != TERM_OK) return false; 00374 } 00375 } 00376 if (adreg_write(0x0, &bytes_read) != TERM_OK) { 00377 printf("Failed to write BDM register.\r\n"); 00378 return false; 00379 } 00380 return true; 00381 } 00382 00383 bool bdmSyscallFwrite(void) 00384 { 00385 printf("BDM FWRITE Syscall not supported.\r\n"); 00386 return false; 00387 } 00388 00389 bool bdmSyscallFtell(void) 00390 { 00391 printf("BDM FTELL Syscall not supported.\r\n"); 00392 return false; 00393 } 00394 00395 bool bdmSyscallFseek(void) 00396 { 00397 uint32_t bdm_byte_offset, bdm_file_origin, bdm_file_handle = NULL; 00398 if (adreg_read(&bdm_file_handle, 0x1) != TERM_OK) { 00399 printf("Failed to read BDM register.\r\n"); 00400 return false; 00401 } 00402 if (adreg_read(&bdm_byte_offset, 0x2) != TERM_OK) { 00403 printf("Failed to read BDM register.\r\n"); 00404 return false; 00405 } 00406 if (adreg_read(&bdm_file_origin, 0x3) != TERM_OK) { 00407 printf("Failed to read BDM register.\r\n"); 00408 return false; 00409 } 00410 uint32_t origin; 00411 switch (bdm_file_origin) { 00412 case 0x2: 00413 origin = SEEK_END; 00414 break; 00415 case 0x1: 00416 origin = SEEK_CUR; 00417 break; 00418 case 0x0: 00419 default: 00420 origin = SEEK_SET; 00421 break; 00422 } 00423 uint32_t fseek_result = fseek ( fp ,bdm_byte_offset ,origin ); 00424 if (adreg_write(0x0, &fseek_result) != TERM_OK) { 00425 printf("Failed to write BDM register.\r\n"); 00426 return false; 00427 } 00428 return true; 00429 } 00430 00431 bool bdmSyscallFgets(void) 00432 { 00433 printf("BDM FGETS Syscall not supported.\r\n"); 00434 return false; 00435 } 00436 00437 bool bdmSyscallFputs(void) 00438 { 00439 printf("BDM FPUTS Syscall not supported.\r\n"); 00440 return false; 00441 } 00442 00443 bool bdmSyscallEval(void) 00444 { 00445 printf("BDM EVAL Syscall not supported.\r\n"); 00446 return false; 00447 } 00448 00449 bool bdmSyscallFreadsrec(void) 00450 { 00451 printf("BDM FREADSREC Syscall not supported.\r\n"); 00452 return false; 00453 }
Generated on Fri Jul 15 2022 00:43:05 by 1.7.2