Sophie Dexter
/
Just4Trionic
Just4Trionic - CAN and BDM FLASH programmer for Saab cars
bdmdriver.cpp@5:1775b4b13232, 2015-04-25 (annotated)
- Committer:
- Just4pLeisure
- Date:
- Sat Apr 25 17:07:08 2015 +0000
- Revision:
- 5:1775b4b13232
Version 1.5 Is a significant milestone.; ; Supports BDM and CAN read and write of T5.x, T7 and T8 ECU's plus T8 recovery.; A Target Resident Driver for BDM gives a big speed boost.; Supports many alternative replacement FLASH chips for T5.x ECU's;
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
Just4pLeisure | 5:1775b4b13232 | 1 | /******************************************************************************* |
Just4pLeisure | 5:1775b4b13232 | 2 | |
Just4pLeisure | 5:1775b4b13232 | 3 | bdmdriver.cpp |
Just4pLeisure | 5:1775b4b13232 | 4 | (c) 2014 by Sophie Dexter |
Just4pLeisure | 5:1775b4b13232 | 5 | |
Just4pLeisure | 5:1775b4b13232 | 6 | BD32 like 'syscall' processor for BDM resident driver functions |
Just4pLeisure | 5:1775b4b13232 | 7 | |
Just4pLeisure | 5:1775b4b13232 | 8 | ******************************************************************************** |
Just4pLeisure | 5:1775b4b13232 | 9 | |
Just4pLeisure | 5:1775b4b13232 | 10 | WARNING: Use at your own risk, sadly this software comes with no guarantees. |
Just4pLeisure | 5:1775b4b13232 | 11 | This software is provided 'free' and in good faith, but the author does not |
Just4pLeisure | 5:1775b4b13232 | 12 | accept liability for any damage arising from its use. |
Just4pLeisure | 5:1775b4b13232 | 13 | |
Just4pLeisure | 5:1775b4b13232 | 14 | *******************************************************************************/ |
Just4pLeisure | 5:1775b4b13232 | 15 | |
Just4pLeisure | 5:1775b4b13232 | 16 | #include "bdmdriver.h" |
Just4pLeisure | 5:1775b4b13232 | 17 | |
Just4pLeisure | 5:1775b4b13232 | 18 | FILE *fp = NULL; |
Just4pLeisure | 5:1775b4b13232 | 19 | |
Just4pLeisure | 5:1775b4b13232 | 20 | //private functions |
Just4pLeisure | 5:1775b4b13232 | 21 | bool bdmSyscallPuts (void); |
Just4pLeisure | 5:1775b4b13232 | 22 | bool bdmSyscallPutchar(void); |
Just4pLeisure | 5:1775b4b13232 | 23 | bool bdmSyscallGets(void); |
Just4pLeisure | 5:1775b4b13232 | 24 | bool bdmSyscallGetchar(void); |
Just4pLeisure | 5:1775b4b13232 | 25 | bool bdmSyscallGetstat(void); |
Just4pLeisure | 5:1775b4b13232 | 26 | bool bdmSyscallFopen(void); |
Just4pLeisure | 5:1775b4b13232 | 27 | bool bdmSyscallFclose(void); |
Just4pLeisure | 5:1775b4b13232 | 28 | bool bdmSyscallFread(void); |
Just4pLeisure | 5:1775b4b13232 | 29 | bool bdmSyscallFwrite(void); |
Just4pLeisure | 5:1775b4b13232 | 30 | bool bdmSyscallFtell(void); |
Just4pLeisure | 5:1775b4b13232 | 31 | bool bdmSyscallFseek(void); |
Just4pLeisure | 5:1775b4b13232 | 32 | bool bdmSyscallFgets(void); |
Just4pLeisure | 5:1775b4b13232 | 33 | bool bdmSyscallFputs(void); |
Just4pLeisure | 5:1775b4b13232 | 34 | bool bdmSyscallEval(void); |
Just4pLeisure | 5:1775b4b13232 | 35 | bool bdmSyscallFreadsrec(void); |
Just4pLeisure | 5:1775b4b13232 | 36 | |
Just4pLeisure | 5:1775b4b13232 | 37 | //----------------------------------------------------------------------------- |
Just4pLeisure | 5:1775b4b13232 | 38 | /** |
Just4pLeisure | 5:1775b4b13232 | 39 | Loads the contenst of a uint8_t array into the target's memory starting at the |
Just4pLeisure | 5:1775b4b13232 | 40 | specified address |
Just4pLeisure | 5:1775b4b13232 | 41 | |
Just4pLeisure | 5:1775b4b13232 | 42 | @param dataArray[] uint8_t array conataining data for BDM tartget |
Just4pLeisure | 5:1775b4b13232 | 43 | @param startAddress Start address to load BDM memory to |
Just4pLeisure | 5:1775b4b13232 | 44 | |
Just4pLeisure | 5:1775b4b13232 | 45 | @return succ / fail |
Just4pLeisure | 5:1775b4b13232 | 46 | */ |
Just4pLeisure | 5:1775b4b13232 | 47 | bool bdmLoadMemory(uint8_t dataArray[], uint32_t startAddress, uint32_t dataArraySize) |
Just4pLeisure | 5:1775b4b13232 | 48 | { |
Just4pLeisure | 5:1775b4b13232 | 49 | // for (uint32_t i = 0; i < sizeof(residentDriver); i++) { |
Just4pLeisure | 5:1775b4b13232 | 50 | // if(memwrite_byte(&driverAddress, residentDriver[i]) != TERM_OK) return false; |
Just4pLeisure | 5:1775b4b13232 | 51 | // driverAddress++; |
Just4pLeisure | 5:1775b4b13232 | 52 | // } |
Just4pLeisure | 5:1775b4b13232 | 53 | uint32_t driverSize = dataArraySize; |
Just4pLeisure | 5:1775b4b13232 | 54 | uint32_t driverOffset = 0; |
Just4pLeisure | 5:1775b4b13232 | 55 | uint32_t driverLong = 0; |
Just4pLeisure | 5:1775b4b13232 | 56 | uint16_t driverWord = 0; |
Just4pLeisure | 5:1775b4b13232 | 57 | uint8_t driverByte = 0; |
Just4pLeisure | 5:1775b4b13232 | 58 | // Check that there is something to send |
Just4pLeisure | 5:1775b4b13232 | 59 | if (driverSize == 0) return false; |
Just4pLeisure | 5:1775b4b13232 | 60 | // Send the first 1-4 bytes as efficiently as possible over BDM |
Just4pLeisure | 5:1775b4b13232 | 61 | switch (driverSize % 4) { |
Just4pLeisure | 5:1775b4b13232 | 62 | case 3: |
Just4pLeisure | 5:1775b4b13232 | 63 | driverWord = (dataArray[driverOffset++] << 8) | dataArray[driverOffset++]; |
Just4pLeisure | 5:1775b4b13232 | 64 | if(memwrite_word(&startAddress, driverWord) != TERM_OK) return false; |
Just4pLeisure | 5:1775b4b13232 | 65 | driverByte = dataArray[driverOffset++]; |
Just4pLeisure | 5:1775b4b13232 | 66 | if(memfill_byte(driverByte) != TERM_OK) return false; |
Just4pLeisure | 5:1775b4b13232 | 67 | break; |
Just4pLeisure | 5:1775b4b13232 | 68 | case 2: |
Just4pLeisure | 5:1775b4b13232 | 69 | driverWord = (dataArray[driverOffset++] << 8) | dataArray[driverOffset++]; |
Just4pLeisure | 5:1775b4b13232 | 70 | if(memwrite_word(&startAddress, driverWord) != TERM_OK) return false; |
Just4pLeisure | 5:1775b4b13232 | 71 | break; |
Just4pLeisure | 5:1775b4b13232 | 72 | case 1: |
Just4pLeisure | 5:1775b4b13232 | 73 | driverByte = dataArray[driverOffset++]; |
Just4pLeisure | 5:1775b4b13232 | 74 | if(memwrite_byte(&startAddress, driverByte) != TERM_OK) return false; |
Just4pLeisure | 5:1775b4b13232 | 75 | break; |
Just4pLeisure | 5:1775b4b13232 | 76 | case 0: |
Just4pLeisure | 5:1775b4b13232 | 77 | for (uint32_t i = 0; i < 4; i++) { |
Just4pLeisure | 5:1775b4b13232 | 78 | driverLong <<= 8; |
Just4pLeisure | 5:1775b4b13232 | 79 | driverLong |= dataArray[driverOffset++]; |
Just4pLeisure | 5:1775b4b13232 | 80 | } |
Just4pLeisure | 5:1775b4b13232 | 81 | if(memwrite_long(&startAddress, &driverLong) != TERM_OK) return false; |
Just4pLeisure | 5:1775b4b13232 | 82 | break; |
Just4pLeisure | 5:1775b4b13232 | 83 | // default: // There shouldn't be a default case |
Just4pLeisure | 5:1775b4b13232 | 84 | } |
Just4pLeisure | 5:1775b4b13232 | 85 | // transfer the rest as 'longs' to make best use of BDM transfer speed |
Just4pLeisure | 5:1775b4b13232 | 86 | // printf("driverOffset 0x%08x, driverSize 0x%08x\r\n", driverOffset, driverSize); |
Just4pLeisure | 5:1775b4b13232 | 87 | while (driverOffset < driverSize) { |
Just4pLeisure | 5:1775b4b13232 | 88 | for (uint32_t i = 0; i < 4; i++) { |
Just4pLeisure | 5:1775b4b13232 | 89 | driverLong <<= 8; |
Just4pLeisure | 5:1775b4b13232 | 90 | driverLong |= dataArray[driverOffset++]; |
Just4pLeisure | 5:1775b4b13232 | 91 | } |
Just4pLeisure | 5:1775b4b13232 | 92 | if(memfill_long(&driverLong) != TERM_OK) return false; |
Just4pLeisure | 5:1775b4b13232 | 93 | } |
Just4pLeisure | 5:1775b4b13232 | 94 | // printf("driverOffset 0x%08x, driverSize 0x%08x\r\n", driverOffset, driverSize); |
Just4pLeisure | 5:1775b4b13232 | 95 | return true; |
Just4pLeisure | 5:1775b4b13232 | 96 | } |
Just4pLeisure | 5:1775b4b13232 | 97 | |
Just4pLeisure | 5:1775b4b13232 | 98 | //----------------------------------------------------------------------------- |
Just4pLeisure | 5:1775b4b13232 | 99 | /** |
Just4pLeisure | 5:1775b4b13232 | 100 | Starts a BDM resident driver at the current PC (Program Counter) or a specified |
Just4pLeisure | 5:1775b4b13232 | 101 | if given. The driver is allowed to run for a maximum period, maxtime, specified |
Just4pLeisure | 5:1775b4b13232 | 102 | as milliseconds. |
Just4pLeisure | 5:1775b4b13232 | 103 | |
Just4pLeisure | 5:1775b4b13232 | 104 | @param addr BDM driver address (0 to continue from current PC) |
Just4pLeisure | 5:1775b4b13232 | 105 | @param maxtime how long to allow driver to execute (milliseconds) |
Just4pLeisure | 5:1775b4b13232 | 106 | |
Just4pLeisure | 5:1775b4b13232 | 107 | @return succ / fail |
Just4pLeisure | 5:1775b4b13232 | 108 | */ |
Just4pLeisure | 5:1775b4b13232 | 109 | bool bdmRunDriver(uint32_t addr, uint32_t maxtime) |
Just4pLeisure | 5:1775b4b13232 | 110 | { |
Just4pLeisure | 5:1775b4b13232 | 111 | // Start BDM driver and allow it up to 200 milliseconds to update 256 Bytes |
Just4pLeisure | 5:1775b4b13232 | 112 | // Upto 25 pulses per byte, 16us per pulse, 256 Bytes |
Just4pLeisure | 5:1775b4b13232 | 113 | // 25 * 16 * 256 = 102,400us plus overhead for driver code execution time |
Just4pLeisure | 5:1775b4b13232 | 114 | // Allowing up to 200 milliseconds seems like a good allowance. |
Just4pLeisure | 5:1775b4b13232 | 115 | if (run_chip(&addr) != TERM_OK) { |
Just4pLeisure | 5:1775b4b13232 | 116 | printf("Failed to start BDM driver.\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 117 | return false; |
Just4pLeisure | 5:1775b4b13232 | 118 | } |
Just4pLeisure | 5:1775b4b13232 | 119 | timeout.reset(); |
Just4pLeisure | 5:1775b4b13232 | 120 | timeout.start(); |
Just4pLeisure | 5:1775b4b13232 | 121 | // T5 ECUs' BDM interface seem to have problems when the running the CPU and |
Just4pLeisure | 5:1775b4b13232 | 122 | // sometimes shows the CPU briefly switching between showing BDM mode or that |
Just4pLeisure | 5:1775b4b13232 | 123 | // the CPU is running. |
Just4pLeisure | 5:1775b4b13232 | 124 | // I 'debounce' the interface state to workaround this erratic bahaviour |
Just4pLeisure | 5:1775b4b13232 | 125 | for (uint32_t debounce = 0; debounce < 5; debounce++) { |
Just4pLeisure | 5:1775b4b13232 | 126 | while (IS_RUNNING) { |
Just4pLeisure | 5:1775b4b13232 | 127 | debounce = 0; |
Just4pLeisure | 5:1775b4b13232 | 128 | if (timeout.read_ms() > maxtime) { |
Just4pLeisure | 5:1775b4b13232 | 129 | printf("Driver did not return to BDM mode.\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 130 | timeout.stop(); |
Just4pLeisure | 5:1775b4b13232 | 131 | return false; |
Just4pLeisure | 5:1775b4b13232 | 132 | } |
Just4pLeisure | 5:1775b4b13232 | 133 | } |
Just4pLeisure | 5:1775b4b13232 | 134 | wait_us(1); |
Just4pLeisure | 5:1775b4b13232 | 135 | } |
Just4pLeisure | 5:1775b4b13232 | 136 | timeout.stop(); |
Just4pLeisure | 5:1775b4b13232 | 137 | return true; |
Just4pLeisure | 5:1775b4b13232 | 138 | } |
Just4pLeisure | 5:1775b4b13232 | 139 | |
Just4pLeisure | 5:1775b4b13232 | 140 | |
Just4pLeisure | 5:1775b4b13232 | 141 | //----------------------------------------------------------------------------- |
Just4pLeisure | 5:1775b4b13232 | 142 | /** |
Just4pLeisure | 5:1775b4b13232 | 143 | Starts a BDM resident driver at the current PC (Program Counter) or a specified |
Just4pLeisure | 5:1775b4b13232 | 144 | if given. The driver is allowed to run for a maximum period, maxtime, specified |
Just4pLeisure | 5:1775b4b13232 | 145 | as milliseconds. |
Just4pLeisure | 5:1775b4b13232 | 146 | |
Just4pLeisure | 5:1775b4b13232 | 147 | @param addr BDM driver address (0 to continue from current PC) |
Just4pLeisure | 5:1775b4b13232 | 148 | @param maxtime how long to allow driver to execute (milliseconds) |
Just4pLeisure | 5:1775b4b13232 | 149 | |
Just4pLeisure | 5:1775b4b13232 | 150 | @return DONE, CONTINUE, ERROR |
Just4pLeisure | 5:1775b4b13232 | 151 | |
Just4pLeisure | 5:1775b4b13232 | 152 | */ |
Just4pLeisure | 5:1775b4b13232 | 153 | |
Just4pLeisure | 5:1775b4b13232 | 154 | uint8_t bdmProcessSyscall(void) |
Just4pLeisure | 5:1775b4b13232 | 155 | { |
Just4pLeisure | 5:1775b4b13232 | 156 | |
Just4pLeisure | 5:1775b4b13232 | 157 | uint32_t syscall = 0xFFFFFFFF; |
Just4pLeisure | 5:1775b4b13232 | 158 | if (adreg_read(&syscall, 0x0) != TERM_OK) { |
Just4pLeisure | 5:1775b4b13232 | 159 | printf("Failed to read BDM register.\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 160 | return ERROR; |
Just4pLeisure | 5:1775b4b13232 | 161 | } |
Just4pLeisure | 5:1775b4b13232 | 162 | syscall &= 0xFF; |
Just4pLeisure | 5:1775b4b13232 | 163 | // printf("SYSCALL 0x%08x\r\n", syscall); |
Just4pLeisure | 5:1775b4b13232 | 164 | switch (syscall) { |
Just4pLeisure | 5:1775b4b13232 | 165 | case QUIT: |
Just4pLeisure | 5:1775b4b13232 | 166 | if (adreg_read(&syscall, 0x1) != TERM_OK) { |
Just4pLeisure | 5:1775b4b13232 | 167 | printf("Failed to read BDM register.\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 168 | return ERROR; |
Just4pLeisure | 5:1775b4b13232 | 169 | } |
Just4pLeisure | 5:1775b4b13232 | 170 | return DONE; |
Just4pLeisure | 5:1775b4b13232 | 171 | case PUTS: |
Just4pLeisure | 5:1775b4b13232 | 172 | if (!bdmSyscallPuts()) return ERROR; |
Just4pLeisure | 5:1775b4b13232 | 173 | break; |
Just4pLeisure | 5:1775b4b13232 | 174 | case PUTCHAR: |
Just4pLeisure | 5:1775b4b13232 | 175 | if (!bdmSyscallPutchar()) return ERROR; |
Just4pLeisure | 5:1775b4b13232 | 176 | break; |
Just4pLeisure | 5:1775b4b13232 | 177 | case GETS: |
Just4pLeisure | 5:1775b4b13232 | 178 | if (!bdmSyscallGets()) return ERROR; |
Just4pLeisure | 5:1775b4b13232 | 179 | break; |
Just4pLeisure | 5:1775b4b13232 | 180 | case GETCHAR: |
Just4pLeisure | 5:1775b4b13232 | 181 | if (!bdmSyscallGetchar()) return ERROR; |
Just4pLeisure | 5:1775b4b13232 | 182 | break; |
Just4pLeisure | 5:1775b4b13232 | 183 | case GETSTAT: |
Just4pLeisure | 5:1775b4b13232 | 184 | if (!bdmSyscallGetstat()) return ERROR; |
Just4pLeisure | 5:1775b4b13232 | 185 | break; |
Just4pLeisure | 5:1775b4b13232 | 186 | case FOPEN: |
Just4pLeisure | 5:1775b4b13232 | 187 | if (!bdmSyscallFopen()) return ERROR; |
Just4pLeisure | 5:1775b4b13232 | 188 | break; |
Just4pLeisure | 5:1775b4b13232 | 189 | case FCLOSE: |
Just4pLeisure | 5:1775b4b13232 | 190 | if (!bdmSyscallFclose()) return ERROR; |
Just4pLeisure | 5:1775b4b13232 | 191 | break; |
Just4pLeisure | 5:1775b4b13232 | 192 | case FREAD: |
Just4pLeisure | 5:1775b4b13232 | 193 | if (!bdmSyscallFread()) return ERROR; |
Just4pLeisure | 5:1775b4b13232 | 194 | break; |
Just4pLeisure | 5:1775b4b13232 | 195 | case FWRITE: |
Just4pLeisure | 5:1775b4b13232 | 196 | if (!bdmSyscallFwrite()) return ERROR; |
Just4pLeisure | 5:1775b4b13232 | 197 | break; |
Just4pLeisure | 5:1775b4b13232 | 198 | case FTELL: |
Just4pLeisure | 5:1775b4b13232 | 199 | if (!bdmSyscallFtell()) return ERROR; |
Just4pLeisure | 5:1775b4b13232 | 200 | break; |
Just4pLeisure | 5:1775b4b13232 | 201 | case FSEEK: |
Just4pLeisure | 5:1775b4b13232 | 202 | if (!bdmSyscallFseek()) return ERROR; |
Just4pLeisure | 5:1775b4b13232 | 203 | break; |
Just4pLeisure | 5:1775b4b13232 | 204 | case FGETS: |
Just4pLeisure | 5:1775b4b13232 | 205 | if (!bdmSyscallFgets()) return ERROR; |
Just4pLeisure | 5:1775b4b13232 | 206 | break; |
Just4pLeisure | 5:1775b4b13232 | 207 | case FPUTS: |
Just4pLeisure | 5:1775b4b13232 | 208 | if (!bdmSyscallFputs()) return ERROR; |
Just4pLeisure | 5:1775b4b13232 | 209 | break; |
Just4pLeisure | 5:1775b4b13232 | 210 | case EVAL: |
Just4pLeisure | 5:1775b4b13232 | 211 | if (!bdmSyscallEval()) return ERROR; |
Just4pLeisure | 5:1775b4b13232 | 212 | break; |
Just4pLeisure | 5:1775b4b13232 | 213 | case FREADSREC: |
Just4pLeisure | 5:1775b4b13232 | 214 | if (!bdmSyscallFreadsrec()) return ERROR; |
Just4pLeisure | 5:1775b4b13232 | 215 | break; |
Just4pLeisure | 5:1775b4b13232 | 216 | default: |
Just4pLeisure | 5:1775b4b13232 | 217 | printf("!!! Unknown BDM Syscall !!!\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 218 | return ERROR; |
Just4pLeisure | 5:1775b4b13232 | 219 | } |
Just4pLeisure | 5:1775b4b13232 | 220 | return CONTINUE; |
Just4pLeisure | 5:1775b4b13232 | 221 | } |
Just4pLeisure | 5:1775b4b13232 | 222 | |
Just4pLeisure | 5:1775b4b13232 | 223 | |
Just4pLeisure | 5:1775b4b13232 | 224 | bool bdmSyscallPuts() |
Just4pLeisure | 5:1775b4b13232 | 225 | { |
Just4pLeisure | 5:1775b4b13232 | 226 | uint32_t bdm_string_address = 0, bdm_return = 0; |
Just4pLeisure | 5:1775b4b13232 | 227 | if (adreg_read(&bdm_string_address, 0x8) != TERM_OK) { |
Just4pLeisure | 5:1775b4b13232 | 228 | printf("Failed to read BDM register.\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 229 | return false; |
Just4pLeisure | 5:1775b4b13232 | 230 | } |
Just4pLeisure | 5:1775b4b13232 | 231 | // a loop to read chars from BDM into a string |
Just4pLeisure | 5:1775b4b13232 | 232 | char bdm_string[256]; |
Just4pLeisure | 5:1775b4b13232 | 233 | for (uint32_t i = 0; i < sizeof(bdm_string); i++) { |
Just4pLeisure | 5:1775b4b13232 | 234 | bdm_string[i] = 0x0; |
Just4pLeisure | 5:1775b4b13232 | 235 | } |
Just4pLeisure | 5:1775b4b13232 | 236 | uint32_t i = 0; |
Just4pLeisure | 5:1775b4b13232 | 237 | do { |
Just4pLeisure | 5:1775b4b13232 | 238 | if (memread_byte((uint8_t*)(bdm_string+i), &bdm_string_address) != TERM_OK) { |
Just4pLeisure | 5:1775b4b13232 | 239 | printf("Failed to read BDM memory at address 0x%08x.\r\n", bdm_string_address); |
Just4pLeisure | 5:1775b4b13232 | 240 | return false; |
Just4pLeisure | 5:1775b4b13232 | 241 | } |
Just4pLeisure | 5:1775b4b13232 | 242 | bdm_string_address++; |
Just4pLeisure | 5:1775b4b13232 | 243 | } while ( (bdm_string[i++] != 0x0) && (i < sizeof(bdm_string)) ); |
Just4pLeisure | 5:1775b4b13232 | 244 | // print the string to stdout (USB virtual serial port) |
Just4pLeisure | 5:1775b4b13232 | 245 | printf(bdm_string); |
Just4pLeisure | 5:1775b4b13232 | 246 | // Send BDM return code in D0 (always 0x0 for PUTS) |
Just4pLeisure | 5:1775b4b13232 | 247 | if (adreg_write(0x0, &bdm_return) != TERM_OK) { |
Just4pLeisure | 5:1775b4b13232 | 248 | printf("Failed to write BDM register.\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 249 | return false; |
Just4pLeisure | 5:1775b4b13232 | 250 | } |
Just4pLeisure | 5:1775b4b13232 | 251 | return true; |
Just4pLeisure | 5:1775b4b13232 | 252 | } |
Just4pLeisure | 5:1775b4b13232 | 253 | |
Just4pLeisure | 5:1775b4b13232 | 254 | bool bdmSyscallPutchar() |
Just4pLeisure | 5:1775b4b13232 | 255 | { |
Just4pLeisure | 5:1775b4b13232 | 256 | uint32_t bdm_character = 0, bdm_return = 0; |
Just4pLeisure | 5:1775b4b13232 | 257 | // read char from BDM |
Just4pLeisure | 5:1775b4b13232 | 258 | if (adreg_read(&bdm_character, 0x1) != TERM_OK) { |
Just4pLeisure | 5:1775b4b13232 | 259 | printf("Failed to read BDM register.\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 260 | return false; |
Just4pLeisure | 5:1775b4b13232 | 261 | } |
Just4pLeisure | 5:1775b4b13232 | 262 | // print the char to USB virtual serial port |
Just4pLeisure | 5:1775b4b13232 | 263 | pc.putc((char)bdm_character); |
Just4pLeisure | 5:1775b4b13232 | 264 | // Send BDM return code in D0 (always 0x0 for PUTCHAR) |
Just4pLeisure | 5:1775b4b13232 | 265 | if (adreg_write(0x0, &bdm_return) != TERM_OK) { |
Just4pLeisure | 5:1775b4b13232 | 266 | printf("Failed to write BDM register.\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 267 | return false; |
Just4pLeisure | 5:1775b4b13232 | 268 | } |
Just4pLeisure | 5:1775b4b13232 | 269 | return true; |
Just4pLeisure | 5:1775b4b13232 | 270 | } |
Just4pLeisure | 5:1775b4b13232 | 271 | |
Just4pLeisure | 5:1775b4b13232 | 272 | bool bdmSyscallGets() |
Just4pLeisure | 5:1775b4b13232 | 273 | { |
Just4pLeisure | 5:1775b4b13232 | 274 | printf("BDM GETS Syscall not supported.\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 275 | return ERROR; |
Just4pLeisure | 5:1775b4b13232 | 276 | } |
Just4pLeisure | 5:1775b4b13232 | 277 | |
Just4pLeisure | 5:1775b4b13232 | 278 | bool bdmSyscallGetchar() |
Just4pLeisure | 5:1775b4b13232 | 279 | { |
Just4pLeisure | 5:1775b4b13232 | 280 | // get a char from the USB virtual serial port |
Just4pLeisure | 5:1775b4b13232 | 281 | uint32_t bdm_return = (uint32_t)pc.getc(); |
Just4pLeisure | 5:1775b4b13232 | 282 | // Send the char to BDM in D0 |
Just4pLeisure | 5:1775b4b13232 | 283 | if (adreg_write(0x0, &bdm_return) != TERM_OK) { |
Just4pLeisure | 5:1775b4b13232 | 284 | printf("Failed to write BDM register.\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 285 | return false; |
Just4pLeisure | 5:1775b4b13232 | 286 | } |
Just4pLeisure | 5:1775b4b13232 | 287 | return true; |
Just4pLeisure | 5:1775b4b13232 | 288 | } |
Just4pLeisure | 5:1775b4b13232 | 289 | |
Just4pLeisure | 5:1775b4b13232 | 290 | bool bdmSyscallGetstat(void) |
Just4pLeisure | 5:1775b4b13232 | 291 | { |
Just4pLeisure | 5:1775b4b13232 | 292 | printf("BDM GETSTAT Syscall not supported.\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 293 | return false; |
Just4pLeisure | 5:1775b4b13232 | 294 | } |
Just4pLeisure | 5:1775b4b13232 | 295 | |
Just4pLeisure | 5:1775b4b13232 | 296 | bool bdmSyscallFopen(void) |
Just4pLeisure | 5:1775b4b13232 | 297 | { |
Just4pLeisure | 5:1775b4b13232 | 298 | uint32_t bdm_filename_address = 0, bdm_filemode_address = 0; |
Just4pLeisure | 5:1775b4b13232 | 299 | if (adreg_read(&bdm_filename_address, 0x8) != TERM_OK) { |
Just4pLeisure | 5:1775b4b13232 | 300 | printf("Failed to read BDM register.\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 301 | return false; |
Just4pLeisure | 5:1775b4b13232 | 302 | } |
Just4pLeisure | 5:1775b4b13232 | 303 | if (adreg_read(&bdm_filemode_address, 0x9) != TERM_OK) { |
Just4pLeisure | 5:1775b4b13232 | 304 | printf("Failed to read BDM register.\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 305 | return false; |
Just4pLeisure | 5:1775b4b13232 | 306 | } |
Just4pLeisure | 5:1775b4b13232 | 307 | // a loop to initialise the strings to 0x0 |
Just4pLeisure | 5:1775b4b13232 | 308 | char filename_string[80], filemode_string[5]; |
Just4pLeisure | 5:1775b4b13232 | 309 | uint32_t i = 0; |
Just4pLeisure | 5:1775b4b13232 | 310 | for (i = 0; i < sizeof(filename_string); i++) { |
Just4pLeisure | 5:1775b4b13232 | 311 | filename_string[i] = 0x0; |
Just4pLeisure | 5:1775b4b13232 | 312 | } |
Just4pLeisure | 5:1775b4b13232 | 313 | for (i = 0; i < sizeof(filemode_string); i++) { |
Just4pLeisure | 5:1775b4b13232 | 314 | filemode_string[i] = 0x0; |
Just4pLeisure | 5:1775b4b13232 | 315 | } |
Just4pLeisure | 5:1775b4b13232 | 316 | i = 0; |
Just4pLeisure | 5:1775b4b13232 | 317 | // a loop to read chars from BDM into a string |
Just4pLeisure | 5:1775b4b13232 | 318 | do { |
Just4pLeisure | 5:1775b4b13232 | 319 | if (memread_byte((uint8_t*)filename_string[i], &bdm_filename_address) != TERM_OK) { |
Just4pLeisure | 5:1775b4b13232 | 320 | printf("Failed to read BDM memory at address 0x%08x.\r\n", bdm_filename_address); |
Just4pLeisure | 5:1775b4b13232 | 321 | return false; |
Just4pLeisure | 5:1775b4b13232 | 322 | } |
Just4pLeisure | 5:1775b4b13232 | 323 | bdm_filename_address++; |
Just4pLeisure | 5:1775b4b13232 | 324 | } while ( (filename_string[i++] != 0x0) && (i < sizeof(filename_string)) ); |
Just4pLeisure | 5:1775b4b13232 | 325 | do { |
Just4pLeisure | 5:1775b4b13232 | 326 | if (memread_byte((uint8_t*)filemode_string[i], &bdm_filemode_address) != TERM_OK) { |
Just4pLeisure | 5:1775b4b13232 | 327 | printf("Failed to read BDM memory at address 0x%08x.\r\n", bdm_filemode_address); |
Just4pLeisure | 5:1775b4b13232 | 328 | return false; |
Just4pLeisure | 5:1775b4b13232 | 329 | } |
Just4pLeisure | 5:1775b4b13232 | 330 | bdm_filemode_address++; |
Just4pLeisure | 5:1775b4b13232 | 331 | } while ( (filemode_string[i++] != 0x0) && (i < sizeof(filemode_string)) ); |
Just4pLeisure | 5:1775b4b13232 | 332 | // Open the file |
Just4pLeisure | 5:1775b4b13232 | 333 | fp = fopen(filename_string, filemode_string); // Open "modified.hex" on the local file system for reading |
Just4pLeisure | 5:1775b4b13232 | 334 | // Send BDM return code in D0 |
Just4pLeisure | 5:1775b4b13232 | 335 | if (adreg_write(0x0, (uint32_t*)fp) != TERM_OK) { |
Just4pLeisure | 5:1775b4b13232 | 336 | printf("Failed to write BDM register.\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 337 | return false; |
Just4pLeisure | 5:1775b4b13232 | 338 | } |
Just4pLeisure | 5:1775b4b13232 | 339 | return true; |
Just4pLeisure | 5:1775b4b13232 | 340 | } |
Just4pLeisure | 5:1775b4b13232 | 341 | |
Just4pLeisure | 5:1775b4b13232 | 342 | bool bdmSyscallFclose(void) |
Just4pLeisure | 5:1775b4b13232 | 343 | { |
Just4pLeisure | 5:1775b4b13232 | 344 | uint32_t close_result = fclose(fp); |
Just4pLeisure | 5:1775b4b13232 | 345 | // Send BDM return code in D0 |
Just4pLeisure | 5:1775b4b13232 | 346 | if (adreg_write(0x0, &close_result) != TERM_OK) { |
Just4pLeisure | 5:1775b4b13232 | 347 | printf("Failed to write BDM register.\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 348 | return false; |
Just4pLeisure | 5:1775b4b13232 | 349 | } |
Just4pLeisure | 5:1775b4b13232 | 350 | return true; |
Just4pLeisure | 5:1775b4b13232 | 351 | } |
Just4pLeisure | 5:1775b4b13232 | 352 | |
Just4pLeisure | 5:1775b4b13232 | 353 | bool bdmSyscallFread(void) |
Just4pLeisure | 5:1775b4b13232 | 354 | { |
Just4pLeisure | 5:1775b4b13232 | 355 | uint32_t bdm_byte_count, bdm_buffer_address, bdm_file_handle = NULL; |
Just4pLeisure | 5:1775b4b13232 | 356 | if (adreg_read(&bdm_file_handle, 0x1) != TERM_OK) { |
Just4pLeisure | 5:1775b4b13232 | 357 | printf("Failed to read BDM register.\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 358 | return false; |
Just4pLeisure | 5:1775b4b13232 | 359 | } |
Just4pLeisure | 5:1775b4b13232 | 360 | if (adreg_read(&bdm_byte_count, 0x2) != TERM_OK) { |
Just4pLeisure | 5:1775b4b13232 | 361 | printf("Failed to read BDM register.\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 362 | return false; |
Just4pLeisure | 5:1775b4b13232 | 363 | } |
Just4pLeisure | 5:1775b4b13232 | 364 | if (adreg_read(&bdm_buffer_address, 0x9) != TERM_OK) { |
Just4pLeisure | 5:1775b4b13232 | 365 | printf("Failed to read BDM register.\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 366 | return false; |
Just4pLeisure | 5:1775b4b13232 | 367 | } |
Just4pLeisure | 5:1775b4b13232 | 368 | uint32_t bytes_read = fread(&file_buffer[0],1,bdm_byte_count,fp); |
Just4pLeisure | 5:1775b4b13232 | 369 | for (uint32_t byte_count = 0; byte_count < bytes_read; byte_count++) { |
Just4pLeisure | 5:1775b4b13232 | 370 | if (byte_count == 0x0) { |
Just4pLeisure | 5:1775b4b13232 | 371 | if(memwrite_byte(&bdm_buffer_address, file_buffer[byte_count]) != TERM_OK) return false; |
Just4pLeisure | 5:1775b4b13232 | 372 | } else { |
Just4pLeisure | 5:1775b4b13232 | 373 | if(memfill_byte(file_buffer[byte_count]) != TERM_OK) return false; |
Just4pLeisure | 5:1775b4b13232 | 374 | } |
Just4pLeisure | 5:1775b4b13232 | 375 | } |
Just4pLeisure | 5:1775b4b13232 | 376 | if (adreg_write(0x0, &bytes_read) != TERM_OK) { |
Just4pLeisure | 5:1775b4b13232 | 377 | printf("Failed to write BDM register.\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 378 | return false; |
Just4pLeisure | 5:1775b4b13232 | 379 | } |
Just4pLeisure | 5:1775b4b13232 | 380 | return true; |
Just4pLeisure | 5:1775b4b13232 | 381 | } |
Just4pLeisure | 5:1775b4b13232 | 382 | |
Just4pLeisure | 5:1775b4b13232 | 383 | bool bdmSyscallFwrite(void) |
Just4pLeisure | 5:1775b4b13232 | 384 | { |
Just4pLeisure | 5:1775b4b13232 | 385 | printf("BDM FWRITE Syscall not supported.\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 386 | return false; |
Just4pLeisure | 5:1775b4b13232 | 387 | } |
Just4pLeisure | 5:1775b4b13232 | 388 | |
Just4pLeisure | 5:1775b4b13232 | 389 | bool bdmSyscallFtell(void) |
Just4pLeisure | 5:1775b4b13232 | 390 | { |
Just4pLeisure | 5:1775b4b13232 | 391 | printf("BDM FTELL Syscall not supported.\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 392 | return false; |
Just4pLeisure | 5:1775b4b13232 | 393 | } |
Just4pLeisure | 5:1775b4b13232 | 394 | |
Just4pLeisure | 5:1775b4b13232 | 395 | bool bdmSyscallFseek(void) |
Just4pLeisure | 5:1775b4b13232 | 396 | { |
Just4pLeisure | 5:1775b4b13232 | 397 | uint32_t bdm_byte_offset, bdm_file_origin, bdm_file_handle = NULL; |
Just4pLeisure | 5:1775b4b13232 | 398 | if (adreg_read(&bdm_file_handle, 0x1) != TERM_OK) { |
Just4pLeisure | 5:1775b4b13232 | 399 | printf("Failed to read BDM register.\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 400 | return false; |
Just4pLeisure | 5:1775b4b13232 | 401 | } |
Just4pLeisure | 5:1775b4b13232 | 402 | if (adreg_read(&bdm_byte_offset, 0x2) != TERM_OK) { |
Just4pLeisure | 5:1775b4b13232 | 403 | printf("Failed to read BDM register.\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 404 | return false; |
Just4pLeisure | 5:1775b4b13232 | 405 | } |
Just4pLeisure | 5:1775b4b13232 | 406 | if (adreg_read(&bdm_file_origin, 0x3) != TERM_OK) { |
Just4pLeisure | 5:1775b4b13232 | 407 | printf("Failed to read BDM register.\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 408 | return false; |
Just4pLeisure | 5:1775b4b13232 | 409 | } |
Just4pLeisure | 5:1775b4b13232 | 410 | uint32_t origin; |
Just4pLeisure | 5:1775b4b13232 | 411 | switch (bdm_file_origin) { |
Just4pLeisure | 5:1775b4b13232 | 412 | case 0x2: |
Just4pLeisure | 5:1775b4b13232 | 413 | origin = SEEK_END; |
Just4pLeisure | 5:1775b4b13232 | 414 | break; |
Just4pLeisure | 5:1775b4b13232 | 415 | case 0x1: |
Just4pLeisure | 5:1775b4b13232 | 416 | origin = SEEK_CUR; |
Just4pLeisure | 5:1775b4b13232 | 417 | break; |
Just4pLeisure | 5:1775b4b13232 | 418 | case 0x0: |
Just4pLeisure | 5:1775b4b13232 | 419 | default: |
Just4pLeisure | 5:1775b4b13232 | 420 | origin = SEEK_SET; |
Just4pLeisure | 5:1775b4b13232 | 421 | break; |
Just4pLeisure | 5:1775b4b13232 | 422 | } |
Just4pLeisure | 5:1775b4b13232 | 423 | uint32_t fseek_result = fseek ( fp ,bdm_byte_offset ,origin ); |
Just4pLeisure | 5:1775b4b13232 | 424 | if (adreg_write(0x0, &fseek_result) != TERM_OK) { |
Just4pLeisure | 5:1775b4b13232 | 425 | printf("Failed to write BDM register.\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 426 | return false; |
Just4pLeisure | 5:1775b4b13232 | 427 | } |
Just4pLeisure | 5:1775b4b13232 | 428 | return true; |
Just4pLeisure | 5:1775b4b13232 | 429 | } |
Just4pLeisure | 5:1775b4b13232 | 430 | |
Just4pLeisure | 5:1775b4b13232 | 431 | bool bdmSyscallFgets(void) |
Just4pLeisure | 5:1775b4b13232 | 432 | { |
Just4pLeisure | 5:1775b4b13232 | 433 | printf("BDM FGETS Syscall not supported.\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 434 | return false; |
Just4pLeisure | 5:1775b4b13232 | 435 | } |
Just4pLeisure | 5:1775b4b13232 | 436 | |
Just4pLeisure | 5:1775b4b13232 | 437 | bool bdmSyscallFputs(void) |
Just4pLeisure | 5:1775b4b13232 | 438 | { |
Just4pLeisure | 5:1775b4b13232 | 439 | printf("BDM FPUTS Syscall not supported.\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 440 | return false; |
Just4pLeisure | 5:1775b4b13232 | 441 | } |
Just4pLeisure | 5:1775b4b13232 | 442 | |
Just4pLeisure | 5:1775b4b13232 | 443 | bool bdmSyscallEval(void) |
Just4pLeisure | 5:1775b4b13232 | 444 | { |
Just4pLeisure | 5:1775b4b13232 | 445 | printf("BDM EVAL Syscall not supported.\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 446 | return false; |
Just4pLeisure | 5:1775b4b13232 | 447 | } |
Just4pLeisure | 5:1775b4b13232 | 448 | |
Just4pLeisure | 5:1775b4b13232 | 449 | bool bdmSyscallFreadsrec(void) |
Just4pLeisure | 5:1775b4b13232 | 450 | { |
Just4pLeisure | 5:1775b4b13232 | 451 | printf("BDM FREADSREC Syscall not supported.\r\n"); |
Just4pLeisure | 5:1775b4b13232 | 452 | return false; |
Just4pLeisure | 5:1775b4b13232 | 453 | } |