├── main.o ├── blink.bin ├── KT_BinIO.o ├── KT_ProgressBar.o ├── README.md ├── KT_BinIO.h ├── KT_ProgressBar.h ├── KT_ProgressBar.cpp ├── LICENSE ├── KT_BinIO.cpp └── main.cpp /main.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NgoHungCuong/vnproch551/HEAD/main.o -------------------------------------------------------------------------------- /blink.bin: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NgoHungCuong/vnproch551/HEAD/blink.bin -------------------------------------------------------------------------------- /KT_BinIO.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NgoHungCuong/vnproch551/HEAD/KT_BinIO.o -------------------------------------------------------------------------------- /KT_ProgressBar.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/NgoHungCuong/vnproch551/HEAD/KT_ProgressBar.o -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # vnproch551 2 | CH551 Programming tool 3 | Usage: vnproch551 flash_file.bin 4 | -------------------------------------------------------------------------------- /KT_BinIO.h: -------------------------------------------------------------------------------- 1 | #ifndef KT_BIN_IO_H_ 2 | #define KT_BIN_IO_H_ 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | class KT_BinIO { 9 | private: 10 | 11 | public: 12 | uint8_t *pReadBuff; 13 | uint8_t *pWriteBuff; 14 | uint32_t Read(char *pszInput); 15 | uint32_t Write(char *pszOutput); 16 | uint32_t InitBuffer(); 17 | uint32_t FreeBuffer(); 18 | uint32_t u32Size; 19 | protected: 20 | }; 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /KT_ProgressBar.h: -------------------------------------------------------------------------------- 1 | #ifndef KT_PROGRESS_BAR_H_ 2 | #define KT_PROGRESS_BAR_H_ 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | class KT_ProgressBar { 9 | private: 10 | uint32_t u32Max = 100; 11 | char cSig = '.'; 12 | uint32_t u32Num = 100; 13 | uint32_t u32Pos = 0; 14 | public: 15 | void SetNum(uint32_t u32Num); 16 | void SetSig(char cSig); 17 | void SetMax(uint32_t u32Max); 18 | void SetPos(uint32_t u32Pos); 19 | void Display(void); 20 | }; 21 | 22 | #endif 23 | -------------------------------------------------------------------------------- /KT_ProgressBar.cpp: -------------------------------------------------------------------------------- 1 | #include "KT_ProgressBar.h" 2 | 3 | void KT_ProgressBar::SetNum(uint32_t u32Num) 4 | { 5 | this->u32Num = u32Num; 6 | } 7 | void KT_ProgressBar::SetSig(char cSig) 8 | { 9 | this->cSig = cSig; 10 | } 11 | void KT_ProgressBar::SetMax(uint32_t u32Max) 12 | { 13 | this->u32Max = u32Max; 14 | } 15 | void KT_ProgressBar::SetPos(uint32_t u32Pos) 16 | { 17 | this->u32Pos = u32Pos; 18 | } 19 | 20 | void KT_ProgressBar::Display(void) 21 | { 22 | /* erase current line */ 23 | printf("%c[2K\r", 27); 24 | /* display current state */ 25 | uint32_t i; 26 | uint32_t n; 27 | n = u32Pos * u32Num / u32Max; 28 | for (i = 0; i < n; ++i) { 29 | printf("%c", cSig); 30 | } 31 | fflush(stdout); 32 | } 33 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Ngo Hung Cuong 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 | -------------------------------------------------------------------------------- /KT_BinIO.cpp: -------------------------------------------------------------------------------- 1 | #include "KT_BinIO.h" 2 | 3 | uint32_t KT_BinIO::Read(char *pszInput) 4 | { 5 | FILE *f; 6 | f = fopen(pszInput, "rb"); 7 | if (f == NULL) { 8 | return 0; 9 | } 10 | fseek (f , 0 , SEEK_END); 11 | uint32_t lSize; 12 | lSize = ftell (f); 13 | rewind (f); 14 | if (fread(pReadBuff, 1, lSize, f) != lSize) { 15 | fclose(f); 16 | return 0; 17 | } 18 | fclose(f); 19 | return 1; 20 | } 21 | uint32_t KT_BinIO::Write(char *pszOutput) 22 | { 23 | FILE *f; 24 | f = fopen(pszOutput, "wb"); 25 | if (f == NULL) { 26 | return 0; 27 | } 28 | if (!fwrite(pWriteBuff, u32Size, 1, f)) { 29 | fclose(f); 30 | return 0; 31 | } 32 | fclose(f); 33 | return 1; 34 | } 35 | uint32_t KT_BinIO::InitBuffer() 36 | { 37 | pReadBuff = (uint8_t*)malloc(u32Size); 38 | if (pReadBuff == NULL) { 39 | return 0; 40 | } 41 | memset(pReadBuff, 0xFF, u32Size); 42 | pWriteBuff = (uint8_t*)malloc(u32Size); 43 | if (pWriteBuff == NULL) { 44 | return 0; 45 | } 46 | memset(pWriteBuff, 0xFF, u32Size); 47 | return 1; 48 | } 49 | uint32_t KT_BinIO::FreeBuffer() 50 | { 51 | free(pReadBuff); 52 | free(pWriteBuff); 53 | } 54 | -------------------------------------------------------------------------------- /main.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include "KT_BinIO.h" 7 | #include "KT_ProgressBar.h" 8 | 9 | KT_BinIO ktFlash; 10 | 11 | uint8_t u8Buff[64]; 12 | uint8_t u8Mask[8]; 13 | 14 | /* Detect MCU */ 15 | uint8_t u8DetectCmd[64] = { 16 | 0xA1, 0x12, 0x00, 0x51, 0x11, 0x4D, 0x43, 0x55, 17 | 0x20, 0x49, 0x53, 0x50, 0x20, 0x26, 0x20, 0x57, 18 | 0x43, 0x48, 0x2e, 0x43, 0x4e 19 | }; 20 | uint8_t u8DetectRespond = 6; 21 | 22 | /* Get Bootloader Version, Chip ID */ 23 | uint8_t u8IdCmd[64] = { 24 | 0xA7, 0x02, 0x00, 0x1F, 0x00 25 | }; 26 | uint8_t u8IdRespond = 30; 27 | 28 | /* Enable ISP */ 29 | uint8_t u8InitCmd[64] = { 30 | 0xA8, 0x0E, 0x00, 0x07, 0x00, 0xFF, 0xFF, 0xFF, 31 | 0xFF, 0x03, 0x00, 0x00, 0x00, 0xFF, 0x52, 0x00, 32 | 0x00 33 | }; 34 | uint8_t u8InitRespond = 6; 35 | 36 | /* Set Flash Address */ 37 | uint8_t u8AddessCmd[64] = { 38 | 0xA3, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 39 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 40 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 41 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 42 | 0x00 43 | }; 44 | uint8_t u8AddessRespond = 6; 45 | 46 | /* Erase ??? */ 47 | uint8_t u8EraseCmd[64] = { 48 | 0xA4, 0x01, 0x00, 0x08 49 | }; 50 | uint8_t u8EraseRespond = 6; 51 | 52 | /* Reset */ 53 | uint8_t u8ResetCmd[64] = { 54 | 0xA2, 0x01, 0x00, 0x01 /* if 0x00 not run, 0x01 run*/ 55 | }; 56 | uint8_t u8ResetRespond = 6; 57 | 58 | /* Write */ 59 | uint8_t u8WriteCmd[64] = { 60 | 0xA5, 0x3D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 61 | /* byte 4 Low Address (first = 1) */ 62 | /* byte 5 High Address */ 63 | }; 64 | uint8_t u8WriteRespond = 6; 65 | 66 | uint8_t u8ReadCmd[64] = { 67 | 0x00 68 | }; 69 | uint8_t u8ReadRespond = 6; 70 | 71 | libusb_device_handle *h; 72 | 73 | uint32_t Write(uint8_t *p8Buff, uint8_t u8Length); 74 | uint32_t Read(uint8_t *p8Buff, uint8_t u8Length); 75 | 76 | uint32_t Write(uint8_t *p8Buff, uint8_t u8Length) 77 | { 78 | int len; 79 | if (libusb_bulk_transfer(h, 0x02, (unsigned char*)p8Buff, u8Length, &len, 5000) != 0) { 80 | return 0; 81 | } else { 82 | return 1; 83 | } 84 | return 0; 85 | } 86 | uint32_t Read(uint8_t *p8Buff, uint8_t u8Length) 87 | { 88 | int len; 89 | if (libusb_bulk_transfer(h, 0x82, (unsigned char*)p8Buff, u8Length, &len, 5000) != 0) { 90 | return 0; 91 | } else { 92 | return 1; 93 | } 94 | return 0; 95 | } 96 | 97 | int main(int argc, char const *argv[]) 98 | { 99 | uint32_t i; 100 | KT_BinIO ktBin; 101 | KT_ProgressBar ktProg; 102 | 103 | printf("\033[2J\033[1;1H"); 104 | printf("------------------------------------------------------------------\n"); 105 | printf("CH551 Programmer by VNPro\n"); 106 | printf("------------------------------------------------------------------\n"); 107 | if (argc != 2) { 108 | printf("usage: vnproch551 flash_file.bin\n"); 109 | printf("------------------------------------------------------------------\n"); 110 | return 1; 111 | } 112 | /* load flash file */ 113 | ktBin.u32Size = 10 * 1024; 114 | ktBin.InitBuffer(); 115 | if (!ktBin.Read((char*)argv[1])) { 116 | printf("Read file: ERROR\n"); 117 | return 0; 118 | } 119 | 120 | libusb_init(NULL); 121 | 122 | h = libusb_open_device_with_vid_pid(NULL, 0x4348, 0x55e0); 123 | 124 | if (h == NULL) { 125 | printf("Found no CH551 USB\n"); 126 | return 1; 127 | } 128 | 129 | libusb_claim_interface(h, 0); 130 | 131 | /* Detect MCU */ 132 | if (!Write(u8DetectCmd, u8DetectCmd[1] + 3)) { 133 | printf("Send Detect: Fail\n"); 134 | return 1; 135 | } 136 | 137 | if (!Read(u8Buff, u8DetectRespond)) { 138 | printf("Read Detect: Fail\n"); 139 | return 1; 140 | } 141 | 142 | /* Check MCU ID */ 143 | if ((u8Buff[4] != 0x51) && (u8Buff[5] != 0x11)) { 144 | printf("Not support\n"); 145 | return 1; 146 | } 147 | 148 | /* Bootloader and Chip ID */ 149 | if (!Write(u8IdCmd, u8IdCmd[1] + 3)) { 150 | printf("Send ID: Fail\n"); 151 | return 1; 152 | } 153 | 154 | if (!Read(u8Buff, u8IdRespond)) { 155 | printf("Read ID: Fail\n"); 156 | return 1; 157 | } 158 | 159 | printf("Bootloader: %d.%d.%d\n", u8Buff[19], u8Buff[20], u8Buff[21]); 160 | printf("ID: %02X %02X %02X %02X\n", u8Buff[22], u8Buff[23], u8Buff[24], u8Buff[25]); 161 | /* check bootloader version */ 162 | if ((u8Buff[19] != 0x02) || (u8Buff[20] != 0x03) || (u8Buff[21] != 0x01)) { 163 | printf("Not support\n"); 164 | return 1; 165 | } 166 | /* Calc XOR Mask */ 167 | 168 | uint8_t u8Sum; 169 | 170 | u8Sum = u8Buff[22] + u8Buff[23] + u8Buff[24] + u8Buff[25]; 171 | for (i = 0; i < 8; ++i) { 172 | u8Mask[i] = u8Sum; 173 | } 174 | u8Mask[7] += 0x51; 175 | printf("XOR Mask: "); 176 | for (i = 0; i < 8; ++i) { 177 | printf("%02X ", u8Mask[i]); 178 | } 179 | printf("\n"); 180 | 181 | /* init or erase ??? */ 182 | if (!Write(u8InitCmd, u8InitCmd[1] + 3)) { 183 | printf("Send Init: Fail\n"); 184 | return 1; 185 | } 186 | 187 | if (!Read(u8Buff, u8InitRespond)) { 188 | printf("Read Init: Fail\n"); 189 | return 1; 190 | } 191 | 192 | /* Bootloader and Chip ID */ 193 | if (!Write(u8IdCmd, u8IdCmd[1] + 3)) { 194 | printf("Send ID: Fail\n"); 195 | return 1; 196 | } 197 | 198 | if (!Read(u8Buff, u8IdRespond)) { 199 | printf("Read ID: Fail\n"); 200 | return 1; 201 | } 202 | 203 | /* Set Flash Address to 0 */ 204 | if (!Write(u8AddessCmd, u8AddessCmd[1] + 3)) { 205 | printf("Send Address: Fail\n"); 206 | return 1; 207 | } 208 | 209 | if (!Read(u8Buff, u8AddessRespond)) { 210 | printf("Read Address: Fail\n"); 211 | return 1; 212 | } 213 | 214 | /* Erase or unknow */ 215 | if (!Write(u8EraseCmd, u8EraseCmd[1] + 3)) { 216 | printf("Send Erase: Fail\n"); 217 | return 1; 218 | } 219 | 220 | if (!Read(u8Buff, u8EraseRespond)) { 221 | printf("Read Erase: Fail\n"); 222 | return 1; 223 | } 224 | 225 | /* Write */ 226 | printf("Write\n"); 227 | /* Progress */ 228 | uint32_t n; 229 | n = 10 * 1024 / 56; 230 | ktProg.SetMax(n); 231 | ktProg.SetNum(50); 232 | ktProg.SetPos(0); 233 | ktProg.Display(); 234 | 235 | for (i = 0; i < n; ++i) { 236 | uint16_t u16Tmp; 237 | uint32_t j; 238 | /* Write flash */ 239 | memmove(&u8WriteCmd[8], &ktBin.pReadBuff[i * 0x38], 0x38); 240 | for (j = 0; j < 7; ++j) { 241 | uint32_t ii; 242 | for (ii = 0; ii < 8; ++ii) { 243 | u8WriteCmd[8 + j * 8 + ii] ^= u8Mask[ii]; 244 | } 245 | } 246 | u16Tmp = i * 0x38; 247 | u8WriteCmd[3] = (uint8_t)u16Tmp; 248 | u8WriteCmd[4] = (uint8_t)(u16Tmp >> 8); 249 | if (!Write(u8WriteCmd, u8WriteCmd[1] + 3)) { 250 | printf("Send Write: Fail\n"); 251 | return 1; 252 | } 253 | 254 | if (!Read(u8Buff, u8WriteRespond)) { 255 | printf("Read Write: Fail\n"); 256 | return 1; 257 | } 258 | ktProg.SetPos(i + 1); 259 | ktProg.Display(); 260 | } 261 | 262 | /* Reset and Run */ 263 | Write(u8ResetCmd, u8ResetCmd[1] + 3); 264 | //printf("Send Reset: Fail\n"); 265 | //return 1; 266 | //} 267 | printf("\n"); 268 | printf("Write complete!!!\n"); 269 | printf("------------------------------------------------------------------\n"); 270 | 271 | return 0; 272 | } --------------------------------------------------------------------------------