├── picrel.jpg ├── defs.h ├── .gitignore ├── XNAND.h ├── debug.py ├── LICENSE ├── XSPI.h ├── RPI-XSVF.md ├── README.md ├── XNAND.cpp ├── XSPI.cpp ├── xbox-teensy-flasher.ino └── xflash-serial.py /picrel.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/walczakp/xbox360-flasher/HEAD/picrel.jpg -------------------------------------------------------------------------------- /defs.h: -------------------------------------------------------------------------------- 1 | #ifndef _DEFS_H_ 2 | #define _DEFS_H_ 3 | 4 | #define REQ_DATAREAD 0x01 5 | #define REQ_DATAWRITE 0x02 6 | #define REQ_DATAINIT 0x03 7 | #define REQ_DATADEINIT 0x04 8 | #define REQ_DATASTATUS 0x05 9 | #define REQ_DATAERASE 0x06 10 | #define REQ_POWERUP 0x10 11 | #define REQ_SHUTDOWN 0x11 12 | #define REQ_UPDATE 0xF0 13 | 14 | 15 | #endif 16 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.bin 2 | .idea 3 | 4 | # Prerequisites 5 | *.d 6 | 7 | # Compiled Object files 8 | *.slo 9 | *.lo 10 | *.o 11 | *.obj 12 | 13 | # Precompiled Headers 14 | *.gch 15 | *.pch 16 | 17 | # Compiled Dynamic libraries 18 | *.so 19 | *.dylib 20 | *.dll 21 | 22 | # Fortran module files 23 | *.mod 24 | *.smod 25 | 26 | # Compiled Static libraries 27 | *.lai 28 | *.la 29 | *.a 30 | *.lib 31 | 32 | # Executables 33 | *.exe 34 | *.out 35 | *.app 36 | -------------------------------------------------------------------------------- /XNAND.h: -------------------------------------------------------------------------------- 1 | #ifndef _XNAND_H_ 2 | #define _XNAND_H_ 3 | 4 | #include 5 | 6 | void XNAND_ClearStatus(void); 7 | uint16_t XNAND_GetStatus(void); 8 | uint8_t XNAND_WaitReady(uint16_t timeout); 9 | 10 | uint16_t XNAND_Erase(uint32_t blockNum); 11 | 12 | uint16_t XNAND_StartRead(uint32_t blockNum); 13 | void XNAND_ReadFillBuffer(uint8_t* buf, uint8_t wordCount); 14 | 15 | void XNAND_StartWrite(void); 16 | void XNAND_WriteProcess(uint8_t* buf, uint8_t wordCount); 17 | uint16_t XNAND_WriteExecute(uint32_t blockNum); 18 | 19 | #endif 20 | -------------------------------------------------------------------------------- /debug.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | 3 | import serial 4 | 5 | ser = serial.Serial('COM3', baudrate=9600) 6 | 7 | ser.flushInput() 8 | printdate = True 9 | 10 | 11 | while True: 12 | try: 13 | char = (ser.read(1)).decode('ascii') 14 | if printdate: 15 | print(datetime.now(), end="\t") 16 | printdate = False 17 | 18 | if char == '\n': 19 | printdate = True 20 | print(char, end="") 21 | except serial.SerialException: 22 | ser = serial.Serial('COM3', baudrate=9600) 23 | continue 24 | 25 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 walczakp 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /XSPI.h: -------------------------------------------------------------------------------- 1 | #ifndef _XSPI_H_ 2 | #define _XSPI_H_ 3 | 4 | #include 5 | #include 6 | 7 | #define EJ 19 8 | #define XX 17 9 | #define SS 23 10 | #define SCK 13 11 | #define MOSI 15 12 | #define MISO 21 13 | 14 | #define PINOUT(PIN) pinMode(PIN, OUTPUT) 15 | #define PININ(PIN) pinMode(PIN, INPUT_PULLDOWN) 16 | 17 | #define PINHIGH(PIN) digitalWriteFast(PIN, HIGH) 18 | #define PINLOW(PIN) digitalWriteFast(PIN, LOW) 19 | 20 | #define PINGET(PIN) digitalReadFast(PIN) 21 | 22 | #define _delay_ms(MS) delay(MS) 23 | 24 | void XSPI_Init(void); 25 | 26 | void XSPI_Powerup(void); 27 | void XSPI_Shutdown(void); 28 | 29 | void XSPI_EnterFlashmode(void); 30 | void XSPI_LeaveFlashmode(void); 31 | 32 | void XSPI_Read(uint8_t reg, uint8_t* buf); 33 | uint16_t XSPI_ReadWord(uint8_t reg); 34 | uint8_t XSPI_ReadByte(uint8_t reg); 35 | 36 | void XSPI_Write(uint8_t reg, uint8_t* buf); 37 | void XSPI_WriteByte(uint8_t reg, uint8_t byte); 38 | void XSPI_WriteDword(uint8_t reg, uint32_t dword); 39 | void XSPI_Write0(uint8_t reg); 40 | 41 | uint8_t XSPI_FetchByte(void); 42 | void XSPI_PutByte(uint8_t out); 43 | 44 | #endif 45 | -------------------------------------------------------------------------------- /RPI-XSVF.md: -------------------------------------------------------------------------------- 1 | I used these steps to program my Matrix v1 RGH chip on RPi Zero W. YMMV and you're on your own. 2 | 3 | 1. Building OpenOCD from latest source: 4 | ```bash 5 | sudo apt-get install git autoconf libtool make pkg-config libusb-1.0-0 libusb-1.0-0-dev telnet 6 | git clone http://openocd.zylin.com/openocd 7 | cd openocd 8 | ./bootstrap 9 | ./configure --enable-sysfsgpio --enable-bcm2835gpio 10 | make 11 | sudo make install 12 | ``` 13 | 14 | 2. edit `/usr/local/share/openocd/scripts/interface/raspberrypi-native.cfg`, set your GPIO according to the comment and how you connected your chip (BCM numbering): 15 | ``` 16 | # Each of the JTAG lines need a gpio number set: tck tms tdi tdo 17 | # Header pin numbers: 23 22 19 21 18 | bcm2835gpio_jtag_nums 11 25 10 9 19 | ``` 20 | 21 | 3. Create a directory to your RPi and cd to it, upload your xsvf file there. 22 | 4. Create a file with following config (eg. XC2C64A.cfg): 23 | ``` 24 | source [find interface/raspberrypi-native.cfg] 25 | adapter driver raspberrypi-native 26 | 27 | adapter speed 1000 28 | transport select jtag 29 | ``` 30 | 31 | 5. `sudo openocd -f XC2C64A.cfg` 32 | 6. search for `Warn : AUTO auto0.tap - use "jtag newtap auto0 tap -irlen 8 -expected-id 0x06e59093"` 33 | 7. Quit OpenOCD and append what's in quotes (without quotes) at the end of your .cfg file, then start OpenOCD once again. 34 | 8. `telnet localhost 4444` and enter 35 | ``` 36 | xsvf auto0.tap name-of-your-timing-script.xsvf 37 | ``` 38 | 9. After getting `XSVF file programmed successfully` - that's it -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # xbox360-flasher 2 | XBOX360 NAND reader/writer for Teensy (also working for RPi Pico, see below), communicating with PC using USB Serial (with optional debug serial) 3 | 4 | Based on the great work of G33KatWork: https://github.com/G33KatWork/XBox-360-AVR-flasher 5 | 6 | Tested only on Teensy LC, should work on all Teensys from 3.0 upwards without any changes. 7 | Probably will work even with Atmega based boards (all Arduinos) with few tweaks here and there, but no Teensy specific code has been used. This solution can read and write whole 16MB in about 2,5 minutes - much better than LPT and I already had Teensy LC lying around, so essentially this was a free programmer. If anyone's brave enough to run this on some cheap Arduino knock-off board - this may be a fast and cheap solution for XBOX360 modding. 8 | 9 | Tested only on 16MB flash Trinity, don't know if it will behave on any other console (all 16MBs should do fine). There's a different block size on 256/512MB Jaspers, though, so a simple modification might be needed. 10 | 11 | Included a modified version of XFlash script to use serial communication. 12 | 13 | Modify your pinout in XSPI.h if needed. I used 100 ohm resistors on SCK, SS and MOSI. 14 | 15 | Also, what's might be useful - steps I used to program my glitch chip using Raspberry Pi, which I also happen to have lying around: [RPI-XSPF.md](RPI-XSVF.md) 16 | 17 | **Highly experimental, YMMV. You're on your own. Use only if you know what you're doing!** 18 | 19 | **Update 2021-11-15:** 20 | ![u/luhkius](https://www.reddit.com/user/luhkius/) on reddit did a great job of testing this code on the Raspberry Pi Pico and managed to get this working with changes only to the pin numbering: https://www.reddit.com/r/360hacks/comments/qrjzzt/didnt_have_a_flasher_but_found_that_a_4_pi_pico/ - this makes the flasher even cheaper! 21 | 22 | ![picture of teensy flashing the xbox](picrel.jpg) 23 | 24 | 25 | -------------------------------------------------------------------------------- /XNAND.cpp: -------------------------------------------------------------------------------- 1 | #include "XNAND.h" 2 | #include "XSPI.h" 3 | 4 | void XNAND_ClearStatus() 5 | { 6 | uint8_t tmp[4]; 7 | XSPI_Read(0x04, tmp); 8 | XSPI_Write(0x04, tmp); 9 | } 10 | 11 | uint16_t XNAND_GetStatus() 12 | { 13 | return XSPI_ReadWord(0x04); 14 | } 15 | 16 | uint8_t XNAND_WaitReady(uint16_t timeout) 17 | { 18 | do { 19 | if (!(XSPI_ReadByte(0x04) & 0x01)) 20 | return 1; 21 | } while (timeout--); 22 | 23 | return 0; 24 | } 25 | 26 | uint16_t XNAND_Erase(uint32_t blockNum) 27 | { 28 | uint8_t tmp[4]; 29 | 30 | XNAND_ClearStatus(); 31 | 32 | XSPI_Read(0, tmp); 33 | tmp[0] |= 0x08; 34 | XSPI_Write(0, tmp); 35 | 36 | XSPI_WriteDword(0x0C, blockNum << 9); 37 | 38 | if (!XNAND_WaitReady(0x1000)) 39 | return 0x8001; 40 | 41 | XSPI_WriteByte(0x08, 0xAA); 42 | XSPI_WriteByte(0x08, 0x55); 43 | 44 | if (!XNAND_WaitReady(0x1000)) 45 | return 0x8002; 46 | 47 | XSPI_WriteByte(0x08, 0x5); 48 | 49 | if (!XNAND_WaitReady(0x1000)) 50 | return 0x8003; 51 | 52 | return XNAND_GetStatus(); 53 | } 54 | 55 | uint16_t XNAND_StartRead(uint32_t blockNum) 56 | { 57 | uint16_t res; 58 | 59 | XNAND_ClearStatus(); 60 | 61 | XSPI_WriteDword(0x0C, blockNum << 9); 62 | 63 | XSPI_WriteByte(0x08, 0x03); 64 | 65 | if (!XNAND_WaitReady(0x1000)) 66 | return 0x8011; 67 | 68 | res = XNAND_GetStatus(); 69 | 70 | XSPI_Write0(0x0C); 71 | 72 | return res; 73 | } 74 | 75 | void XNAND_ReadFillBuffer(uint8_t* buf, uint8_t wordCount) 76 | { 77 | while(wordCount--) 78 | { 79 | XSPI_Write0(0x08); 80 | XSPI_Read(0x10, buf); 81 | buf += 4; 82 | } 83 | } 84 | 85 | void XNAND_StartWrite() 86 | { 87 | XNAND_ClearStatus(); 88 | XSPI_Write0(0x0C); 89 | } 90 | 91 | void XNAND_WriteProcess(uint8_t* buf, uint8_t wordCount) 92 | { 93 | while(wordCount--) 94 | { 95 | XSPI_Write(0x10, buf); 96 | XSPI_WriteByte(0x08, 0x01); 97 | buf += 4; 98 | } 99 | } 100 | 101 | uint16_t XNAND_WriteExecute(uint32_t blockNum) 102 | { 103 | XSPI_WriteDword(0x0C, blockNum << 9); 104 | 105 | XSPI_WriteByte(0x08, 0x55); 106 | XSPI_WriteByte(0x08, 0xAA); 107 | XSPI_WriteByte(0x08, 0x4); 108 | 109 | if (!XNAND_WaitReady(0x1000)) 110 | return 0x8021; 111 | 112 | return XNAND_GetStatus(); 113 | } 114 | -------------------------------------------------------------------------------- /XSPI.cpp: -------------------------------------------------------------------------------- 1 | #include "XSPI.h" 2 | 3 | void XSPI_Init(void) 4 | { 5 | // PINOUT( KSK); 6 | PINOUT( EJ); 7 | PINOUT( XX); 8 | PINOUT( SS); 9 | PINOUT( SCK); 10 | PINOUT( MOSI); 11 | PININ( MISO); 12 | 13 | PINHIGH( EJ); 14 | PINHIGH( SS); 15 | PINHIGH( XX); 16 | PINHIGH( SCK); 17 | PINLOW( MOSI); 18 | } 19 | 20 | void XSPI_Powerup(void) 21 | { 22 | // PINLOW( KSK); 23 | // _delay_ms(5); 24 | // PINHIGH( KSK); 25 | // _delay_ms(5); 26 | // 27 | // PINLOW( KSK); 28 | // _delay_ms(5); 29 | // PINHIGH( KSK); 30 | // _delay_ms(5); 31 | // 32 | // PINLOW( KSK); 33 | // _delay_ms(5); 34 | // PINHIGH( KSK); 35 | // _delay_ms(5); 36 | // 37 | // PINLOW( KSK); 38 | // _delay_ms(5); 39 | // PINHIGH( KSK); 40 | } 41 | 42 | void XSPI_Shutdown(void) 43 | { 44 | PINHIGH( SS); 45 | PINLOW( XX); 46 | PINLOW( EJ); 47 | 48 | _delay_ms(50); 49 | 50 | PINHIGH( EJ); 51 | } 52 | 53 | void XSPI_EnterFlashmode(void) 54 | { 55 | PINLOW( XX); 56 | 57 | _delay_ms(50); 58 | 59 | PINLOW( SS); 60 | PINLOW( EJ); 61 | 62 | _delay_ms(50); 63 | 64 | PINHIGH( XX); 65 | PINHIGH( EJ); 66 | 67 | _delay_ms(50); 68 | } 69 | 70 | void XSPI_LeaveFlashmode(void) 71 | { 72 | PINHIGH( SS); 73 | PINLOW( EJ); 74 | 75 | _delay_ms(50); 76 | 77 | PINLOW( XX); 78 | PINHIGH( EJ); 79 | } 80 | 81 | void XSPI_Read(uint8_t reg, uint8_t* buf) 82 | { 83 | PINLOW( SS); 84 | 85 | XSPI_PutByte((reg << 2) | 1); 86 | XSPI_PutByte(0xFF); 87 | 88 | *buf++ = XSPI_FetchByte(); 89 | *buf++ = XSPI_FetchByte(); 90 | *buf++ = XSPI_FetchByte(); 91 | *buf++ = XSPI_FetchByte(); 92 | 93 | PINHIGH( SS); 94 | } 95 | 96 | uint16_t XSPI_ReadWord(uint8_t reg) 97 | { 98 | uint16_t res; 99 | 100 | PINLOW( SS); 101 | 102 | XSPI_PutByte((reg << 2) | 1); 103 | XSPI_PutByte(0xFF); 104 | 105 | res = XSPI_FetchByte(); 106 | res |= ((uint16_t)XSPI_FetchByte()) << 8; 107 | 108 | PINHIGH( SS); 109 | 110 | return res; 111 | } 112 | 113 | uint8_t XSPI_ReadByte(uint8_t reg) 114 | { 115 | uint8_t res; 116 | 117 | PINLOW( SS); 118 | 119 | XSPI_PutByte((reg << 2) | 1); 120 | XSPI_PutByte(0xFF); 121 | 122 | res = XSPI_FetchByte(); 123 | 124 | PINHIGH( SS); 125 | 126 | return res; 127 | } 128 | 129 | void XSPI_Write(uint8_t reg, uint8_t* buf) 130 | { 131 | PINLOW( SS); 132 | 133 | XSPI_PutByte((reg << 2) | 2); 134 | 135 | XSPI_PutByte(*buf++); 136 | XSPI_PutByte(*buf++); 137 | XSPI_PutByte(*buf++); 138 | XSPI_PutByte(*buf++); 139 | 140 | PINHIGH( SS); 141 | } 142 | 143 | void XSPI_WriteByte(uint8_t reg, uint8_t byte) 144 | { 145 | uint8_t data[] = {0,0,0,0}; 146 | data[0] = byte; 147 | 148 | XSPI_Write(reg, data); 149 | } 150 | 151 | void XSPI_WriteDword(uint8_t reg, uint32_t dword) 152 | { 153 | XSPI_Write(reg, (uint8_t*)&dword); 154 | } 155 | 156 | void XSPI_Write0(uint8_t reg) 157 | { 158 | uint8_t tmp[] = {0,0,0,0}; 159 | XSPI_Write(reg, tmp); 160 | } 161 | 162 | uint8_t XSPI_FetchByte() 163 | { 164 | uint8_t in = 0; 165 | PINLOW( MOSI); 166 | 167 | for(uint8_t i = 0; i < 8; i++) 168 | { 169 | PINHIGH( SCK); 170 | in |= PINGET( MISO) ? (1 << i) : 0x00; 171 | PINLOW( SCK); 172 | } 173 | 174 | return in; 175 | } 176 | 177 | void XSPI_PutByte(uint8_t out) 178 | { 179 | for(uint8_t i = 0; i < 8; i++) 180 | { 181 | if(out & (1 << i)) PINHIGH( MOSI); else PINLOW( MOSI); 182 | PINHIGH( SCK); 183 | PINLOW( SCK); 184 | } 185 | } 186 | -------------------------------------------------------------------------------- /xbox-teensy-flasher.ino: -------------------------------------------------------------------------------- 1 | #include "XSPI.h" 2 | #include "XNAND.h" 3 | #include "defs.h" 4 | 5 | #define USBSERIAL Serial 6 | #define DBGSERIAL Serial2 7 | 8 | #define dbg(MSG) DBGSERIAL.print(F(MSG)) 9 | #define dbgf(MSG, ...) DBGSERIAL.printf(F(MSG), __VA_ARGS__) 10 | 11 | uint32_t read_param_le(void); 12 | void StartFlashRead(uint32_t, uint32_t); 13 | void StartFlashWrite(uint32_t, uint32_t); 14 | void FlashInit(void); 15 | void FlashDeinit(void); 16 | void FlashStatus(void); 17 | 18 | uint16_t STATUS = 0; 19 | uint8_t PAGE_BUFFER[0x210] = {}; 20 | 21 | void setup() { 22 | // put your setup code here, to run once: 23 | USBSERIAL.begin(115200); 24 | DBGSERIAL.begin(9600); 25 | 26 | dbg("Init SPI\n"); 27 | XSPI_Init(); 28 | } 29 | 30 | void loop() { 31 | if (USBSERIAL.available()) { 32 | int16_t command = USBSERIAL.read(); // serial.read is 0-255 or -1 :( 33 | 34 | if (command > 0) { 35 | uint32_t paramA = read_param_le(); 36 | uint32_t paramB = read_param_le(); 37 | switch(command) 38 | { 39 | case REQ_DATAREAD: StartFlashRead(paramA << 5, paramB); break; 40 | case REQ_DATAWRITE: StartFlashWrite(paramA << 5, paramB); break; 41 | case REQ_DATAINIT: FlashInit(); break; 42 | case REQ_DATADEINIT: FlashDeinit(); break; 43 | case REQ_DATASTATUS: FlashStatus(); break; 44 | // case REQ_DATAERASE: FlashErase(paramA << 5); break; 45 | // case REQ_POWERUP: PowerUp(); break; 46 | // case REQ_SHUTDOWN: Shutdown(); break; 47 | // case REQ_UPDATE: Update(); break; 48 | } 49 | } 50 | } 51 | } 52 | 53 | uint32_t read_param_le() { 54 | uint32_t buffer = 0; 55 | int16_t read = -1; 56 | for(int i = 0; i < 4; ) { 57 | if (USBSERIAL.available()) { 58 | read = USBSERIAL.read(); 59 | buffer = (buffer >> 8) | (read << 24); 60 | i++; 61 | } 62 | } 63 | return buffer; 64 | } 65 | 66 | 67 | void StartFlashRead(uint32_t startPage, uint32_t len) { 68 | uint8_t* buff_ptr = PAGE_BUFFER; 69 | STATUS = 0; 70 | uint32_t wordsLeft = 0; 71 | uint32_t nextPage = startPage; 72 | 73 | len /= 4; 74 | while(len) { 75 | uint8_t readNow; 76 | 77 | if(!wordsLeft) 78 | { 79 | STATUS = XNAND_StartRead(nextPage); 80 | nextPage++; 81 | wordsLeft = 0x210 / 4; 82 | buff_ptr = PAGE_BUFFER; 83 | } 84 | 85 | readNow = (len < wordsLeft) ? len : wordsLeft; 86 | XNAND_ReadFillBuffer(buff_ptr, readNow); 87 | 88 | buff_ptr += (readNow*4); 89 | wordsLeft -= readNow; 90 | len -= readNow; 91 | 92 | if(!wordsLeft) { 93 | USBSERIAL.write(PAGE_BUFFER, 0x210); 94 | } 95 | } 96 | } 97 | 98 | void StartFlashWrite(uint32_t startPage, uint32_t len) { 99 | STATUS = XNAND_Erase(startPage); 100 | XNAND_StartWrite(); 101 | 102 | uint8_t* buff_ptr = PAGE_BUFFER; 103 | uint32_t wordsLeft = 0; 104 | uint32_t nextPage = startPage; 105 | 106 | len /= 4; 107 | while(len) 108 | { 109 | uint8_t writeNow; 110 | 111 | if(!wordsLeft) 112 | { 113 | while (USBSERIAL.available() < 0x210) {} 114 | USBSERIAL.readBytes((char*)PAGE_BUFFER, 0x210); 115 | 116 | buff_ptr = PAGE_BUFFER; 117 | wordsLeft = 0x210 / 4; 118 | } 119 | 120 | writeNow = (len < wordsLeft) ? len : wordsLeft; 121 | XNAND_WriteProcess(buff_ptr, writeNow); 122 | 123 | buff_ptr += (writeNow*4); 124 | wordsLeft -= writeNow; 125 | len -= writeNow; 126 | 127 | //execute write if buffer in NAND controller is filled 128 | if(!wordsLeft) 129 | { 130 | STATUS = XNAND_WriteExecute(nextPage++); 131 | XNAND_StartWrite(); 132 | } 133 | } 134 | } 135 | 136 | void FlashInit(void) { 137 | dbg("Entering flashmode\n"); 138 | XSPI_EnterFlashmode(); 139 | 140 | dbg("Reading flashconfig\n"); 141 | uint8_t FlashConfig[4]; 142 | XSPI_Read(0, FlashConfig); //2 times? 143 | XSPI_Read(0, FlashConfig); 144 | 145 | USBSERIAL.write(FlashConfig, 4); 146 | } 147 | 148 | void FlashDeinit() { 149 | dbg("Leaving flashmode\n"); 150 | XSPI_LeaveFlashmode(); 151 | } 152 | 153 | void FlashStatus() { 154 | uint8_t FlashStatus[2] = {(uint8_t)(STATUS & 0xFF), (uint8_t)(STATUS >> 8)}; 155 | USBSERIAL.write(FlashStatus, 2); 156 | } 157 | -------------------------------------------------------------------------------- /xflash-serial.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | import serial 3 | import sys 4 | import struct 5 | import pprint 6 | import argparse 7 | import code 8 | 9 | pp = pprint.PrettyPrinter() 10 | 11 | 12 | class ConsoleUI: 13 | def opStart(self, name): 14 | sys.stdout.write(name.ljust(40)) 15 | 16 | def opProgress(self, progress, total=-1): 17 | if (total >= 0): 18 | prstr = "0x%04x / 0x%04x" % (progress, total) 19 | else: 20 | prstr = "0x%04x" % (progress) 21 | 22 | sys.stdout.write(prstr.ljust(20)) 23 | sys.stdout.write('\x08' * 20) 24 | sys.stdout.flush() 25 | 26 | def opEnd(self, result): 27 | sys.stdout.write(result.ljust(20)) 28 | sys.stdout.write("\n") 29 | 30 | 31 | class XFlash: 32 | def __init__(self, serialport): 33 | self.serial = serial.Serial(serialport, baudrate=115200) 34 | 35 | def __del__(self): 36 | try: 37 | self.serial.close() 38 | del self.serial 39 | except: 40 | pass 41 | 42 | def cmd(self, cmd, argA=0, argB=0): 43 | buffer = struct.pack(">= 1 106 | # if val & 1: 107 | # val ^= 0x6954559 108 | # val >>= 1 109 | # 110 | # val = ~val 111 | # return data[:-4] + struct.pack("