├── README.md ├── Makefile ├── ftdi.h └── main.c /README.md: -------------------------------------------------------------------------------- 1 | # CH55x-USB-Blaster 2 | 3 | USB-Blaster instance on CH55x MCU. 4 | 5 | Based on CH55x-sdcc-lib. 6 | 7 | License: MIT 8 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | TARGET = usb_blaster 2 | 3 | # Adjust the XRAM location and size to leave space for the USB DMA buffers 4 | # Buffer layout in XRAM: 5 | # 0x0000 Ep0Buffer[8] 6 | # 0x0040 Ep1Buffer[8] 7 | # 0x0080 EP2Buffer[2*64] 8 | # 9 | # This takes a total of 256bytes, so there are 256 bytes left. 10 | 11 | #XRAM_SIZE = 0x0100 12 | #XRAM_LOC = 0x0100 13 | 14 | XRAM_SIZE = 0x0200 15 | XRAM_LOC = 0x0000 16 | #FREQ_SYS = 24000000 17 | CODE_SIZE = 0x2800 18 | 19 | EXTRA_FLAGS = --opt-code-speed 20 | 21 | C_FILES = \ 22 | main.c \ 23 | ../../include/debug.c 24 | 25 | #EXTRA_FLAGS += -DDE_PRINTF 26 | 27 | pre-flash: 28 | 29 | 30 | include ../Makefile.include 31 | -------------------------------------------------------------------------------- /ftdi.h: -------------------------------------------------------------------------------- 1 | #define FTDI_VEN_REQ_RESET 0x00 2 | #define FTDI_VEN_REQ_SET_BAUDRATE 0x01 3 | #define FTDI_VEN_REQ_SET_DATA_CHAR 0x02 4 | #define FTDI_VEN_REQ_SET_FLOW_CTRL 0x03 5 | #define FTDI_VEN_REQ_SET_MODEM_CTRL 0x04 6 | #define FTDI_VEN_REQ_GET_MODEM_STA 0x05 7 | #define FTDI_VEN_REQ_SET_EVENT_CHAR 0x06 8 | #define FTDI_VEN_REQ_SET_ERR_CHAR 0x07 9 | #define FTDI_VEN_REQ_SET_LAT_TIMER 0x09 10 | #define FTDI_VEN_REQ_GET_LAT_TIMER 0x0A 11 | #define FTDI_VEN_REQ_SET_BITMODE 0x0B 12 | #define FTDI_VEN_REQ_RD_PINS 0x0C 13 | #define FTDI_VEN_REQ_RD_EEPROM 0x90 14 | #define FTDI_VEN_REQ_WR_EEPROM 0x91 15 | #define FTDI_VEN_REQ_ES_EEPROM 0x92 16 | 17 | #define FTDI_MODEM_STA_SIZE 0x02 18 | #define FTDI_MODEM_STA_DUMMY0 0x01 19 | #define FTDI_MODEM_STA_DUMMY1 0x60 -------------------------------------------------------------------------------- /main.c: -------------------------------------------------------------------------------- 1 | // USB-Blaster instance on CH55x MCU. 2 | // Author: Duan 3 | // License: MIT 4 | // Based on USB-MIDI by Zhiyuan Wan 5 | 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include "ftdi.h" 15 | 16 | #define BTN_PIN 2 //P3.2 for bootloader entry. 17 | SBIT(BTN, 0xB0, BTN_PIN); 18 | 19 | SBIT(LED, 0x90, 1); 20 | /* 21 | SBIT(TMS, 0x90, 4); 22 | SBIT(TCK, 0x90, 5); 23 | SBIT(TDI, 0x90, 6); 24 | SBIT(TDO, 0x90, 7); 25 | */ 26 | 27 | SBIT(TMS, 0x90, 4); 28 | SBIT(TCK, 0x90, 7); 29 | SBIT(TDI, 0x90, 5); 30 | SBIT(TDO, 0x90, 6); 31 | 32 | SBIT(P2B7, 0xA0, 7); 33 | SBIT(P2B6, 0xA0, 6); 34 | SBIT(P2B5, 0xA0, 5); 35 | SBIT(P2B4, 0xA0, 4); 36 | SBIT(P2B3, 0xA0, 3); 37 | SBIT(P2B2, 0xA0, 2); 38 | SBIT(P2B1, 0xA0, 1); 39 | SBIT(P2B0, 0xA0, 0); 40 | 41 | 42 | __xdata __at(0x0000) uint8_t transmit_buffer[128]; //fixed address for ringbuf 43 | __xdata __at(0x0080) uint8_t receive_buffer[64]; 44 | __xdata __at(0x0100) uint8_t Ep0Buffer[0x08]; //端点0 OUT&IN缓冲区,必须是偶地址 45 | __xdata __at(0x0140) uint8_t Ep1Buffer[0x40]; //端点1 IN缓冲区 46 | __xdata __at(0x0180) uint8_t Ep2Buffer[0x40]; //端点2 OUT缓冲区,必须是偶地址 47 | 48 | 49 | uint16_t SetupLen; 50 | uint8_t SetupReq, Count, UsbConfig; 51 | uint8_t vendor_control; 52 | uint8_t send_dummy; 53 | 54 | const uint8_t *pDescr; //USB配置标志 55 | USB_SETUP_REQ SetupReqBuf; //暂存Setup包 56 | #define UsbSetupBuf ((PUSB_SETUP_REQ)Ep0Buffer) 57 | 58 | __code uint8_t ftdi_rom[] = { 59 | 0x00, 0x00, 0xfb, 0x09, 0x01, 0x60, 0x00, 0x04, 60 | 0x80, 0xe1, 0x1c, 0x00, 0x00, 0x02, 0x94, 0x0e, 61 | 0xa2, 0x18, 0xba, 0x12, 0x0e, 0x03, 0x41, 0x00, 62 | 0x6c, 0x00, 0x74, 0x00, 0x65, 0x00, 0x72, 0x00, 63 | 0x61, 0x00, 0x18, 0x03, 0x55, 0x00, 0x53, 0x00, 64 | 0x42, 0x00, 0x2d, 0x00, 0x42, 0x00, 0x6c, 0x00, 65 | 0x61, 0x00, 0x73, 0x00, 0x74, 0x00, 0x65, 0x00, 66 | 0x72, 0x00, 0x12, 0x03, 0x43, 0x00, 0x30, 0x00, 67 | 0x42, 0x00, 0x46, 0x00, 0x41, 0x00, 0x36, 0x00, 68 | 0x44, 0x00, 0x37, 0x00, 0x02, 0x03, 0x01, 0x00, 69 | 0x52, 0x45, 0x56, 0x42, 0x00, 0x00, 0x00, 0x00, 70 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 71 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 72 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 73 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 74 | 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xb5, 0xb2}; 75 | 76 | __code uint8_t DevDesc[] = { 77 | 0x12, 0x01, 0x00, 0x02, 78 | 0x00, 0x00, 0x00, 0x08, 79 | 0xFB, 0x09, 0x01, 0x60, 0x00, 0x04, 0x01, 0x02, 0x03, /* VID PID bString */ 80 | 0x01}; 81 | 82 | __code uint8_t CfgDesc[] = { 83 | 0x09, 0x02, sizeof(CfgDesc) & 0xff, sizeof(CfgDesc) >> 8, 84 | 0x01, 0x01, 0x00, 0x80, 0xe1, 85 | /* Interface Descriptor */ 86 | 0x09, 0x04, 0x00, 0x00, 0x02, 0xff, 0xff, 0xff, 0x00, 87 | /* Endpoint Descriptor */ 88 | 0x07, 0x05, 0x81, 0x02, 0x40, 0x00, 0x01, //EP1_IN 89 | 0x07, 0x05, 0x02, 0x02, 0x40, 0x00, 0x01, //EP2_OUT 90 | }; 91 | 92 | /* USB String Descriptors (optional) */ 93 | unsigned char __code LangDes[] = {0x04, 0x03, 0x09, 0x04}; // EN_US 94 | unsigned char __code SerDes[] = { 95 | //TODO: variable SN. 96 | sizeof(SerDes), 0x03, 97 | 'C', 0, '0', 0, 'B', 0, 'F', 0, 'A', 0, '6', 0, 'D', 0, '7', 0 /* "C0BFA6D7" */ 98 | }; 99 | unsigned char __code Prod_Des[] = { 100 | sizeof(Prod_Des), 101 | 0x03, 102 | 'U', 0, 'S', 0, 'B', 0, '-', 0, 'B', 0, 'l', 0, 'a', 0, 's', 0, 't', 0, 'e', 0, 'r', 0 /* "USB-Blaster" */ 103 | }; 104 | unsigned char __code Manuf_Des[] = { 105 | sizeof(Manuf_Des), 106 | 0x03, 107 | 'A', 0, 'l', 0, 't', 0, 'e', 0, 'r', 0, 'a', 0 /* Manufacturer: "Altera" */ 108 | }; 109 | 110 | volatile __idata uint8_t USBByteCount = 0; //代表USB端点接收到的数据 111 | volatile __idata uint8_t USBBufOutPoint = 0; //取数据指针 112 | volatile __idata uint16_t sof_count = 0; 113 | volatile __idata uint8_t ep1_in_busy = 0; //上传端点是否忙标志 114 | volatile __idata uint8_t latency_timer = 4; 115 | 116 | /******************************************************************************* 117 | * Function Name : USBDeviceCfg() 118 | * Description : USB设备模式配置 119 | * Input : None 120 | * Output : None 121 | * Return : None 122 | *******************************************************************************/ 123 | void USBDeviceCfg() 124 | { 125 | USB_CTRL = 0x00; //清空USB控制寄存器 126 | USB_CTRL &= ~bUC_HOST_MODE; //该位为选择设备模式 127 | USB_CTRL |= bUC_DEV_PU_EN | bUC_INT_BUSY | bUC_DMA_EN; //USB设备和内部上拉使能,在中断期间中断标志未清除前自动返回NAK 128 | USB_DEV_AD = 0x00; //设备地址初始化 129 | // USB_CTRL |= bUC_LOW_SPEED; 130 | // UDEV_CTRL |= bUD_LOW_SPEED; //选择低速1.5M模式 131 | USB_CTRL &= ~bUC_LOW_SPEED; 132 | UDEV_CTRL &= ~bUD_LOW_SPEED; //选择全速12M模式,默认方式 133 | UDEV_CTRL = bUD_PD_DIS; // 禁止DP/DM下拉电阻 134 | UDEV_CTRL |= bUD_PORT_EN; //使能物理端口 135 | } 136 | /******************************************************************************* 137 | * Function Name : USBDeviceIntCfg() 138 | * Description : USB设备模式中断初始化 139 | * Input : None 140 | * Output : None 141 | * Return : None 142 | *******************************************************************************/ 143 | void USBDeviceIntCfg() 144 | { 145 | USB_INT_EN |= bUIE_SUSPEND; //使能设备挂起中断 146 | USB_INT_EN |= bUIE_TRANSFER; //使能USB传输完成中断 147 | USB_INT_EN |= bUIE_BUS_RST; //使能设备模式USB总线复位中断 148 | USB_INT_EN |= bUIE_DEV_SOF; //For timeout count. 149 | USB_INT_FG |= 0x1F; //清中断标志 150 | IE_USB = 1; //使能USB中断 151 | EA = 1; //允许单片机中断 152 | } 153 | /******************************************************************************* 154 | * Function Name : USBDeviceEndPointCfg() 155 | * Description : USB设备模式端点配置,模拟兼容HID设备,除了端点0的控制传输,还包括端点2批量上下传 156 | * Input : None 157 | * Output : None 158 | * Return : None 159 | *******************************************************************************/ 160 | void USBDeviceEndPointCfg() 161 | { 162 | UEP1_DMA = (uint16_t)Ep1Buffer; //端点1 IN数据传输地址 163 | UEP2_DMA = (uint16_t)Ep2Buffer; //端点2 OUT数据传输地址 164 | UEP2_3_MOD = 0x08; 165 | UEP2_CTRL = bUEP_AUTO_TOG | UEP_R_RES_ACK; //端点2自动翻转同步标志位,OUT返回ACK 166 | UEP1_CTRL = bUEP_AUTO_TOG | UEP_T_RES_NAK; //端点1自动翻转同步标志位,IN事务返回NAK 167 | UEP0_DMA = (uint16_t)Ep0Buffer; //端点0数据传输地址 168 | UEP4_1_MOD = 0x40; //端点1上传缓冲区;端点0单64字节收发缓冲区 169 | UEP0_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK; //手动翻转,OUT事务返回ACK,IN事务返回NAK 170 | } 171 | 172 | /******************************************************************************* 173 | * Function Name : DeviceInterrupt() 174 | * Description : CH55xUSB中断处理函数 175 | *******************************************************************************/ 176 | void DeviceInterrupt(void) __interrupt(INT_NO_USB) //USB中断服务程序,使用寄存器组1 177 | { 178 | uint16_t len; 179 | if ((USB_INT_ST & MASK_UIS_TOKEN) == UIS_TOKEN_SOF) 180 | { 181 | sof_count++; 182 | } 183 | if (UIF_TRANSFER) //USB传输完成标志 184 | { 185 | switch (USB_INT_ST & (MASK_UIS_TOKEN | MASK_UIS_ENDP)) 186 | { 187 | case UIS_TOKEN_IN | 1: //endpoint 1 188 | UEP1_T_LEN = 0; 189 | UEP1_CTRL = UEP1_CTRL & ~MASK_UEP_T_RES | UEP_T_RES_NAK; //默认应答NAK 190 | ep1_in_busy = 0; 191 | break; 192 | case UIS_TOKEN_OUT | 2: //endpoint 2 193 | { 194 | if (U_TOG_OK) // 不同步的数据包将丢弃 195 | { 196 | USBByteCount = USB_RX_LEN; 197 | USBBufOutPoint = 0; //取数据指针复位 198 | UEP2_CTRL = UEP2_CTRL & ~MASK_UEP_R_RES | UEP_R_RES_NAK; //收到一包数据就NAK,主函数处理完,由主函数修改响应方式 199 | } 200 | break; 201 | } 202 | break; 203 | case UIS_TOKEN_SETUP | 0: //SETUP事务 204 | len = USB_RX_LEN; 205 | if (len == (sizeof(USB_SETUP_REQ))) 206 | { 207 | uint8_t addr; 208 | SetupLen = ((uint16_t)UsbSetupBuf->wLengthH << 8) | (UsbSetupBuf->wLengthL); 209 | len = 0; // 默认为成功并且上传0长度 210 | vendor_control = 0; //默认非vendor 211 | SetupReq = UsbSetupBuf->bRequest; 212 | if ((UsbSetupBuf->bRequestType & USB_REQ_TYP_MASK) == USB_REQ_TYP_VENDOR) 213 | { 214 | vendor_control = 1; 215 | if (SetupLen == 0) 216 | { 217 | //No Data 218 | switch (SetupReq) 219 | { 220 | case FTDI_VEN_REQ_RESET: 221 | break; 222 | case FTDI_VEN_REQ_SET_BAUDRATE: 223 | break; 224 | case FTDI_VEN_REQ_SET_DATA_CHAR: 225 | break; 226 | case FTDI_VEN_REQ_SET_FLOW_CTRL: 227 | break; 228 | case FTDI_VEN_REQ_SET_MODEM_CTRL: 229 | break; 230 | default: 231 | break; 232 | } 233 | } 234 | else 235 | { 236 | //Data 237 | switch (SetupReq) 238 | { 239 | case FTDI_VEN_REQ_RD_EEPROM: 240 | addr = UsbSetupBuf->wIndexL << 1; //((req->wIndex >> 8) & 0x3F) << 1; 241 | Ep0Buffer[0] = ftdi_rom[addr]; 242 | Ep0Buffer[1] = ftdi_rom[addr + 1]; 243 | len = 2; 244 | break; 245 | case FTDI_VEN_REQ_GET_MODEM_STA: 246 | // return fixed modem status 247 | Ep0Buffer[0] = FTDI_MODEM_STA_DUMMY0; 248 | Ep0Buffer[1] = FTDI_MODEM_STA_DUMMY1; 249 | len = 2; 250 | break; 251 | case FTDI_VEN_REQ_SET_LAT_TIMER: 252 | latency_timer = UsbSetupBuf->wValueL; 253 | len = 0; 254 | break; 255 | default: 256 | // return dummy data 257 | Ep0Buffer[0] = 0x0; 258 | Ep0Buffer[1] = 0x0; 259 | len = 2; 260 | break; 261 | } 262 | } 263 | } 264 | else if ((UsbSetupBuf->bRequestType & USB_REQ_TYP_MASK) == USB_REQ_TYP_STANDARD) 265 | { 266 | switch (SetupReq) //请求码 267 | { 268 | case USB_GET_DESCRIPTOR: 269 | switch (UsbSetupBuf->wValueH) 270 | { 271 | case 1: //设备描述符 272 | pDescr = DevDesc; //把设备描述符送到要发送的缓冲区 273 | len = sizeof(DevDesc); 274 | break; 275 | case 2: //配置描述符 276 | pDescr = CfgDesc; //把设备描述符送到要发送的缓冲区 277 | len = sizeof(CfgDesc); 278 | break; 279 | case 3: 280 | if (UsbSetupBuf->wValueL == 0) 281 | { 282 | pDescr = LangDes; 283 | len = sizeof(LangDes); 284 | } 285 | else if (UsbSetupBuf->wValueL == 1) 286 | { 287 | pDescr = Manuf_Des; 288 | len = sizeof(Manuf_Des); 289 | } 290 | else if (UsbSetupBuf->wValueL == 2) 291 | { 292 | pDescr = Prod_Des; 293 | len = sizeof(Prod_Des); 294 | } 295 | else 296 | { 297 | pDescr = SerDes; 298 | len = sizeof(SerDes); 299 | } 300 | break; 301 | default: 302 | len = 0xff; //不支持的命令或者出错 303 | break; 304 | } 305 | if (SetupLen > len) 306 | { 307 | SetupLen = len; //限制总长度 308 | } 309 | len = SetupLen >= DEFAULT_ENDP0_SIZE ? DEFAULT_ENDP0_SIZE : SetupLen; //本次传输长度 310 | memcpy(Ep0Buffer, pDescr, len); //加载上传数据 311 | SetupLen -= len; 312 | pDescr += len; 313 | break; 314 | case USB_SET_ADDRESS: 315 | SetupLen = UsbSetupBuf->wValueL; //暂存USB设备地址 316 | break; 317 | case USB_GET_CONFIGURATION: 318 | Ep0Buffer[0] = UsbConfig; 319 | if (SetupLen >= 1) 320 | { 321 | len = 1; 322 | } 323 | break; 324 | case USB_SET_CONFIGURATION: 325 | UsbConfig = UsbSetupBuf->wValueL; 326 | break; 327 | case USB_GET_INTERFACE: 328 | break; 329 | case USB_CLEAR_FEATURE: //Clear Feature 330 | if ((UsbSetupBuf->bRequestType & 0x1F) == USB_REQ_RECIP_DEVICE) /* 清除设备 */ 331 | { 332 | if ((((uint16_t)UsbSetupBuf->wValueH << 8) | UsbSetupBuf->wValueL) == 0x01) 333 | { 334 | if (CfgDesc[7] & 0x20) 335 | { 336 | /* 唤醒 */ 337 | } 338 | else 339 | { 340 | len = 0xFF; /* 操作失败 */ 341 | } 342 | } 343 | else 344 | { 345 | len = 0xFF; /* 操作失败 */ 346 | } 347 | } 348 | else if ((UsbSetupBuf->bRequestType & USB_REQ_RECIP_MASK) == USB_REQ_RECIP_ENDP) // 端点 349 | { 350 | switch (UsbSetupBuf->wIndexL) 351 | { 352 | case 0x02: 353 | UEP2_CTRL = UEP2_CTRL & ~(bUEP_R_TOG | MASK_UEP_R_RES) | UEP_R_RES_ACK; 354 | break; 355 | case 0x81: 356 | UEP1_CTRL = UEP1_CTRL & ~(bUEP_T_TOG | MASK_UEP_T_RES) | UEP_T_RES_NAK; 357 | break; 358 | default: 359 | len = 0xFF; // 不支持的端点 360 | break; 361 | } 362 | ep1_in_busy = 0; 363 | } 364 | else 365 | { 366 | len = 0xFF; // 不是端点不支持 367 | } 368 | break; 369 | case USB_SET_FEATURE: /* Set Feature */ 370 | if ((UsbSetupBuf->bRequestType & 0x1F) == USB_REQ_RECIP_DEVICE) /* 设置设备 */ 371 | { 372 | if ((((uint16_t)UsbSetupBuf->wValueH << 8) | UsbSetupBuf->wValueL) == 0x01) 373 | { 374 | if (CfgDesc[7] & 0x20) 375 | { 376 | /* 休眠 */ 377 | #ifdef DE_PRINTF 378 | printf("suspend\r\n"); //睡眠状态 379 | #endif 380 | while (XBUS_AUX & bUART0_TX) 381 | { 382 | ; //等待发送完成 383 | } 384 | SAFE_MOD = 0x55; 385 | SAFE_MOD = 0xAA; 386 | WAKE_CTRL = bWAK_BY_USB | bWAK_RXD0_LO | bWAK_RXD1_LO; //USB或者RXD0/1有信号时可被唤醒 387 | PCON |= PD; //睡眠 388 | SAFE_MOD = 0x55; 389 | SAFE_MOD = 0xAA; 390 | WAKE_CTRL = 0x00; 391 | } 392 | else 393 | { 394 | len = 0xFF; /* 操作失败 */ 395 | } 396 | } 397 | else 398 | { 399 | len = 0xFF; /* 操作失败 */ 400 | } 401 | } 402 | else if ((UsbSetupBuf->bRequestType & 0x1F) == USB_REQ_RECIP_ENDP) /* 设置端点 */ 403 | { 404 | if ((((uint16_t)UsbSetupBuf->wValueH << 8) | UsbSetupBuf->wValueL) == 0x00) 405 | { 406 | switch (((uint16_t)UsbSetupBuf->wIndexH << 8) | UsbSetupBuf->wIndexL) 407 | { 408 | case 0x82: 409 | UEP2_CTRL = UEP2_CTRL & (~bUEP_T_TOG) | UEP_T_RES_STALL; /* 设置端点2 IN STALL */ 410 | break; 411 | case 0x02: 412 | UEP2_CTRL = UEP2_CTRL & (~bUEP_R_TOG) | UEP_R_RES_STALL; /* 设置端点2 OUT Stall */ 413 | break; 414 | case 0x81: 415 | UEP1_CTRL = UEP1_CTRL & (~bUEP_T_TOG) | UEP_T_RES_STALL; /* 设置端点1 IN STALL */ 416 | break; 417 | case 0x01: 418 | UEP1_CTRL = UEP1_CTRL & (~bUEP_R_TOG) | UEP_R_RES_STALL; /* 设置端点1 OUT Stall */ 419 | default: 420 | len = 0xFF; /* 操作失败 */ 421 | break; 422 | } 423 | } 424 | else 425 | { 426 | len = 0xFF; /* 操作失败 */ 427 | } 428 | } 429 | else 430 | { 431 | len = 0xFF; /* 操作失败 */ 432 | } 433 | break; 434 | case USB_GET_STATUS: 435 | Ep0Buffer[0] = 0x00; 436 | Ep0Buffer[1] = 0x00; 437 | if (SetupLen >= 2) 438 | { 439 | len = 2; 440 | } 441 | else 442 | { 443 | len = SetupLen; 444 | } 445 | break; 446 | default: 447 | len = 0xff; //操作失败 448 | break; 449 | } 450 | } 451 | else 452 | { 453 | switch (SetupReq) 454 | { 455 | 456 | default: 457 | len = 0xFF; /*命令不支持*/ 458 | break; 459 | } 460 | } 461 | } 462 | else 463 | { 464 | len = 0xff; //包长度错误 465 | } 466 | if (len == 0xff) 467 | { 468 | SetupReq = 0xFF; 469 | UEP0_CTRL = bUEP_R_TOG | bUEP_T_TOG | UEP_R_RES_STALL | UEP_T_RES_STALL; //STALL 470 | } 471 | else if (len <= DEFAULT_ENDP0_SIZE) //上传数据或者状态阶段返回0长度包 472 | { 473 | UEP0_T_LEN = len; 474 | UEP0_CTRL = bUEP_R_TOG | bUEP_T_TOG | UEP_R_RES_ACK | UEP_T_RES_ACK; //默认数据包是DATA1,返回应答ACK 475 | } 476 | else 477 | { 478 | UEP0_T_LEN = 0; //虽然尚未到状态阶段,但是提前预置上传0长度数据包以防主机提前进入状态阶段 479 | UEP0_CTRL = bUEP_R_TOG | bUEP_T_TOG | UEP_R_RES_ACK | UEP_T_RES_ACK; //默认数据包是DATA1,返回应答ACK 480 | } 481 | break; 482 | case UIS_TOKEN_IN | 0: //endpoint0 IN 483 | switch (SetupReq) 484 | { 485 | case USB_GET_DESCRIPTOR: 486 | len = SetupLen >= DEFAULT_ENDP0_SIZE ? DEFAULT_ENDP0_SIZE : SetupLen; //本次传输长度 487 | memcpy(Ep0Buffer, pDescr, len); //加载上传数据 488 | SetupLen -= len; 489 | pDescr += len; 490 | UEP0_T_LEN = len; 491 | UEP0_CTRL ^= bUEP_T_TOG; //同步标志位翻转 492 | break; 493 | case USB_SET_ADDRESS: 494 | if (!vendor_control) 495 | { 496 | USB_DEV_AD = USB_DEV_AD & bUDA_GP_BIT | SetupLen; 497 | UEP0_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK; 498 | } 499 | break; 500 | default: 501 | UEP0_T_LEN = 0; //状态阶段完成中断或者是强制上传0长度数据包结束控制传输 502 | UEP0_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK; 503 | break; 504 | } 505 | break; 506 | case UIS_TOKEN_OUT | 0: // endpoint0 OUT 507 | /*if(SetupReq ==SET_LINE_CODING) //设置串口属性 508 | { 509 | if( U_TOG_OK ) 510 | { 511 | // memcpy(LineCoding,UsbSetupBuf,USB_RX_LEN); 512 | // Config_Uart1(LineCoding); 513 | UEP0_T_LEN = 0; 514 | UEP0_CTRL |= UEP_R_RES_ACK | UEP_T_RES_ACK; // 准备上传0包 515 | } 516 | } 517 | else 518 | {*/ 519 | UEP0_T_LEN = 0; 520 | UEP0_CTRL |= UEP_R_RES_ACK | UEP_T_RES_ACK; //状态阶段,对IN响应NAK 521 | //} 522 | break; 523 | 524 | default: 525 | break; 526 | } 527 | UIF_TRANSFER = 0; //写0清空中断 528 | } 529 | if (UIF_BUS_RST) //设备模式USB总线复位中断 530 | { 531 | #ifdef DE_PRINTF 532 | printf("reset\r\n"); //睡眠状态 533 | #endif 534 | UEP0_CTRL = UEP_R_RES_ACK | UEP_T_RES_NAK; 535 | UEP1_CTRL = bUEP_AUTO_TOG | UEP_T_RES_NAK; 536 | UEP2_CTRL = bUEP_AUTO_TOG | UEP_R_RES_ACK; 537 | USB_DEV_AD = 0x00; 538 | UIF_SUSPEND = 0; 539 | UIF_TRANSFER = 0; 540 | UIF_BUS_RST = 0; //清中断标志 541 | 542 | USBByteCount = 0; //USB端点收到的长度 543 | UsbConfig = 0; //清除配置值 544 | ep1_in_busy = 0; 545 | } 546 | if (UIF_SUSPEND) //USB总线挂起/唤醒完成 547 | { 548 | UIF_SUSPEND = 0; 549 | if (USB_MIS_ST & bUMS_SUSPEND) //挂起 550 | { 551 | #ifdef DE_PRINTF 552 | printf("suspend\r\n"); //睡眠状态 553 | #endif 554 | while (XBUS_AUX & bUART0_TX) 555 | { 556 | ; //等待发送完成 557 | } 558 | SAFE_MOD = 0x55; 559 | SAFE_MOD = 0xAA; 560 | WAKE_CTRL = bWAK_BY_USB | bWAK_RXD0_LO | bWAK_RXD1_LO; //USB或者RXD0/1有信号时可被唤醒 561 | PCON |= PD; //睡眠 562 | SAFE_MOD = 0x55; 563 | SAFE_MOD = 0xAA; 564 | WAKE_CTRL = 0x00; 565 | } 566 | } 567 | else 568 | { //意外的中断,不可能发生的情况 569 | USB_INT_FG = 0xFF; //清中断标志 570 | } 571 | } 572 | 573 | __idata uint8_t transmit_buffer_in_offset; 574 | __idata uint8_t transmit_buffer_out_offset; 575 | __idata uint8_t send_len; 576 | 577 | //主函数 578 | void main() 579 | { 580 | uint8_t length = 0; 581 | uint8_t read_buffer_index = 0; 582 | uint8_t shift_count = 0; 583 | uint8_t operand = 0; 584 | uint8_t shift_en = 0; 585 | uint8_t read_en = 0; 586 | uint16_t timeout_count = 0; 587 | 588 | CfgFsys(); //CH559时钟选择配置 589 | //mDelaymS(5); //修改主频等待内部晶振稳定,必加 590 | BTN = 1; 591 | mDelaymS(50); 592 | if (BTN == 0) 593 | { 594 | mDelaymS(50); 595 | if (BTN == 0) 596 | { 597 | EA = 0; 598 | mDelaymS(100); 599 | (*(void (*)(void))0x3800)(); // goto bootloader. 600 | while (1) 601 | ; 602 | } 603 | } 604 | 605 | USBDeviceCfg(); 606 | USBDeviceEndPointCfg(); //端点配置 607 | USBDeviceIntCfg(); //中断初始化 608 | 609 | //P1.1 P1.4 P1.5 P1.6 output push-pull. 610 | //P1.7 input. 611 | P1_MOD_OC = 0x40; 612 | P1_DIR_PU = 0xf2; 613 | TDO = 1; 614 | 615 | UEP0_T_LEN = 0; 616 | UEP1_T_LEN = 0; //预使用发送长度一定要清空 617 | 618 | Ep1Buffer[0] = FTDI_MODEM_STA_DUMMY0; 619 | Ep1Buffer[1] = FTDI_MODEM_STA_DUMMY1; 620 | 621 | transmit_buffer_in_offset = 0; 622 | transmit_buffer_out_offset = 0; 623 | 624 | length = 0; 625 | send_dummy = 1; 626 | LED = 0; 627 | 628 | while (1) 629 | { 630 | if (UsbConfig) 631 | { 632 | length = 0; 633 | if (USBByteCount) //USB接收端点有数据 634 | { 635 | //memcpy(receive_buffer, Ep2Buffer, USBByteCount); 636 | 637 | __asm 638 | push ar7 639 | push a 640 | inc _XBUS_AUX //dptr1 641 | mov dptr, #_receive_buffer //target receive_buffer 642 | dec _XBUS_AUX //dptr0 643 | mov dptr, #_Ep2Buffer //source Ep2Buffer 644 | mov ar7, _USBByteCount 645 | 1$: 646 | movx a, @dptr 647 | inc dptr 648 | .db #0xA5 //WCH 0xA5 instruction 649 | djnz ar7, 1$ 650 | pop a 651 | pop ar7 652 | __endasm; 653 | 654 | UEP2_CTRL = UEP2_CTRL & ~MASK_UEP_R_RES | UEP_R_RES_ACK; 655 | length = USBByteCount; 656 | USBByteCount = 0; 657 | } 658 | 659 | read_buffer_index = 0; 660 | while (read_buffer_index < length) 661 | { 662 | P2 = receive_buffer[read_buffer_index]; 663 | read_buffer_index++; 664 | //TODO: Assembly implementation for IO control. 665 | //TODO: Use hardware spi for shift control. 666 | if (shift_count == 0) 667 | { 668 | shift_en = P2B7; 669 | read_en = P2B6; 670 | if (shift_en) 671 | { 672 | shift_count = P2 & 0x3f; 673 | } 674 | else if (read_en) 675 | { 676 | LED = P2B5; 677 | TDI = P2B4; 678 | TMS = P2B1; 679 | TCK = P2B0; 680 | transmit_buffer[transmit_buffer_in_offset] = TDO; 681 | transmit_buffer_in_offset++; 682 | transmit_buffer_in_offset &= 0x7f;// %= sizeof(transmit_buffer); 683 | } 684 | else 685 | { 686 | LED = P2B5; 687 | TDI = P2B4; 688 | TMS = P2B1; 689 | TCK = P2B0; 690 | } 691 | } 692 | else 693 | { 694 | shift_count--; 695 | if (read_en) 696 | { 697 | TDI = P2B0; 698 | P2B0 = TDO; 699 | TCK = 1; 700 | TCK = 0; 701 | 702 | TDI = P2B1; 703 | P2B1 = TDO; 704 | TCK = 1; 705 | TCK = 0; 706 | 707 | TDI = P2B2; 708 | P2B2 = TDO; 709 | TCK = 1; 710 | TCK = 0; 711 | 712 | TDI = P2B3; 713 | P2B3 = TDO; 714 | TCK = 1; 715 | TCK = 0; 716 | 717 | TDI = P2B4; 718 | P2B4 = TDO; 719 | TCK = 1; 720 | TCK = 0; 721 | 722 | TDI = P2B5; 723 | P2B5 = TDO; 724 | TCK = 1; 725 | TCK = 0; 726 | 727 | TDI = P2B6; 728 | P2B6 = TDO; 729 | TCK = 1; 730 | TCK = 0; 731 | 732 | TDI = P2B7; 733 | P2B7 = TDO; 734 | TCK = 1; 735 | TCK = 0; 736 | 737 | transmit_buffer[transmit_buffer_in_offset] = P2; 738 | transmit_buffer_in_offset++; 739 | transmit_buffer_in_offset &= 0x7f; 740 | } 741 | else 742 | { 743 | TDI = P2B0; 744 | TCK = 1; 745 | TCK = 0; 746 | 747 | TDI = P2B1; 748 | TCK = 1; 749 | TCK = 0; 750 | 751 | TDI = P2B2; 752 | TCK = 1; 753 | TCK = 0; 754 | 755 | TDI = P2B3; 756 | TCK = 1; 757 | TCK = 0; 758 | 759 | TDI = P2B4; 760 | TCK = 1; 761 | TCK = 0; 762 | 763 | TDI = P2B5; 764 | TCK = 1; 765 | TCK = 0; 766 | 767 | TDI = P2B6; 768 | TCK = 1; 769 | TCK = 0; 770 | 771 | TDI = P2B7; 772 | TCK = 1; 773 | TCK = 0; 774 | } 775 | } 776 | } 777 | 778 | if (ep1_in_busy == 0) //端点不繁忙(空闲后的第一包数据,只用作触发上传) 779 | { 780 | int8_t data_len = transmit_buffer_in_offset - transmit_buffer_out_offset; 781 | data_len = data_len < 0 ? 128 + data_len : data_len; 782 | if (data_len > 0) // 2 for modem bytes. 783 | { 784 | uint8_t i; 785 | send_len = (data_len >= 62) ? 62 : data_len; 786 | 787 | for (i = 0; i < send_len; i++) 788 | { 789 | Ep1Buffer[i + 2] = transmit_buffer[transmit_buffer_out_offset]; 790 | transmit_buffer_out_offset++; 791 | transmit_buffer_out_offset &= 0x7f;// %= sizeof(transmit_buffer); 792 | } 793 | /* 794 | __asm 795 | push ar7 796 | push a 797 | inc _XBUS_AUX //dptr1 798 | mov dptr, #(_Ep1Buffer + 0x0002) //target receive_buffer 799 | dec _XBUS_AUX //dptr0 800 | mov dph, #(_transmit_buffer >> 8) //fixed address 0x00XX 801 | mov dpl, _transmit_buffer_out_offset 802 | mov ar7, _send_len 803 | 2$: 804 | movx a, @dptr 805 | .db #0xA5 //WCH 0xA5 instruction 806 | inc _transmit_buffer_out_offset //idata 807 | anl _transmit_buffer_out_offset, #0x7f //ring operation 808 | mov dph, #(_transmit_buffer >> 8) //fixed address 0x00XX 809 | mov dpl, _transmit_buffer_out_offset 810 | djnz ar7, 2$ 811 | pop a 812 | pop ar7 813 | __endasm; 814 | */ 815 | 816 | ep1_in_busy = 1; 817 | UEP1_T_LEN = send_len + 2; 818 | UEP1_CTRL = UEP1_CTRL & ~MASK_UEP_T_RES | UEP_T_RES_ACK; //应答ACK 819 | } 820 | else if ((sof_count - timeout_count) > latency_timer) 821 | { 822 | timeout_count = sof_count; 823 | ep1_in_busy = 1; 824 | UEP1_T_LEN = 2; //预使用发送长度一定要清空 825 | UEP1_CTRL = UEP1_CTRL & ~MASK_UEP_T_RES | UEP_T_RES_ACK; //应答ACK 826 | } 827 | else if(send_dummy) 828 | { 829 | send_dummy--; 830 | ep1_in_busy = 1; 831 | UEP1_T_LEN = 2; //预使用发送长度一定要清空 832 | UEP1_CTRL = UEP1_CTRL & ~MASK_UEP_T_RES | UEP_T_RES_ACK; //应答ACK 833 | } 834 | } 835 | } 836 | } 837 | } 838 | --------------------------------------------------------------------------------