From ddea639a7b97b19d643a899134e92b4fd947edfb Mon Sep 17 00:00:00 2001 From: qitas Date: Mon, 17 May 2021 11:27:15 +0800 Subject: [PATCH] init --- .github/workflows/linux-sdcc-4.0.0.yml | 36 ++ project/JTAG/Makefile | 13 + project/JTAG/ch552.h | 257 +++++++++ project/JTAG/ch55xtool.py | 341 ++++++++++++ project/JTAG/usbjtag.c | 270 ++++++++++ project/JTAG/usbjtag.py | 139 +++++ src/template/Makefile | 54 ++ src/template/src/ch552.c | 34 ++ src/template/src/ch552.h | 696 +++++++++++++++++++++++++ src/template/src/ch552_usb.h | 344 ++++++++++++ src/template/src/main.c | 11 + tools/ch55xtool.py | 7 +- 12 files changed, 2200 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/linux-sdcc-4.0.0.yml create mode 100644 project/JTAG/Makefile create mode 100644 project/JTAG/ch552.h create mode 100644 project/JTAG/ch55xtool.py create mode 100644 project/JTAG/usbjtag.c create mode 100644 project/JTAG/usbjtag.py create mode 100644 src/template/Makefile create mode 100644 src/template/src/ch552.c create mode 100644 src/template/src/ch552.h create mode 100644 src/template/src/ch552_usb.h create mode 100644 src/template/src/main.c diff --git a/.github/workflows/linux-sdcc-4.0.0.yml b/.github/workflows/linux-sdcc-4.0.0.yml new file mode 100644 index 0000000..a01c716 --- /dev/null +++ b/.github/workflows/linux-sdcc-4.0.0.yml @@ -0,0 +1,36 @@ +name: SDCC_4.0.0 + +on: + push: + branches: + - master + - github_actions + tags: + - '*' + pull_request: + branches: + - master + - github_actions + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - name: Check out + uses: actions/checkout@v2 + + - name: Download SDCC + run: | + wget https://sourceforge.net/projects/sdcc/files/sdcc-linux-amd64/4.0.0/sdcc-4.0.0-amd64-unknown-linux2.5.tar.bz2 + tar -xf sdcc-4.0.0-amd64-unknown-linux2.5.tar.bz2 + echo `pwd`/sdcc-4.0.0/bin >> $GITHUB_PATH + + - name: Build + working-directory: src/template + run: make + + - uses: actions/upload-artifact@v2 + with: + name: sdcc_template + path: src/template diff --git a/project/JTAG/Makefile b/project/JTAG/Makefile new file mode 100644 index 0000000..b2ae4ba --- /dev/null +++ b/project/JTAG/Makefile @@ -0,0 +1,13 @@ +CFLAGS=-mmcs51 --model-small --xram-size 0x0400 --xram-loc 0x0000 --code-size 0x3800 + +all: + sdcc $(CFLAGS) usbjtag.c -o usbjtag.hex + objcopy -I ihex -O binary usbjtag.hex usbjtag.bin + -@rm -rf *.asm *.lst *.rel *.rst *.sym *.lk *.map *.mem *.hex + +flash: + -@python3 usbjtag.py -i + python3 ch55xtool.py -r -f usbjtag.bin + +test: + python3 usbjtag.py -rcsv -f test.bin diff --git a/project/JTAG/ch552.h b/project/JTAG/ch552.h new file mode 100644 index 0000000..81852b0 --- /dev/null +++ b/project/JTAG/ch552.h @@ -0,0 +1,257 @@ +#ifndef __CH552_H__ +#define __CH552_H__ + +#include + +//System SFRs +SFR(PSW, 0xD0); +SBIT(CY, 0xD0, 7); +SBIT(AC, 0xD0, 6); +SBIT(F0, 0xD0, 5); +SBIT(RS1, 0xD0, 4); +SBIT(RS0, 0xD0, 3); +SBIT(OV, 0xD0, 2); +SBIT(F1, 0xD0, 1); +SBIT(P, 0xD0, 0); +SFR(ACC, 0xE0); +SFR(B, 0xF0); +SFR(SP, 0x81); +SFR(DPL, 0x82); +SFR(DPH, 0x83); +SFR(SAFE_MOD, 0xA1); +SFR(GLOBAL_CFG, 0xB1); +SFR(PCON, 0x87); +SFR(CLOCK_CFG, 0xB9); +SFR(WAKE_CTRL, 0xA9); +SFR(RESET_KEEP, 0xFE); +SFR(WDOG_COUNT, 0xFF); + +//Interrupt SFRs +SFR(IE, 0xA8); +SBIT(EA, 0xA8, 7); +SBIT(E_DIS, 0xA8, 6); +SBIT(ET2, 0xA8, 5); +SBIT(ES, 0xA8, 4); +SBIT(ET1, 0xA8, 3); +SBIT(EX1, 0xA8, 2); +SBIT(ET0, 0xA8, 1); +SBIT(EX0, 0xA8, 0); +SFR(IP, 0xB8); +SBIT(PH_FLAG, 0xB8, 7); +SBIT(PL_FLAG, 0xB8, 6); +SBIT(PT2, 0xB8, 5); +SBIT(PS, 0xB8, 4); +SBIT(PT1, 0xB8, 3); +SBIT(PX1, 0xB8, 2); +SBIT(PT0, 0xB8, 1); +SBIT(PX0, 0xB8, 0); +SFR(IE_EX, 0xE8); +SBIT(IE_WDOG, 0xE8, 7); +SBIT(IE_GPIO, 0xE8, 6); +SBIT(IE_PWMX, 0xE8, 5); +SBIT(IE_UART1, 0xE8, 4); +SBIT(IE_ADC, 0xE8, 3); +SBIT(IE_USB, 0xE8, 2); +SBIT(IE_TKEY, 0xE8, 1); +SBIT(IE_SPI0, 0xE8, 0); +SFR(IP_EX, 0xE9); +SFR(GPIO_IE, 0xC7); + +//Flash SFRs +SFR16(ROM_ADDR, 0x84); +SFR(ROM_ADDR_L, 0x84); +SFR(ROM_ADDR_H, 0x85); +SFR16(ROM_DATA, 0x8E); +SFR(ROM_DATA_L, 0x8E); +SFR(ROM_DATA_H, 0x8F); +SFR(ROM_CTRL, 0x86); + +//Port SFRs +SFR(P1, 0x90); +SBIT(P10, 0x90, 0); +SBIT(P11, 0x90, 1); +SBIT(P12, 0x90, 2); +SBIT(P13, 0x90, 3); +SBIT(P14, 0x90, 4); +SBIT(P15, 0x90, 5); +SBIT(P16, 0x90, 6); +SBIT(P17, 0x90, 7); +SFR(P1_MOD_OC, 0x92); +SFR(P1_DIR_PU, 0x93); +SFR(P2, 0xA0); +SFR(P3, 0xB0); +SBIT(P30, 0xB0, 0); +SBIT(P31, 0xB0, 1); +SBIT(P32, 0xB0, 2); +SBIT(P33, 0xB0, 3); +SBIT(P34, 0xB0, 4); +SBIT(P35, 0xB0, 5); +SBIT(P36, 0xB0, 6); +SBIT(P37, 0xB0, 7); +SFR(P3_MOD_OC, 0x96); +SFR(P3_DIR_PU, 0x97); +SFR(PIN_FUNC, 0xC6); +SFR(XBUS_AUX, 0xA2); + +//Timer0/1 SFRs +SFR(TCON,0x88); +SBIT(TF1, 0x88, 7); +SBIT(TR1, 0x88, 6); +SBIT(TF0, 0x88, 5); +SBIT(TR0, 0x88, 4); +SBIT(IE1, 0x88, 3); +SBIT(IT1, 0x88, 2); +SBIT(IE0, 0x88, 1); +SBIT(IT0, 0x88, 0); +SFR(TMOD,0x89); +SFR(TL0,0x8A); +SFR(TL1,0x8B); +SFR(TH0,0x8C); +SFR(TH1,0x8D); + +//Timer2 SFRs +SFR(T2CON, 0xC8); +SBIT(TF2, 0xC8, 7); +SBIT(CAP1F, 0xC8, 7); +SBIT(EXF2, 0xC8, 6); +SBIT(RCLK, 0xC8, 5); +SBIT(TCLK, 0xC8, 4); +SBIT(EXEN2, 0xC8, 3); +SBIT(TR2, 0xC8, 2); +SBIT(C_T2, 0xC8, 1); +SBIT(CP_RL2, 0xC8, 0); +SFR(T2MOD, 0xC9); +SFR16(RCAP2, 0xCA); +SFR(RCAP2L, 0xCA); +SFR(RCAP2H, 0xCB); +SFR16(T2COUNT, 0xCC); +SFR(TL2, 0xCC); +SFR(TH2, 0xCD); +SFR16(T2CAP1, 0xCE); +SFR(T2CAP1L, 0xCE); +SFR(T2CAP1H, 0xCF); + +//PWM SFRs +SFR(PWM_DATA2, 0x9B); +SFR(PWM_DATA1, 0x9C); +SFR(PWM_CTRL, 0x9D); +SFR(PWM_CK_SE, 0x9E); + +//UART0 SFRs +SFR(SCON, 0x98); +SBIT(SM0, 0x98, 7); +SBIT(SM0, 0x98, 7); +SBIT(SM1, 0x98, 6); +SBIT(SM2, 0x98, 5); +SBIT(REN, 0x98, 4); +SBIT(TB8, 0x98, 3); +SBIT(RB8, 0x98, 2); +SBIT(TI, 0x98, 1); +SBIT(RI, 0x98, 0); +SFR(SBUF, 0x99); + +//UART1 SFRs +SFR(SCON1, 0xC0); +SBIT(U1SM0, 0xC0, 7); +SBIT(U1SMOD, 0xC0, 5); +SBIT(U1REN, 0xC0, 4); +SBIT(U1TB8, 0xC0, 3); +SBIT(U1RB8, 0xC0, 2); +SBIT(U1TI, 0xC0, 1); +SBIT(U1RI, 0xC0, 0); +SFR(SBUF1, 0xC1); +SFR(SBAUD1, 0xC2); + +//SPI SFRs +SFR(SPI0_STAT, 0xF8); +SBIT(S0_FST_ACT, 0xF8, 7); +SBIT(S0_IF_OV, 0xF8, 6); +SBIT(S0_IF_FIRST, 0xF8, 5); +SBIT(S0_IF_BYTE, 0xF8, 4); +SBIT(S0_FREE, 0xF8, 3); +SBIT(S0_T_FIFO, 0xF8, 2); +SBIT(S0_R_FIFO, 0xF8, 0); +SFR(SPI0_DATA, 0xF9); +SFR(SPI0_CTRL, 0xFA); +SFR(SPI0_CK_SE, 0xFB); +SFR(SPI0_SETUP, 0xFC); + +//ADC SFRs +SFR(ADC_CTRL, 0x80); +SBIT(CMPO, 0x80, 7); +SBIT(CMP_IF, 0x80, 6); +SBIT(ADC_IF, 0x80, 5); +SBIT(ADC_START, 0x80, 4); +SBIT(CMP_CHAN, 0x80, 3); +SBIT(ADC_CHAN1, 0x80, 1); +SBIT(ADC_CHAN0, 0x80, 0); +SFR(ADC_CFG, 0x9A); +SFR(ADC_DATA, 0x9F); + +//Touch SFRs +SFR(TKEY_CTRL, 0xC3); +SFR16(TKEY_DAT, 0xC4); +SFR(TKEY_DATL, 0xC4); +SFR(TKEY_DATH, 0xC5); + +//USB SFRs +SFR(USB_C_CTRL, 0x91); +SFR(USB_CTRL, 0xE2); +SFR(UDEV_CTRL, 0xD1); +SFR(USB_DEV_AD, 0xE3); +SFR(USB_MIS_ST, 0xDA); +SFR(USB_RX_LEN, 0xDB); +SFR(USB_INT_EN, 0xE1); +SFR(USB_INT_FG, 0xD8); +SBIT(U_IS_NAK, 0xD8, 7); +SBIT(U_TOG_OK, 0xD8, 6); +SBIT(U_SIE_FREE, 0xD8, 5); +SBIT(UIF_FIFO_OV, 0xD8, 4); +SBIT(UIF_HST_SOF, 0xD8, 3); +SBIT(UIF_SUSPEND, 0xD8, 2); +SBIT(UIF_TRANSFER, 0xD8, 1); +SBIT(UIF_DETECT, 0xD8, 0); +SBIT(UIF_BUS_RST, 0xD8, 0); +SFR(USB_INT_ST, 0xD9); +SFR(UEP4_1_MOD, 0xEA); +SFR(UEP2_3_MOD, 0xEB); +SFR(UEP0_CTRL, 0xDC); +SFR(UEP0_T_LEN, 0xDD); +SFR(UEP1_CTRL, 0xD2); +SFR(UEP1_T_LEN, 0xD3); +SFR(UEP2_CTRL, 0xD4); +SFR(UEP2_T_LEN, 0xD5); +SFR(UEP3_CTRL, 0xD6); +SFR(UEP3_T_LEN, 0xD7); +SFR(UEP4_CTRL, 0xDE); +SFR(UEP4_T_LEN, 0xDF); +SFR16(UEP0_DMA, 0xEC); +SFR(UEP0_DMA_L, 0xEC); +SFR(UEP0_DMA_H, 0xED); +SFR16(UEP1_DMA, 0xEE); +SFR(UEP1_DMA_L, 0xEE); +SFR(UEP1_DMA_H, 0xEF); +SFR16(UEP2_DMA, 0xE4); +SFR(UEP2_DMA_L, 0xE4); +SFR(UEP2_DMA_H, 0xE5); +SFR16(UEP3_DMA, 0xE6); +SFR(UEP3_DMA_L, 0xE6); +SFR(UEP3_DMA_H, 0xE7); + +//Interrupt vectors +#define INT_NO_INT0 0 +#define INT_NO_TMR0 1 +#define INT_NO_INT1 2 +#define INT_NO_TMR1 3 +#define INT_NO_UART0 4 +#define INT_NO_TMR2 5 +#define INT_NO_SPI0 6 +#define INT_NO_TKEY 7 +#define INT_NO_USB 8 +#define INT_NO_ADC 9 +#define INT_NO_UART1 10 +#define INT_NO_PWMX 11 +#define INT_NO_GPIO 12 +#define INT_NO_WDOG 13 + +#endif diff --git a/project/JTAG/ch55xtool.py b/project/JTAG/ch55xtool.py new file mode 100644 index 0000000..2e976ca --- /dev/null +++ b/project/JTAG/ch55xtool.py @@ -0,0 +1,341 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + +import sys, os +import time +import array +import math +import argparse + +import usb.core +import usb.util + +#======= Some C-like static constants ======= +DFU_ID_VENDOR = 0x4348 +DFU_ID_PRODUCT = 0x55e0 + +EP_OUT_ADDR = 0x02 +EP_IN_ADDR = 0x82 + +USB_MAX_TIMEOUT = 2000 + +DETECT_CHIP_CMD_V2 = [0xa1, 0x12, 0x00, 0x52, 0x11, 0x4d, 0x43, 0x55, 0x20, 0x49, 0x53, + 0x50, 0x20, 0x26, 0x20, 0x57, 0x43, 0x48, 0x2e, 0x43, 0x4e] +END_FLASH_CMD_V2 = [0xa2, 0x01, 0x00, 0x00] +RESET_RUN_CMD_V2 = [0xa2, 0x01, 0x00, 0x01] +SEND_KEY_CMD_V20 = [0xa3, 0x30, 0x00] +SEND_KEY_CMD_V23 = [0xa3, 0x38, 0x00] + [0x00] * (0x38) +ERASE_CHIP_CMD_V2 = [0xa4, 0x01, 0x00, 0x08] +WRITE_CMD_V2 = [0xa5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] +VERIFY_CMD_V2 = [0xa6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00] +READ_CFG_CMD_V2 = [0xa7, 0x02, 0x00, 0x1f, 0x00] + +CH55X_IC_REF = {} +CH55X_IC_REF[0x51] = {'device_name': 'CH551', 'device_flash_size': 10240, 'device_dataflash_size': 128, 'chip_id': 0x51} +CH55X_IC_REF[0x52] = {'device_name': 'CH552', 'device_flash_size': 16384, 'device_dataflash_size': 128, 'chip_id': 0x52} +CH55X_IC_REF[0x53] = {'device_name': 'CH553', 'device_flash_size': 10240, 'device_dataflash_size': 128, 'chip_id': 0x53} +CH55X_IC_REF[0x54] = {'device_name': 'CH554', 'device_flash_size': 14336, 'device_dataflash_size': 128, 'chip_id': 0x54} +CH55X_IC_REF[0x59] = {'device_name': 'CH559', 'device_flash_size': 61440, 'device_dataflash_size': 128, 'chip_id': 0x59} +#============================================= + +def __get_dfu_device(idVendor=DFU_ID_VENDOR, idProduct=DFU_ID_PRODUCT): + dev = usb.core.find(idVendor=idVendor, idProduct=idProduct) + if dev is None: + return (None, 'NO_DEV_FOUND') + try: + if dev.is_kernel_driver_active(0): + try: + dev.detach_kernel_driver(0) + except usb.core.USBError: + return (None, 'USB_ERROR_CANNOT_DETACH_KERNEL_DRIVER') + except: + pass #Windows dont need detach + + try: + dev.set_configuration() + except usb.core.USBError: + return (None, 'USB_ERROR_CANNOT_SET_CONFIG') + + try: + usb.util.claim_interface(dev, 0) + except usb.core.USBError: + return (None, 'USB_ERROR_CANNOT_CLAIM_INTERFACE') + + return (dev, '') + +def __detect_ch55x_v2(dev): + dev.write(EP_OUT_ADDR, DETECT_CHIP_CMD_V2) + ret = dev.read(EP_IN_ADDR, 6, USB_MAX_TIMEOUT) + try: + return CH55X_IC_REF[ret[4]] + except KeyError: + return None + +def __read_cfg_ch55x_v2(dev): + dev.write(EP_OUT_ADDR, READ_CFG_CMD_V2) + ret = dev.read(EP_IN_ADDR, 30, USB_MAX_TIMEOUT) + + ver_str = 'V%d.%d%d' % (ret[19], ret[20], ret[21]) + chk_sum = (ret[22] + ret[23] + ret[24] + ret[25]) % 256 + + return (ver_str, chk_sum) + +def __write_key_ch55x_v20(dev, chk_sum): + SEND_KEY_CMD_V20 = SEND_KEY_CMD_V20 + [chk_sum] * 0x30 + + dev.write(EP_OUT_ADDR, SEND_KEY_CMD_V20) + ret = dev.read(EP_IN_ADDR, 6, USB_MAX_TIMEOUT) + if ret[3] == 0: + return True + else: + return None + +def __write_key_ch55x_v23(dev): + dev.write(EP_OUT_ADDR, SEND_KEY_CMD_V23) + ret = dev.read(EP_IN_ADDR, 6, USB_MAX_TIMEOUT) + if ret[3] == 0: + return True + else: + return None + +def __erase_chip_ch55x_v2(dev): + dev.write(EP_OUT_ADDR, ERASE_CHIP_CMD_V2) + ret = dev.read(EP_IN_ADDR, 6, USB_MAX_TIMEOUT) + if ret[3] == 0: + return True + else: + return None + +def __write_flash_ch55x_v20(dev, chk_sum, chip_id, payload): + payload = payload + [0] * ((math.ceil(len(payload) / 56) * 56) - len(payload)) # Payload needs to be padded, 56 is a good number + file_length = len(payload) + + for index in range(file_length): + if index % 8 == 7: + payload[index] = (payload[index] ^ ((chk_sum + chip_id) % 256)) % 256 + + left_len = file_length + curr_addr = 0 + + while curr_addr < file_length: + + if left_len >= 56: + pkt_length = 56 + else: + pkt_length = left_len + + __WRITE_CMD_V2 = WRITE_CMD_V2 + __WRITE_CMD_V2[1] = pkt_length + 5 + __WRITE_CMD_V2[3] = curr_addr % 256 + __WRITE_CMD_V2[4] = (curr_addr >> 8) % 256 + __WRITE_CMD_V2[7] = left_len % 256 + __WRITE_CMD_V2 = __WRITE_CMD_V2 + payload[curr_addr:curr_addr+pkt_length] + + dev.write(EP_OUT_ADDR, __WRITE_CMD_V2) + ret = dev.read(EP_IN_ADDR, 6, USB_MAX_TIMEOUT) + + curr_addr = curr_addr + pkt_length + left_len = left_len - pkt_length + + if ret[4] != 0x00: + return None + + return file_length + +def __write_flash_ch55x_v23(dev, chk_sum, chip_id, payload): + payload = payload + [0] * ((math.ceil(len(payload) / 56) * 56) - len(payload)) # Payload needs to be padded, 56 is a good number + file_length = len(payload) + + for index in range(file_length): + if index % 8 == 7: + payload[index] = (payload[index] ^ ((chk_sum + chip_id) % 256)) % 256 + else: + payload[index] = (payload[index] ^ chk_sum) % 256 + + left_len = file_length + curr_addr = 0 + + while curr_addr < file_length: + + if left_len >= 56: + pkt_length = 56 + else: + pkt_length = left_len + + __WRITE_CMD_V2 = WRITE_CMD_V2 + __WRITE_CMD_V2[1] = pkt_length + 5 + __WRITE_CMD_V2[3] = curr_addr % 256 + __WRITE_CMD_V2[4] = (curr_addr >> 8) % 256 + __WRITE_CMD_V2[7] = left_len % 256 + __WRITE_CMD_V2 = __WRITE_CMD_V2 + payload[curr_addr:curr_addr+pkt_length] + + dev.write(EP_OUT_ADDR, __WRITE_CMD_V2) + ret = dev.read(EP_IN_ADDR, 6, USB_MAX_TIMEOUT) + + curr_addr = curr_addr + pkt_length + left_len = left_len - pkt_length + + if ret[4] != 0x00: + return None + + return file_length + +def __verify_flash_ch55x_v20(dev, chk_sum, chip_id, payload): + payload = payload + [0] * ((math.ceil(len(payload) / 56) * 56) - len(payload)) # Payload needs to be padded, 56 is a good number + file_length = len(payload) + + for index in range(file_length): + if index % 8 == 7: + payload[index] = (payload[index] ^ ((chk_sum + chip_id) % 256)) % 256 + + left_len = file_length + curr_addr = 0 + + while curr_addr < file_length: + + if left_len >= 56: + pkt_length = 56 + else: + pkt_length = left_len + + __VERIFY_CMD_V2 = VERIFY_CMD_V2 + __VERIFY_CMD_V2[1] = pkt_length + 5 + __VERIFY_CMD_V2[3] = curr_addr % 256 + __VERIFY_CMD_V2[4] = (curr_addr >> 8) % 256 + __VERIFY_CMD_V2[7] = left_len % 256 + __VERIFY_CMD_V2 = __VERIFY_CMD_V2 + payload[curr_addr:curr_addr+pkt_length] + + dev.write(EP_OUT_ADDR, __VERIFY_CMD_V2) + ret = dev.read(EP_IN_ADDR, 6, USB_MAX_TIMEOUT) + + curr_addr = curr_addr + pkt_length + left_len = left_len - pkt_length + + if ret[4] != 0x00: + return None + + return file_length + +def __verify_flash_ch55x_v23(dev, chk_sum, chip_id, payload): + payload = payload + [0] * ((math.ceil(len(payload) / 56) * 56) - len(payload)) # Payload needs to be padded, 56 is a good number + file_length = len(payload) + + for index in range(file_length): + if index % 8 == 7: + payload[index] = (payload[index] ^ ((chk_sum + chip_id) % 256)) % 256 + else: + payload[index] = (payload[index] ^ chk_sum) % 256 + + left_len = file_length + curr_addr = 0 + + while curr_addr < file_length: + + if left_len >= 56: + pkt_length = 56 + else: + pkt_length = left_len + + __VERIFY_CMD_V2 = VERIFY_CMD_V2 + __VERIFY_CMD_V2[1] = pkt_length + 5 + __VERIFY_CMD_V2[3] = curr_addr % 256 + __VERIFY_CMD_V2[4] = (curr_addr >> 8) % 256 + __VERIFY_CMD_V2[7] = left_len % 256 + __VERIFY_CMD_V2 = __VERIFY_CMD_V2 + payload[curr_addr:curr_addr+pkt_length] + + dev.write(EP_OUT_ADDR, __VERIFY_CMD_V2) + ret = dev.read(EP_IN_ADDR, 6, USB_MAX_TIMEOUT) + + curr_addr = curr_addr + pkt_length + left_len = left_len - pkt_length + + if ret[4] != 0x00: + return None + + return file_length + +def __end_flash_ch55x_v2(dev): + dev.write(EP_OUT_ADDR, END_FLASH_CMD_V2) + ret = dev.read(EP_IN_ADDR, 6, USB_MAX_TIMEOUT) + if ret[4] != 0x00: + return None + else: + return True + +def __restart_run_ch55x_v2(dev): + dev.write(EP_OUT_ADDR, RESET_RUN_CMD_V2) + +def __main(): + parser = argparse.ArgumentParser(description="USBISP Tool For WinChipHead CH55x.") + parser.add_argument('-f', '--file', type=str, default='', help="The target file to be flashed.") + parser.add_argument('-r', '--reset_after_flash', action='store_true', default=False, help="Reset after finsh flash.") + args = parser.parse_args() + + ret = __get_dfu_device() + if ret[0] is None: + sys.exit(ret[1]) + dev = ret[0] + + ret = __detect_ch55x_v2(dev) + if ret is None: + print('Unable to detect CH55x.') + print('Found %s.' % ret['device_name']) + chip_id = ret['chip_id'] + + ret = __read_cfg_ch55x_v2(dev) + chk_sum = ret[1] + + print('BTVER: %s.' % ret[0]) + + if args.file != '': + payload = list(open(args.file, 'rb').read()) + if ret[0] in ['V2.30']: + ret = __write_key_ch55x_v20(dev, chk_sum) + if ret is None: + sys.exit('Failed to write key to CH55x.') + + ret = __erase_chip_ch55x_v2(dev) + if ret is None: + sys.exit('Failed to erase CH55x.') + + ret = __write_flash_ch55x_v20(dev, chk_sum, chip_id, payload) + if ret is None: + sys.exit('Failed to flash firmware of CH55x.') + + ret = __verify_flash_ch55x_v20(dev, chk_sum, chip_id, payload) + if ret is None: + sys.exit('Failed to verify firmware of CH55x.') + else: + if ret[0] in ['V2.31', 'V2.40']: + ret = __write_key_ch55x_v23(dev) + if ret is None: + sys.exit('Failed to write key to CH55x.') + + ret = __erase_chip_ch55x_v2(dev) + if ret is None: + sys.exit('Failed to erase CH55x.') + + ret = __write_flash_ch55x_v23(dev, chk_sum, chip_id, payload) + if ret is None: + sys.exit('Failed to flash firmware of CH55x.') + + ret = __verify_flash_ch55x_v23(dev, chk_sum, chip_id, payload) + if ret is None: + sys.exit('Failed to verify firmware of CH55x.') + else: + sys.exit('Bootloader version not supported.') + + ret = __end_flash_ch55x_v2(dev) + if ret is None: + sys.exit('Failed to end flash process.') + + print('Flash done.') + + if args.reset_after_flash: + __restart_run_ch55x_v2(dev) + print('Restart and run.') + + + +if __name__ == '__main__': + __main() diff --git a/project/JTAG/usbjtag.c b/project/JTAG/usbjtag.c new file mode 100644 index 0000000..b1df2f3 --- /dev/null +++ b/project/JTAG/usbjtag.c @@ -0,0 +1,270 @@ +/* +CH552 USB-JTAG Adapter + +Copyright (c) 2020, Bo Gao <7zlaser@gmail.com> + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, this list of + conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright notice, this list + of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. +3. Neither the name of the copyright holder nor the names of its contributors may be + used to endorse or promote products derived from this software without specific + prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include +#include +#include "ch552.h" + +//Pin map +#define TMS P14 +#define TCK P17 +#define TDI P15 +#define TDO P16 +#define ENA P33 +#define RST P32 +#define ISP P10 //Not used, pull down + +//Helper macros +#define jtag_bit(mask) {TMS=tms&mask; TDI=tdi&mask; SAFE_MOD++; TCK=1; TCK=0;} +#define jtag_bit_read(mask) {TMS=tms&mask; TDI=tdi&mask; SAFE_MOD++; tdo|=TDO?mask:0; TCK=1; TCK=0;} +#define usb_txdesc(desc) {len=sizeof(desc); len=len>*slen?*slen:len; for(i=0;iNAK + if(USB_RX_LEN!=8) goto ep0_stall; + *slen=buf_ep0[6]; + if(buf_ep0[7]) *slen=64; + len=0; + *scode=buf_ep0[1]; + if((buf_ep0[0]&0x60)==0) //Standard request + if(*scode==0x06) //Get descriptor + { + if(buf_ep0[3]==0x01) usb_txdesc(desc_dev) //Device + else if(buf_ep0[3]==0x02) usb_txdesc(desc_cfg) //Config + else if(buf_ep0[3]==0x03) //String + { + if(buf_ep0[2]==0x00) usb_txdesc(desc_lng) + else if(buf_ep0[2]==0x01) usb_txdesc(desc_pro) + else goto ep0_stall; + } + else goto ep0_stall; + } + else if(*scode==0x05) *slen=buf_ep0[2]; //Set address + else if(*scode==0x08) {buf_ep0[0]=*config; len=*slen?1:0;} //Get config + else if(*scode==0x09) *config=buf_ep0[2]; //Set config + else if(*scode==0x0a) {buf_ep0[0]=0x00; len=*slen?1:0;} //Get interface + else if(*scode==0x00) //Get status + { + if(buf_ep0[0]==0x82 && buf_ep0[4]==0x81) buf_ep0[0]=(UEP1_CTRL&0x03)==0x03?1:0; + else if(buf_ep0[0]==0x82 && buf_ep0[4]==0x01) buf_ep0[0]=(UEP1_CTRL&0x0c)==0x0c?1:0; + else buf_ep0[0]=0; + buf_ep0[1]=0; + len=*slen>2?2:*slen; + } + else if(buf_ep0[0]==0x02 && *scode==0x03) //Set feature + if(buf_ep0[4]==0x81) UEP1_CTRL|=0x03; + else if(buf_ep0[4]==0x01) UEP1_CTRL|=0x0c; + else goto ep0_stall; + else if(buf_ep0[0]==0x02 && *scode==0x01) //Clear feature + if(buf_ep0[4]==0x81) UEP1_CTRL=(UEP1_CTRL&~0x43)|0x02; + else if(buf_ep0[4]==0x01) UEP1_CTRL=(UEP1_CTRL&~0x8c); + else goto ep0_stall; + else goto ep0_stall; + else + { +ep0_stall: + *slen=*scode=0x00; + UEP0_CTRL=0x03; //IN STALL, DATA1 + return; + } + UEP0_T_LEN=len; //Max 64 bytes + UEP0_CTRL=0xc0; //DATA1 +} + +//Finished receiving from EP1 +inline void ep1_out(void) +{ + uint8_t len=USB_RX_LEN; + uint8_t cmd=buf_ep1[0]; + if(!U_TOG_OK) return; + if(len<1) return; + if((cmd&0xf0)==0x00) {RST=cmd&0x01; ENA=cmd&0x02;} //Power control + else if((cmd&0xf0)==0x10 && len&1) //JTAG write + if(!(cmd&0x01)) jtag_write(&buf_ep1[1], &buf_ep1[1+len>>1], len>>1); //Write only + else //Write and read + { + jtag_write_read(&buf_ep1[1], &buf_ep1[1+len>>1], &buf_ep1[64], len>>1); + UEP1_T_LEN=len>>1; + UEP1_CTRL&=~0x02; + } + else if((cmd&0xf0)==0x20) //SPI write + if(!(cmd&0x01)) spi_write(&buf_ep1[1], len-1, cmd&0x02); //Write only + else //Write and read + { + spi_write_read(&buf_ep1[1], &buf_ep1[64], len-1, cmd&0x02); + UEP1_T_LEN=len-1; + UEP1_CTRL&=~0x02; + } + else if(cmd==0xff) //Enter ISP mode + { + EA=0; + USB_CTRL=0x06; //Reset USB + USB_INT_FG=0xff; + for(len=0;len<255;len++) //Delay + for(cmd=0;cmd<255;cmd++) {SAFE_MOD++; SAFE_MOD++; SAFE_MOD++; SAFE_MOD++;} + ((void (*)(void))0x3800)(); //Jump to bootloader + } +} + +//USB interrupt handler +void usb_isr(void) __interrupt (INT_NO_USB) __using 1 +{ + static uint8_t scode=0, slen=0, config=0; + uint8_t token; + if(UIF_TRANSFER) //Transfer done + { + token=USB_INT_ST&0x3f; + if(token==0x21) //EP1 IN + UEP1_CTRL|=0x02; //EP1 IN NAK + else if(token==0x01) //EP1 OUT + ep1_out(); + else if(token==0x30) //EP0 SETUP + ep0_setup(&scode, &slen, &config); + else if(token==0x20) //EP0 IN + { + if(scode==0x05) USB_DEV_AD=slen; + UEP0_T_LEN=0; //Send ZLP + UEP0_CTRL=0x02; //IN NAK + } + else if(token==0x00) //EP0 OUT + UEP0_CTRL=0x02; //IN NAK + UIF_TRANSFER=0; + } + else if(UIF_BUS_RST) //Bus reset + { + UEP0_CTRL=0x02; + UEP1_CTRL=0x12; + USB_DEV_AD=0x00; + scode=slen=config=0; + USB_INT_FG=0xff; + } + else USB_INT_FG=0xff; +} diff --git a/project/JTAG/usbjtag.py b/project/JTAG/usbjtag.py new file mode 100644 index 0000000..47e30ca --- /dev/null +++ b/project/JTAG/usbjtag.py @@ -0,0 +1,139 @@ +#!/usr/bin/env python3 + +# Copyright (c) 2020, Bo Gao <7zlaser@gmail.com> + +# Redistribution and use in source and binary forms, with or without modification, +# are permitted provided that the following conditions are met: + +# 1. Redistributions of source code must retain the above copyright notice, this list of +# conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright notice, this list +# of conditions and the following disclaimer in the documentation +# and/or other materials provided with the distribution. +# 3. Neither the name of the copyright holder nor the names of its contributors may be +# used to endorse or promote products derived from this software without specific +# prior written permission. + +# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT +# SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, +# EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +# OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THE +# SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import sys, usb, time, binascii + +class GowinJTAG: + dev=None + + # Open USB device + def __init__(self): + self.dev=usb.core.find(idVendor=0x20a0, idProduct=0x4209) + if self.dev is None: + print("Error: device not found") + sys.exit(-1) + self.dev.reset() + self.dev.set_configuration() + + # Close USB device + def __del__(self): + try: + usb.util.dispose_resources(self.dev) + except Exception: pass + + # Write JTAG command + def WriteCmd(self, cmd): + self.dev.write(0x01, [0x10, 0x30, 0x80, 0x01, 0x00, cmd&0xff, 0x00]) + + # Reset FPGA + def ResetPwr(self): + self.dev.write(0x01, [0x00]) + time.sleep(0.01) + self.dev.write(0x01, [0x01]) + + # Reset JTAG + def ResetTap(self): + self.dev.write(0x01, [0x10, 0xff, 0x00, 0x00, 0x00]) + + # Reset SRAM + def ResetRam(self): + self.WriteCmd(0x15) # Enter config mode + self.WriteCmd(0x05) # Clear SRAM + self.WriteCmd(0x02) # Nop + time.sleep(0.01) # Wait for finish + self.WriteCmd(0x3a) # Exit config mode + self.WriteCmd(0x02) # Nop + + # Read JTAG ID + def ReadId(self): + self.WriteCmd(0x11) # Read JTAG ID command + self.dev.write(0x01, [0x11, 0x20, 0x00, 0x00, 0x00, 0x80, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00]) + ret=self.dev.read(0x81, 64, 100) + ret.reverse() + return bytes(ret[1:5]).hex() + + # Write SRAM + def WriteRam(self, filename): + flen=0 + self.WriteCmd(0x15) # Enter config mode + self.WriteCmd(0x17) # Write SRAM + self.dev.write(0x01, [0x10, 0x20, 0x00]) # Shift DR + with open(filename, "rb") as f: + while True: + dat=f.read(63) + if not dat: + break + # SPI mode, MSB first + self.dev.write(0x01, [0x20]+list(dat)) + flen=f.tell() + self.dev.write(0x01, [0x10, 0x03, 0x00]) # Idle + self.WriteCmd(0x3a) # Exit config mode + self.WriteCmd(0x02) # Nop + return flen + + # Enter ISP mode + def EnterIsp(self): + try: # Connection WILL break + self.dev.write(0x01, [0xff]) + except Exception: pass + +# Entry point +if __name__ == "__main__": + import argparse + import os + parser=argparse.ArgumentParser(description="USB JTAG programmer for Gowin FPGAs") + parser.add_argument("-r", action="store_true", default=False, dest="reset_fpga", help="Reset FPGA") + parser.add_argument("-c", action="store_true", default=False, dest="clear_sram", help="Clear SRAM content") + parser.add_argument("-s", action="store_true", default=False, dest="prog_sram", help="Program SRAM") + parser.add_argument("-f", action="store", dest="prog_filename", help="Specify SRAM filename") + parser.add_argument("-i", action="store_true", default=False, dest="isp_mode", help="Enter adapter ISP mode") + parser.add_argument("-v", action="store_true", default=False, dest="verbose_mode", help="Verbose output") + args=parser.parse_args() + jtag=GowinJTAG() + if args.isp_mode: + jtag.EnterIsp() + time.sleep(0.5) + sys.exit(0) + if args.reset_fpga: + jtag.ResetPwr() + jtag.ResetTap() + if args.verbose_mode: + print("Device ID is 0x"+jtag.ReadId()) + if args.clear_sram or args.prog_sram: + jtag.ResetRam() + if args.prog_sram: + if args.prog_filename is None: + print("Error: filename not specified") + sys.exit(-1) + if not os.path.exists(args.prog_filename): + print("Error: cannot open file") + sys.exit(-1) + tbegin=time.time() + flen=jtag.WriteRam(args.prog_filename) + tend=time.time() + if args.verbose_mode: + print("Programming done in {0:.2f}s at {1:.2f}kB/s.".format(tend-tbegin, flen/(tend-tbegin)/1000.0)) + sys.exit(0) diff --git a/src/template/Makefile b/src/template/Makefile new file mode 100644 index 0000000..801d189 --- /dev/null +++ b/src/template/Makefile @@ -0,0 +1,54 @@ +# MCU Configuration +FREQ_SYS ?= 24000000 +IRAM_SIZE ?= 0x100 +XRAM_SIZE ?= 0x400 +CODE_SIZE ?= 0x3800 + +SRC_DIR := ./src +OBJ_DIR := ./out +TMP_DIR := $(OBJ_DIR)/generated + +# File containing "void main(void)" function +MAIN := $(SRC_DIR)/main.c +# Target file name, do not add an extension +TARGET := flashme + +# Point to SDCC toolchain folder +TOOLCHAIN := ../sdcc-4.0.0/bin +CC := $(TOOLCHAIN)/sdcc +OBJCOPY = $(TOOLCHAIN)/sdobjcopy +CFLAGS := \ + -mmcs51 \ + --model-large \ + --iram-size $(IRAM_SIZE) \ + --xram-size $(XRAM_SIZE) \ + --code-size $(CODE_SIZE) \ + -DFREQ_SYS=$(FREQ_SYS) +LDFLAGS := $(CFLAGS) + +SRCS := $(shell find $(SRC_DIR)/ -name *.c ! -wholename $(MAIN)) +RELS := $(patsubst $(SRC_DIR)/%.c,$(TMP_DIR)/%.rel,$(SRCS)) +INC_FLAGS := $(addprefix -I,$(shell find $(SRC_DIRS) -type d ! -regex '\(.*\/\.git.*\|.\)')) + +.PHONY: all +all: $(OBJ_DIR)/$(TARGET).bin + +$(OBJ_DIR)/$(TARGET).bin: $(TMP_DIR)/$(TARGET).ihx + $(OBJCOPY) -I ihex -O binary $< $@ + +$(TMP_DIR)/$(TARGET).ihx: $(MAIN) $(RELS) $(TMP_DIR) + $(CC) $< $(RELS) -o $@ $(LDFLAGS) + +$(TMP_DIR)/%.rel: $(SRC_DIR)/%.c $(TMP_DIR) + $(CC) -c $(CFLAGS) $(INC_FLAGS) $< -o $(TMP_DIR)/ + +$(TMP_DIR): + mkdir -p $@ + +$(OBJ_DIR): + mkdir -p $@ + +.PHONY: clean +clean: + rm -rf $(TMP_DIR) + rm -rf $(OBJ_DIR) diff --git a/src/template/src/ch552.c b/src/template/src/ch552.c new file mode 100644 index 0000000..02e4b5a --- /dev/null +++ b/src/template/src/ch552.c @@ -0,0 +1,34 @@ +#include "ch552.h" + +void init_clock(void) { +#if OSC_EN_XT + SAFE_MOD = 0x55; + SAFE_MOD = 0xAA; + CLOCK_CFG |= bOSC_EN_XT; // Enable external oscillator + CLOCK_CFG &= ~bOSC_EN_INT; // Disable internal oscillator +#endif + SAFE_MOD = 0x55; + SAFE_MOD = 0xAA; +#if FREQ_SYS == 24000000 + CLOCK_CFG = (CLOCK_CFG & ~MASK_SYS_CK_SEL) | 0x06; // 24MHz +#endif +#if FREQ_SYS == 16000000 + CLOCK_CFG = (CLOCK_CFG & ~MASK_SYS_CK_SEL) | 0x05; // 16MHz +#endif +#if FREQ_SYS == 12000000 + CLOCK_CFG = (CLOCK_CFG & ~MASK_SYS_CK_SEL) | 0x04; // 12MHz +#endif +#if FREQ_SYS == 6000000 + CLOCK_CFG = (CLOCK_CFG & ~MASK_SYS_CK_SEL) | 0x03; // 6MHz +#endif +#if FREQ_SYS == 3000000 + CLOCK_CFG = (CLOCK_CFG & ~MASK_SYS_CK_SEL) | 0x02; // 3MHz +#endif +#if FREQ_SYS == 750000 + CLOCK_CFG = (CLOCK_CFG & ~MASK_SYS_CK_SEL) | 0x01; // 750KHz +#endif +#if FREQ_SYS == 187500 + CLOCK_CFG = (CLOCK_CFG & ~MASK_SYS_CK_SEL) | 0x00; // 187.5KHz +#endif + SAFE_MOD = 0x00; +} diff --git a/src/template/src/ch552.h b/src/template/src/ch552.h new file mode 100644 index 0000000..2423301 --- /dev/null +++ b/src/template/src/ch552.h @@ -0,0 +1,696 @@ +/*-------------------------------------------------------------------------- +ch552.h +Header file for CH552 microcontrollers. +**************************************** +** Copyright (C) W.ch 1999-2016 ** +** Web: http://wch.cn ** +** Translated and adapted for "compiler.h" by Iscle ** +**************************************** +--------------------------------------------------------------------------*/ + +#ifndef __CH552_H__ +#define __CH552_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/*----- SFR --------------------------------------------------------------*/ +/* sbit are bit addressable, others are byte addressable */ + +/* System Registers */ +SFR(PSW, 0xD0); // program status word +SBIT(CY, 0xD0, 7); // carry flag +SBIT(AC, 0xD0, 6); // auxiliary carry flag +SBIT(F0, 0xD0, 5); // bit addressable general purpose flag 0 +SBIT(RS1, 0xD0, 4); // register R0-R7 bank selection high bit +SBIT(RS0, 0xD0, 3); // register R0-R7 bank selection low bit +#define MASK_PSW_RS 0x18 // bit mask of register R0-R7 bank selection +// RS1 & RS0: register R0-R7 bank selection +// 00 - bank 0, R0-R7 @ address 0x00-0x07 +// 01 - bank 1, R0-R7 @ address 0x08-0x0F +// 10 - bank 2, R0-R7 @ address 0x10-0x17 +// 11 - bank 3, R0-R7 @ address 0x18-0x1F +SBIT(OV, 0xD0, 2); // overflow flag +SBIT(F1, 0xD0, 1); // bit addressable general purpose flag 1 +SBIT(P, 0xD0, 0); // ReadOnly: parity flag +SFR(ACC, 0xE0); // accumulator +SFR(B, 0xF0); // general purpose register B +SFR(SP, 0x81); // stack pointer +//SFR16(DPTR, 0x82); // DPTR pointer, little-endian +SFR(DPL, 0x82); // data pointer low +SFR(DPH, 0x83); // data pointer high +SFR(SAFE_MOD, 0xA1); // WriteOnly: writing safe mode +//SFR(CHIP_ID, 0xA1); // ReadOnly: reading chip ID +#define CHIP_ID SAFE_MOD +SFR(GLOBAL_CFG, 0xB1); // global config, Write@SafeMode +#define bBOOT_LOAD 0x20 // ReadOnly: boot loader status for discriminating BootLoader or Application: set 1 by power on reset, clear 0 by software reset +#define bSW_RESET 0x10 // software reset bit, auto clear by hardware +#define bCODE_WE 0x08 // enable flash-ROM (include code & Data-Flash) being program or erasing: 0=writing protect, 1=enable program and erase +#define bDATA_WE 0x04 // enable Data-Flash (flash-ROM data area) being program or erasing: 0=writing protect, 1=enable program and erase +#define bLDO3V3_OFF 0x02 // disable 5V->3.3V LDO: 0=enable LDO for USB and internal oscillator under 5V power, 1=disable LDO, V33 pin input external 3.3V power +#define bWDOG_EN 0x01 // enable watch-dog reset if watch-dog timer overflow: 0=as timer only, 1=enable reset if timer overflow + +/* Clock and Sleep and Power Registers */ +SFR(PCON, 0x87); // power control and reset flag +#define SMOD 0x80 // baud rate selection for UART0 mode 1/2/3: 0=slow(Fsys/128 @mode2, TF1/32 @mode1/3, no effect for TF2), +// 1=fast(Fsys/32 @mode2, TF1/16 @mode1/3, no effect for TF2) +#define bRST_FLAG1 0x20 // ReadOnly: recent reset flag high bit +#define bRST_FLAG0 0x10 // ReadOnly: recent reset flag low bit +#define MASK_RST_FLAG 0x30 // ReadOnly: bit mask of recent reset flag +#define RST_FLAG_SW 0x00 +#define RST_FLAG_POR 0x10 +#define RST_FLAG_WDOG 0x20 +#define RST_FLAG_PIN 0x30 +// bPC_RST_FLAG1 & bPC_RST_FLAG0: recent reset flag +// 00 - software reset, by bSW_RESET=1 @(bBOOT_LOAD=0 or bWDOG_EN=1) +// 01 - power on reset +// 10 - watch-dog timer overflow reset +// 11 - external input manual reset by RST pin +#define GF1 0x08 // general purpose flag bit 1 +#define GF0 0x04 // general purpose flag bit 0 +#define PD 0x02 // power-down enable bit, auto clear by wake-up hardware +SFR(CLOCK_CFG, 0xB9); // system clock config: lower 3 bits for system clock Fsys, Write@SafeMode +#define bOSC_EN_INT 0x80 // internal oscillator enable and original clock selection: 1=enable & select internal clock, 0=disable & select external clock +#define bOSC_EN_XT 0x40 // external oscillator enable, need quartz crystal or ceramic resonator between XI and XO pins +#define bWDOG_IF_TO 0x20 // ReadOnly: watch-dog timer overflow interrupt flag, cleared by reload watch-dog count or auto cleared when MCU enter interrupt routine +#define bROM_CLK_FAST 0x10 // flash-ROM clock frequency selection: 0=normal(for Fosc>=16MHz), 1=fast(for Fosc<16MHz) +#define bRST 0x08 // ReadOnly: pin RST input +#define bT2EX_ 0x08 // alternate pin for T2EX +#define bCAP2_ 0x08 // alternate pin for CAP2 +#define MASK_SYS_CK_SEL 0x07 // bit mask of system clock Fsys selection +/* + Fxt = 24MHz(8MHz~25MHz for non-USB application), from external oscillator @XI&XO + Fosc = bOSC_EN_INT ? 24MHz : Fxt + Fpll = Fosc * 4 => 96MHz (32MHz~100MHz for non-USB application) + Fusb4x = Fpll / 2 => 48MHz (Fixed) + MASK_SYS_CK_SEL[2] [1] [0] + Fsys = Fpll / 3 = 32MHz: 1 1 1 + Fsys = Fpll / 4 = 24MHz: 1 1 0 + Fsys = Fpll / 6 = 16MHz: 1 0 1 + Fsys = Fpll / 8 = 12MHz: 1 0 0 + Fsys = Fpll / 16 = 6MHz: 0 1 1 + Fsys = Fpll / 32 = 3MHz: 0 1 0 + Fsys = Fpll / 128 = 750KHz: 0 0 1 + Fsys = Fpll / 512 = 187.5KHz: 0 0 0 +*/ +SFR(WAKE_CTRL, 0xA9); // wake-up control, Write@SafeMode +#define bWAK_BY_USB 0x80 // enable wake-up by USB event +#define bWAK_RXD1_LO 0x40 // enable wake-up by RXD1 low level +#define bWAK_P1_5_LO 0x20 // enable wake-up by pin P1.5 low level +#define bWAK_P1_4_LO 0x10 // enable wake-up by pin P1.4 low level +#define bWAK_P1_3_LO 0x08 // enable wake-up by pin P1.3 low level +#define bWAK_RST_HI 0x04 // enable wake-up by pin RST high level +#define bWAK_P3_2E_3L 0x02 // enable wake-up by pin P3.2 (INT0) edge or pin P3.3 (INT1) low level +#define bWAK_RXD0_LO 0x01 // enable wake-up by RXD0 low level +SFR(RESET_KEEP, 0xFE); // value keeper during reset +SFR(WDOG_COUNT, 0xFF); // watch-dog count, count by clock frequency Fsys/65536 + +/* Interrupt Registers */ +SFR(IE, 0xA8); // interrupt enable +SBIT(EA, 0xA8, 7); // enable global interrupts: 0=disable, 1=enable if E_DIS=0 +SBIT(E_DIS, 0xA8, 6); // disable global interrupts, intend to inhibit interrupt during some flash-ROM operation: 0=enable if EA=1, 1=disable +SBIT(ET2, 0xA8, 5); // enable timer2 interrupt +SBIT(ES, 0xA8, 4); // enable UART0 interrupt +SBIT(ET1, 0xA8, 3); // enable timer1 interrupt +SBIT(EX1, 0xA8, 2); // enable external interrupt INT1 +SBIT(ET0, 0xA8, 1); // enable timer0 interrupt +SBIT(EX0, 0xA8, 0); // enable external interrupt INT0 +SFR(IP, 0xB8); // interrupt priority and current priority +SBIT(PH_FLAG, 0xB8, 7); // ReadOnly: high level priority action flag +SBIT(PL_FLAG, 0xB8, 6); // ReadOnly: low level priority action flag +// PH_FLAG & PL_FLAG: current interrupt priority +// 00 - no interrupt now +// 01 - low level priority interrupt action now +// 10 - high level priority interrupt action now +// 11 - unknown error +SBIT(PT2, 0xB8, 5); // timer2 interrupt priority level +SBIT(PS, 0xB8, 4); // UART0 interrupt priority level +SBIT(PT1, 0xB8, 3); // timer1 interrupt priority level +SBIT(PX1, 0xB8, 2); // external interrupt INT1 priority level +SBIT(PT0, 0xB8, 1); // timer0 interrupt priority level +SBIT(PX0, 0xB8, 0); // external interrupt INT0 priority level +SFR(IE_EX, 0xE8); // extend interrupt enable +SBIT(IE_WDOG, 0xE8, 7); // enable watch-dog timer interrupt +SBIT(IE_GPIO, 0xE8, 6); // enable GPIO input interrupt +SBIT(IE_PWMX, 0xE8, 5); // enable PWM1/2 interrupt +SBIT(IE_UART1, 0xE8, 4); // enable UART1 interrupt +SBIT(IE_ADC, 0xE8, 3); // enable ADC interrupt +SBIT(IE_USB, 0xE8, 2); // enable USB interrupt +SBIT(IE_TKEY, 0xE8, 1); // enable touch-key timer interrupt +SBIT(IE_SPI0, 0xE8, 0); // enable SPI0 interrupt +SFR(IP_EX, 0xE9); // extend interrupt priority +#define bIP_LEVEL 0x80 // ReadOnly: current interrupt nested level: 0=no interrupt or two levels, 1=one level +#define bIP_GPIO 0x40 // GPIO input interrupt priority level +#define bIP_PWMX 0x20 // PWM1/2 interrupt priority level +#define bIP_UART1 0x10 // UART1 interrupt priority level +#define bIP_ADC 0x08 // ADC interrupt priority level +#define bIP_USB 0x04 // USB interrupt priority level +#define bIP_TKEY 0x02 // touch-key timer interrupt priority level +#define bIP_SPI0 0x01 // SPI0 interrupt priority level +SFR(GPIO_IE, 0xC7); // GPIO interrupt enable +#define bIE_IO_EDGE 0x80 // enable GPIO edge interrupt: 0=low/high level, 1=falling/rising edge +#define bIE_RXD1_LO 0x40 // enable interrupt by RXD1 low level / falling edge +#define bIE_P1_5_LO 0x20 // enable interrupt by pin P1.5 low level / falling edge +#define bIE_P1_4_LO 0x10 // enable interrupt by pin P1.4 low level / falling edge +#define bIE_P1_3_LO 0x08 // enable interrupt by pin P1.3 low level / falling edge +#define bIE_RST_HI 0x04 // enable interrupt by pin RST high level / rising edge +#define bIE_P3_1_LO 0x02 // enable interrupt by pin P3.1 low level / falling edge +#define bIE_RXD0_LO 0x01 // enable interrupt by RXD0 low level / falling edge + +/* FlashROM and Data-Flash Registers */ +SFR16(ROM_ADDR, 0x84); // address for flash-ROM, little-endian +SFR(ROM_ADDR_L, 0x84); // address low byte for flash-ROM +SFR(ROM_ADDR_H, 0x85); // address high byte for flash-ROM +SFR16(ROM_DATA, 0x8E); // data for flash-ROM writing, little-endian +SFR(ROM_DATA_L, 0x8E); // data low byte for flash-ROM writing, data byte for Data-Flash reading/writing +SFR(ROM_DATA_H, 0x8F); // data high byte for flash-ROM writing +SFR(ROM_CTRL, 0x86); // WriteOnly: flash-ROM control +#define ROM_CMD_WRITE 0x9A // WriteOnly: flash-ROM word or Data-Flash byte write operation command +#define ROM_CMD_READ 0x8E // WriteOnly: Data-Flash byte read operation command +//SFR(ROM_STATUS, 0x86); // ReadOnly: flash-ROM status +#define ROM_STATUS ROM_CTRL +#define bROM_ADDR_OK 0x40 // ReadOnly: flash-ROM writing operation address valid flag, can be reviewed before or after operation: 0=invalid parameter, 1=address valid +#define bROM_CMD_ERR 0x02 // ReadOnly: flash-ROM operation command error flag: 0=command accepted, 1=unknown command + +/* Port Registers */ +SFR(P1, 0x90); // port 1 input & output +SBIT(SCK, 0x90, 7); // serial clock for SPI0 +SBIT(TXD1, 0x90, 7); // TXD output for UART1 +SBIT(TIN5, 0x90, 7); // TIN5 for Touch-Key +SBIT(MISO, 0x90, 6); // master serial data input or slave serial data output for SPI0 +SBIT(RXD1, 0x90, 6); // RXD input for UART1 +SBIT(TIN4, 0x90, 6); // TIN4 for Touch-Key +SBIT(MOSI, 0x90, 5); // master serial data output or slave serial data input for SPI0 +SBIT(PWM1, 0x90, 5); // PWM output for PWM1 +SBIT(TIN3, 0x90, 5); // TIN3 for Touch-Key +SBIT(UCC2, 0x90, 5); // CC2 for USB type-C +SBIT(AIN2, 0x90, 5); // AIN2 for ADC +SBIT(T2_, 0x90, 4); // alternate pin for T2 +SBIT(CAP1_, 0x90, 4); // alternate pin for CAP1 +SBIT(SCS, 0x90, 4); // slave chip-selection input for SPI0 +SBIT(TIN2, 0x90, 4); // TIN2 for Touch-Key +SBIT(UCC1, 0x90, 4); // CC1 for USB type-C +SBIT(AIN1, 0x90, 4); // AIN1 for ADC +SBIT(TXD_, 0x90, 3); // alternate pin for TXD of UART0 +SBIT(RXD_, 0x90, 2); // alternate pin for RXD of UART0 +SBIT(T2EX, 0x90, 1); // external trigger input for timer2 reload & capture +SBIT(CAP2, 0x90, 1); // capture2 input for timer2 +SBIT(TIN1, 0x90, 1); // TIN1 for Touch-Key +SBIT(VBUS2, 0x90, 1); // VBUS2 for USB type-C +SBIT(AIN0, 0x90, 1); // AIN0 for ADC +SBIT(T2, 0x90, 0); // external count input +SBIT(CAP1, 0x90, 0); // capture1 input for timer2 +SBIT(TIN0, 0x90, 0); // TIN0 for Touch-Key +SFR(P1_MOD_OC, 0x92); // port 1 output mode: 0=push-pull, 1=open-drain +SFR(P1_DIR_PU, 0x93); // port 1 direction for push-pull or pullup enable for open-drain +// Pn_MOD_OC & Pn_DIR_PU: pin input & output configuration for Pn (n=1/3) +// 0 0: float input only, without pullup resistance +// 0 1: push-pull output, strong driving high level and low level +// 1 0: open-drain output and input without pullup resistance +// 1 1: quasi-bidirectional (standard 8051 mode), open-drain output and input with pullup resistance, just driving high level strongly for 2 clocks if turning output level from low to high +#define bSCK 0x80 // serial clock for SPI0 +#define bTXD1 0x80 // TXD output for UART1 +#define bMISO 0x40 // master serial data input or slave serial data output for SPI0 +#define bRXD1 0x40 // RXD input for UART1 +#define bMOSI 0x20 // master serial data output or slave serial data input for SPI0 +#define bPWM1 0x20 // PWM output for PWM1 +#define bUCC2 0x20 // CC2 for USB type-C +#define bAIN2 0x20 // AIN2 for ADC +#define bT2_ 0x10 // alternate pin for T2 +#define bCAP1_ 0x10 // alternate pin for CAP1 +#define bSCS 0x10 // slave chip-selection input for SPI0 +#define bUCC1 0x10 // CC1 for USB type-C +#define bAIN1 0x10 // AIN1 for ADC +#define bTXD_ 0x08 // alternate pin for TXD of UART0 +#define bRXD_ 0x04 // alternate pin for RXD of UART0 +#define bT2EX 0x02 // external trigger input for timer2 reload & capture +#define bCAP2 bT2EX // capture2 input for timer2 +#define bVBUS2 0x02 // VBUS2 for USB type-C +#define bAIN0 0x02 // AIN0 for ADC +#define bT2 0x01 // external count input or clock output for timer2 +#define bCAP1 bT2 // capture1 input for timer2 +SFR(P2, 0xA0); // port 2 +SFR(P3, 0xB0); // port 3 input & output +SBIT(UDM, 0xB0, 7); // ReadOnly: pin UDM input +SBIT(UDP, 0xB0, 6); // ReadOnly: pin UDP input +SBIT(T1, 0xB0, 5); // external count input for timer1 +SBIT(PWM2, 0xB0, 4); // PWM output for PWM2 +SBIT(RXD1_, 0xB0, 4); // alternate pin for RXD1 +SBIT(T0, 0xB0, 4); // external count input for timer0 +SBIT(INT1, 0xB0, 3); // external interrupt 1 input +SBIT(TXD1_, 0xB0, 2); // alternate pin for TXD1 +SBIT(INT0, 0xB0, 2); // external interrupt 0 input +SBIT(VBUS1, 0xB0, 2); // VBUS1 for USB type-C +SBIT(AIN3, 0xB0, 2); // AIN3 for ADC +SBIT(PWM2_, 0xB0, 1); // alternate pin for PWM2 +SBIT(TXD, 0xB0, 1); // TXD output for UART0 +SBIT(PWM1_, 0xB0, 0); // alternate pin for PWM1 +SBIT(RXD, 0xB0, 0); // RXD input for UART0 +SFR(P3_MOD_OC, 0x96); // port 3 output mode: 0=push-pull, 1=open-drain +SFR(P3_DIR_PU, 0x97); // port 3 direction for push-pull or pullup enable for open-drain +#define bUDM 0x80 // ReadOnly: pin UDM input +#define bUDP 0x40 // ReadOnly: pin UDP input +#define bT1 0x20 // external count input for timer1 +#define bPWM2 0x10 // PWM output for PWM2 +#define bRXD1_ 0x10 // alternate pin for RXD1 +#define bT0 0x10 // external count input for timer0 +#define bINT1 0x08 // external interrupt 1 input +#define bTXD1_ 0x04 // alternate pin for TXD1 +#define bINT0 0x04 // external interrupt 0 input +#define bVBUS1 0x04 // VBUS1 for USB type-C +#define bAIN3 0x04 // AIN3 for ADC +#define bPWM2_ 0x02 // alternate pin for PWM2 +#define bTXD 0x02 // TXD output for UART0 +#define bPWM1_ 0x01 // alternate pin for PWM1 +#define bRXD 0x01 // RXD input for UART0 +SFR(PIN_FUNC, 0xC6); // pin function selection +#define bUSB_IO_EN 0x80 // USB UDP/UDM I/O pin enable: 0=P3.6/P3.7 as GPIO, 1=P3.6/P3.7 as USB +#define bIO_INT_ACT 0x40 // ReadOnly: GPIO interrupt request action status +#define bUART1_PIN_X 0x20 // UART1 alternate pin enable: 0=RXD1/TXD1 on P1.6/P1.7, 1=RXD1/TXD1 on P3.4/P3.2 +#define bUART0_PIN_X 0x10 // UART0 alternate pin enable: 0=RXD0/TXD0 on P3.0/P3.1, 1=RXD0/TXD0 on P1.2/P1.3 +#define bPWM2_PIN_X 0x08 // PWM2 alternate pin enable: 0=PWM2 on P3.4, 1=PWM2 on P3.1 +#define bPWM1_PIN_X 0x04 // PWM1 alternate pin enable: 0=PWM1 on P1.5, 1=PWM1 on P3.0 +#define bT2EX_PIN_X 0x02 // T2EX/CAP2 alternate pin enable: 0=T2EX/CAP2 on P1.1, 1=T2EX/CAP2 on RST +#define bT2_PIN_X 0x01 // T2/CAP1 alternate pin enable: 0=T2/CAP1 on P1.1, 1=T2/CAP1 on P1.4 +SFR(XBUS_AUX, 0xA2); // xBUS auxiliary setting +#define bUART0_TX 0x80 // ReadOnly: indicate UART0 transmittal status +#define bUART0_RX 0x40 // ReadOnly: indicate UART0 receiving status +#define bSAFE_MOD_ACT 0x20 // ReadOnly: safe mode action status +#define GF2 0x08 // general purpose flag bit 2 +#define bDPTR_AUTO_INC 0x04 // enable DPTR auto increase if finished MOVX_@DPTR instruction +#define DPS 0x01 // dual DPTR selection: 0=DPTR0 selected, 1=DPTR1 selected + +/* Timer0/1 Registers */ +SFR(TCON, 0x88); // timer 0/1 control and external interrupt control +SBIT(TF1, 0x88, 7); // timer1 overflow & interrupt flag, auto cleared when MCU enter interrupt routine +SBIT(TR1, 0x88, 6); // timer1 run enable +SBIT(TF0, 0x88, 5); // timer0 overflow & interrupt flag, auto cleared when MCU enter interrupt routine +SBIT(TR0, 0x88, 4); // timer0 run enable +SBIT(IE1, 0x88, 3); // INT1 interrupt flag, auto cleared when MCU enter interrupt routine +SBIT(IT1, 0x88, 2); // INT1 interrupt type: 0=low level action, 1=falling edge action +SBIT(IE0, 0x88, 1); // INT0 interrupt flag, auto cleared when MCU enter interrupt routine +SBIT(IT0, 0x88, 0); // INT0 interrupt type: 0=low level action, 1=falling edge action +SFR(TMOD, 0x89); // timer 0/1 mode +#define bT1_GATE 0x80 // gate control of timer1: 0=timer1 run enable while TR1=1, 1=timer1 run enable while P3.3 (INT1) pin is high and TR1=1 +#define bT1_CT 0x40 // counter or timer mode selection for timer1: 0=timer, use internal clock, 1=counter, use P3.5 (T1) pin falling edge as clock +#define bT1_M1 0x20 // timer1 mode high bit +#define bT1_M0 0x10 // timer1 mode low bit +#define MASK_T1_MOD 0x30 // bit mask of timer1 mode +// bT1_M1 & bT1_M0: timer1 mode +// 00: mode 0, 13-bit timer or counter by cascaded TH1 and lower 5 bits of TL1, the upper 3 bits of TL1 are ignored +// 01: mode 1, 16-bit timer or counter by cascaded TH1 and TL1 +// 10: mode 2, TL1 operates as 8-bit timer or counter, and TH1 provide initial value for TL1 auto-reload +// 11: mode 3, stop timer1 +#define bT0_GATE 0x08 // gate control of timer0: 0=timer0 run enable while TR0=1, 1=timer0 run enable while P3.2 (INT0) pin is high and TR0=1 +#define bT0_CT 0x04 // counter or timer mode selection for timer0: 0=timer, use internal clock, 1=counter, use P3.4 (T0) pin falling edge as clock +#define bT0_M1 0x02 // timer0 mode high bit +#define bT0_M0 0x01 // timer0 mode low bit +#define MASK_T0_MOD 0x03 // bit mask of timer0 mode +// bT0_M1 & bT0_M0: timer0 mode +// 00: mode 0, 13-bit timer or counter by cascaded TH0 and lower 5 bits of TL0, the upper 3 bits of TL0 are ignored +// 01: mode 1, 16-bit timer or counter by cascaded TH0 and TL0 +// 10: mode 2, TL0 operates as 8-bit timer or counter, and TH0 provide initial value for TL0 auto-reload +// 11: mode 3, TL0 is 8-bit timer or counter controlled by standard timer0 bits, TH0 is 8-bit timer using TF1 and controlled by TR1, timer1 run enable if it is not mode 3 +SFR(TL0, 0x8A); // low byte of timer 0 count +SFR(TL1, 0x8B); // low byte of timer 1 count +SFR(TH0, 0x8C); // high byte of timer 0 count +SFR(TH1, 0x8D); // high byte of timer 1 count + +/* UART0 Registers */ +SFR(SCON, 0x98); // UART0 control (serial port control) +SBIT(SM0, 0x98, 7); // UART0 mode bit0, selection data bit: 0=8 bits data, 1=9 bits data +SBIT(SM1, 0x98, 6); // UART0 mode bit1, selection baud rate: 0=fixed, 1=variable +// SM0 & SM1: UART0 mode +// 00 - mode 0, shift Register, baud rate fixed at: Fsys/12 +// 01 - mode 1, 8-bit UART, baud rate = variable by timer1 or timer2 overflow rate +// 10 - mode 2, 9-bit UART, baud rate fixed at: Fsys/128@SMOD=0, Fsys/32@SMOD=1 +// 11 - mode 3, 9-bit UART, baud rate = variable by timer1 or timer2 overflow rate +SBIT(SM2, 0x98, 5); // enable multi-device communication in mode 2/3 +#define MASK_UART0_MOD 0xE0 // bit mask of UART0 mode +SBIT(REN, 0x98, 4); // enable UART0 receiving +SBIT(TB8, 0x98, 3); // the 9th transmitted data bit in mode 2/3 +SBIT(RB8, 0x98, 2); // 9th data bit received in mode 2/3, or stop bit received for mode 1 +SBIT(TI, 0x98, 1); // transmit interrupt flag, set by hardware after completion of a serial transmittal, need software clear +SBIT(RI, 0x98, 0); // receive interrupt flag, set by hardware after completion of a serial receiving, need software clear +SFR(SBUF, 0x99); // UART0 data buffer: reading for receiving, writing for transmittal + +/* Timer2/Capture2 Registers */ +SFR(T2CON, 0xC8); // timer 2 control +SBIT(TF2, 0xC8, 7); // timer2 overflow & interrupt flag, need software clear, the flag will not be set when either RCLK=1 or TCLK=1 +SBIT(CAP1F, 0xC8, 7); // timer2 capture 1 interrupt flag, set by T2 edge trigger if bT2_CAP1_EN=1, need software clear +SBIT(EXF2, 0xC8, 6); // timer2 external flag, set by T2EX edge trigger if EXEN2=1, need software clear +SBIT(RCLK, 0xC8, 5); // selection UART0 receiving clock: 0=timer1 overflow pulse, 1=timer2 overflow pulse +SBIT(TCLK, 0xC8, 4); // selection UART0 transmittal clock: 0=timer1 overflow pulse, 1=timer2 overflow pulse +SBIT(EXEN2, 0xC8, 3); // enable T2EX trigger function: 0=ignore T2EX, 1=trigger reload or capture by T2EX edge +SBIT(TR2, 0xC8, 2); // timer2 run enable +SBIT(C_T2, 0xC8, 1); // timer2 clock source selection: 0=timer base internal clock, 1=external edge counter base T2 falling edge +SBIT(CP_RL2, 0xC8, 0); // timer2 function selection (force 0 if RCLK=1 or TCLK=1): 0=timer and auto reload if count overflow or T2EX edge, 1=capture by T2EX edge +SFR(T2MOD, 0xC9); // timer 2 mode and timer 0/1/2 clock mode +#define bTMR_CLK 0x80 // fastest internal clock mode for timer 0/1/2 under faster clock mode: 0=use divided clock, 1=use original Fsys as clock without dividing +#define bT2_CLK 0x40 // timer2 internal clock frequency selection: 0=standard clock, Fsys/12 for timer mode, Fsys/4 for UART0 clock mode, +// 1=faster clock, Fsys/4 @bTMR_CLK=0 or Fsys @bTMR_CLK=1 for timer mode, Fsys/2 @bTMR_CLK=0 or Fsys @bTMR_CLK=1 for UART0 clock mode +#define bT1_CLK 0x20 // timer1 internal clock frequency selection: 0=standard clock, Fsys/12, 1=faster clock, Fsys/4 if bTMR_CLK=0 or Fsys if bTMR_CLK=1 +#define bT0_CLK 0x10 // timer0 internal clock frequency selection: 0=standard clock, Fsys/12, 1=faster clock, Fsys/4 if bTMR_CLK=0 or Fsys if bTMR_CLK=1 +#define bT2_CAP_M1 0x08 // timer2 capture mode high bit +#define bT2_CAP_M0 0x04 // timer2 capture mode low bit +// bT2_CAP_M1 & bT2_CAP_M0: timer2 capture point selection +// x0: from falling edge to falling edge +// 01: from any edge to any edge (level changing) +// 11: from rising edge to rising edge +#define T2OE 0x02 // enable timer2 generated clock output: 0=disable output, 1=enable clock output at T2 pin, frequency = TF2/2 +#define bT2_CAP1_EN 0x01 // enable T2 trigger function for capture 1 of timer2 if RCLK=0 & TCLK=0 & CP_RL2=1 & C_T2=0 & T2OE=0 +SFR16(RCAP2, 0xCA); // reload & capture value, little-endian +SFR(RCAP2L, 0xCA); // low byte of reload & capture value +SFR(RCAP2H, 0xCB); // high byte of reload & capture value +SFR16(T2COUNT, 0xCC); // counter, little-endian +SFR(TL2, 0xCC); // low byte of timer 2 count +SFR(TH2, 0xCD); // high byte of timer 2 count +SFR16(T2CAP1, 0xCE); // ReadOnly: capture 1 value for timer2 +SFR(T2CAP1L, 0xCE); // ReadOnly: capture 1 value low byte for timer2 +SFR(T2CAP1H, 0xCF); // ReadOnly: capture 1 value high byte for timer2 + +/* PWM1/2 Registers */ +SFR(PWM_DATA2, 0x9B); // PWM data for PWM2 +SFR(PWM_DATA1, 0x9C); // PWM data for PWM1 +SFR(PWM_CTRL, 0x9D); // PWM 1/2 control +#define bPWM_IE_END 0x80 // enable interrupt for PWM mode cycle end +#define bPWM2_POLAR 0x40 // PWM2 output polarity: 0=default low and high action, 1=default high and low action +#define bPWM1_POLAR 0x20 // PWM1 output polarity: 0=default low and high action, 1=default high and low action +#define bPWM_IF_END 0x10 // interrupt flag for cycle end, write 1 to clear or write PWM_CYCLE or load new data to clear +#define bPWM2_OUT_EN 0x08 // PWM2 output enable +#define bPWM1_OUT_EN 0x04 // PWM1 output enable +#define bPWM_CLR_ALL 0x02 // force clear FIFO and count of PWM1/2 +SFR(PWM_CK_SE, 0x9E); // clock divisor setting + +/* SPI0/Master0/Slave Registers */ +SFR(SPI0_STAT, 0xF8); // SPI 0 status +SBIT(S0_FST_ACT, 0xF8, 7); // ReadOnly: indicate first byte received status for SPI0 +SBIT(S0_IF_OV, 0xF8, 6); // interrupt flag for slave mode FIFO overflow, direct bit address clear or write 1 to clear +SBIT(S0_IF_FIRST, 0xF8, 5); // interrupt flag for first byte received, direct bit address clear or write 1 to clear +SBIT(S0_IF_BYTE, 0xF8, 4); // interrupt flag for a byte data exchanged, direct bit address clear or write 1 to clear or accessing FIFO to clear if bS0_AUTO_IF=1 +SBIT(S0_FREE, 0xF8, 3); // ReadOnly: SPI0 free status +SBIT(S0_T_FIFO, 0xF8, 2); // ReadOnly: tx FIFO count for SPI0 +SBIT(S0_R_FIFO, 0xF8, 0); // ReadOnly: rx FIFO count for SPI0 +SFR(SPI0_DATA, 0xF9); // FIFO data port: reading for receiving, writing for transmittal +SFR(SPI0_CTRL, 0xFA); // SPI 0 control +#define bS0_MISO_OE 0x80 // SPI0 MISO output enable +#define bS0_MOSI_OE 0x40 // SPI0 MOSI output enable +#define bS0_SCK_OE 0x20 // SPI0 SCK output enable +#define bS0_DATA_DIR 0x10 // SPI0 data direction: 0=out(master_write), 1=in(master_read) +#define bS0_MST_CLK 0x08 // SPI0 master clock mode: 0=mode 0 with default low, 1=mode 3 with default high +#define bS0_2_WIRE 0x04 // enable SPI0 two wire mode: 0=3 wire (SCK+MOSI+MISO), 1=2 wire (SCK+MISO) +#define bS0_CLR_ALL 0x02 // force clear FIFO and count of SPI0 +#define bS0_AUTO_IF 0x01 // enable FIFO accessing to auto clear S0_IF_BYTE interrupt flag +SFR(SPI0_CK_SE, 0xFB); // clock divisor setting +//SFR(SPI0_S_PRE, 0xFB); // preset value for SPI slave +#define SPI0_S_PRE SPI0_CK_SE +SFR(SPI0_SETUP, 0xFC); // SPI 0 setup +#define bS0_MODE_SLV 0x80 // SPI0 slave mode: 0=master, 1=slave +#define bS0_IE_FIFO_OV 0x40 // enable interrupt for slave mode FIFO overflow +#define bS0_IE_FIRST 0x20 // enable interrupt for first byte received for SPI0 slave mode +#define bS0_IE_BYTE 0x10 // enable interrupt for a byte received +#define bS0_BIT_ORDER 0x08 // SPI0 bit data order: 0=MSB first, 1=LSB first +#define bS0_SLV_SELT 0x02 // ReadOnly: SPI0 slave mode chip selected status: 0=unselected, 1=selected +#define bS0_SLV_PRELOAD 0x01 // ReadOnly: SPI0 slave mode data pre-loading status just after chip-selection + +/* UART1 Registers */ +SFR(SCON1, 0xC0); // UART1 control (serial port control) +SBIT(U1SM0, 0xC0, 7); // UART1 mode, selection data bit: 0=8 bits data, 1=9 bits data +SBIT(U1SMOD, 0xC0, 5); // UART1 2X baud rate selection: 0=slow(Fsys/32/(256-SBAUD1)), 1=fast(Fsys/16/(256-SBAUD1)) +SBIT(U1REN, 0xC0, 4); // enable UART1 receiving +SBIT(U1TB8, 0xC0, 3); // the 9th transmitted data bit in 9 bits data mode +SBIT(U1RB8, 0xC0, 2); // 9th data bit received in 9 bits data mode, or stop bit received for 8 bits data mode +SBIT(U1TI, 0xC0, 1); // transmit interrupt flag, set by hardware after completion of a serial transmittal, need software clear +SBIT(U1RI, 0xC0, 0); // receive interrupt flag, set by hardware after completion of a serial receiving, need software clear +SFR(SBUF1, 0xC1); // UART1 data buffer: reading for receiving, writing for transmittal +SFR(SBAUD1, 0xC2); // UART1 baud rate setting + +/* ADC and comparator Registers */ +SFR(ADC_CTRL, 0x80); // ADC control +SBIT(CMPO, 0x80, 7); // ReadOnly: comparator result input +SBIT(CMP_IF, 0x80, 6); // flag for comparator result changed, direct bit address clear +SBIT(ADC_IF, 0x80, 5); // interrupt flag for ADC finished, direct bit address clear +SBIT(ADC_START, 0x80, 4); // set 1 to start ADC, auto cleared when ADC finished +SBIT(CMP_CHAN, 0x80, 3); // comparator IN- input channel selection: 0=AIN1, 1=AIN3 +SBIT(ADC_CHAN1, 0x80, 1); // ADC/comparator IN+ channel selection high bit +SBIT(ADC_CHAN0, 0x80, 0); // ADC/comparator IN+ channel selection low bit +// ADC_CHAN1 & ADC_CHAN0: ADC/comparator IN+ channel selection +// 00: AIN0(P1.1) +// 01: AIN1(P1.4) +// 10: AIN2(P1.5) +// 11: AIN3(P3.2) +SFR(ADC_CFG, 0x9A); // ADC config +#define bADC_EN 0x08 // control ADC power: 0=shut down ADC, 1=enable power for ADC +#define bCMP_EN 0x04 // control comparator power: 0=shut down comparator, 1=enable power for comparator +#define bADC_CLK 0x01 // ADC clock frequency selection: 0=slow clock, 384 Fosc cycles for each ADC, 1=fast clock, 96 Fosc cycles for each ADC +SFR(ADC_DATA, 0x9F); // ReadOnly: ADC data + +/* Touch-key timer Registers */ +SFR(TKEY_CTRL, 0xC3); // touch-key control +#define bTKC_IF 0x80 // ReadOnly: interrupt flag for touch-key timer, cleared by writing touch-key control or auto cleared when start touch-key checking +#define bTKC_2MS 0x10 // touch-key timer cycle selection: 0=1mS, 1=2mS +#define bTKC_CHAN2 0x04 // touch-key channel selection high bit +#define bTKC_CHAN1 0x02 // touch-key channel selection middle bit +#define bTKC_CHAN0 0x01 // touch-key channel selection low bit +// bTKC_CHAN2 & bTKC_CHAN1 & bTKC_CHAN0: touch-key channel selection +// 000: disable touch-key +// 001: TIN0(P1.0) +// 010: TIN1(P1.1) +// 011: TIN2(P1.4) +// 100: TIN3(P1.5) +// 101: TIN4(P1.6) +// 110: TIN5(P1.7) +// 111: enable touch-key but disable all channel +SFR16(TKEY_DAT, 0xC4); // ReadOnly: touch-key data, little-endian +SFR(TKEY_DATL, 0xC4); // ReadOnly: low byte of touch-key data +SFR(TKEY_DATH, 0xC5); // ReadOnly: high byte of touch-key data +#define bTKD_CHG 0x80 // ReadOnly: indicate control changed, current data maybe invalid + +/* USB Device Registers */ +SFR(USB_C_CTRL, 0x91); // USB type-C control +#define bVBUS2_PD_EN 0x80 // USB VBUS2 10K pulldown resistance: 0=disable, 1=enable pullup +#define bUCC2_PD_EN 0x40 // USB CC2 5.1K pulldown resistance: 0=disable, 1=enable pulldown +#define bUCC2_PU1_EN 0x20 // USB CC2 pullup resistance control high bit +#define bUCC2_PU0_EN 0x10 // USB CC2 pullup resistance control low bit +#define bVBUS1_PD_EN 0x08 // USB VBUS1 10K pulldown resistance: 0=disable, 1=enable pullup +#define bUCC1_PD_EN 0x04 // USB CC1 5.1K pulldown resistance: 0=disable, 1=enable pulldown +#define bUCC1_PU1_EN 0x02 // USB CC1 pullup resistance control high bit +#define bUCC1_PU0_EN 0x01 // USB CC1 pullup resistance control low bit +// bUCC?_PU1_EN & bUCC?_PU0_EN: USB CC pullup resistance selection +// 00: disable pullup resistance +// 01: enable 56K pullup resistance for default USB power +// 10: enable 22K pullup resistance for 1.5A USB power +// 11: enable 10K pullup resistance for 3A USB power +SFR(UDEV_CTRL, 0xD1); // USB device physical port control +#define bUD_PD_DIS 0x80 // disable USB UDP/UDM pulldown resistance: 0=enable pulldown, 1=disable +#define bUD_DP_PIN 0x20 // ReadOnly: indicate current UDP pin level +#define bUD_DM_PIN 0x10 // ReadOnly: indicate current UDM pin level +#define bUD_LOW_SPEED 0x04 // enable USB physical port low speed: 0=full speed, 1=low speed +#define bUD_GP_BIT 0x02 // general purpose bit +#define bUD_PORT_EN 0x01 // enable USB physical port I/O: 0=disable, 1=enable +SFR(UEP1_CTRL, 0xD2); // endpoint 1 control +#define bUEP_R_TOG 0x80 // expected data toggle flag of USB endpoint X receiving (OUT): 0=DATA0, 1=DATA1 +#define bUEP_T_TOG 0x40 // prepared data toggle flag of USB endpoint X transmittal (IN): 0=DATA0, 1=DATA1 +#define bUEP_AUTO_TOG 0x10 // enable automatic toggle after successful transfer completion on endpoint 1/2/3: 0=manual toggle, 1=automatic toggle +#define bUEP_R_RES1 0x08 // handshake response type high bit for USB endpoint X receiving (OUT) +#define bUEP_R_RES0 0x04 // handshake response type low bit for USB endpoint X receiving (OUT) +#define MASK_UEP_R_RES 0x0C // bit mask of handshake response type for USB endpoint X receiving (OUT) +#define UEP_R_RES_ACK 0x00 +#define UEP_R_RES_TOUT 0x04 +#define UEP_R_RES_NAK 0x08 +#define UEP_R_RES_STALL 0x0C +// bUEP_R_RES1 & bUEP_R_RES0: handshake response type for USB endpoint X receiving (OUT) +// 00: ACK (ready) +// 01: no response, time out to host, for non-zero endpoint isochronous transactions +// 10: NAK (busy) +// 11: STALL (error) +#define bUEP_T_RES1 0x02 // handshake response type high bit for USB endpoint X transmittal (IN) +#define bUEP_T_RES0 0x01 // handshake response type low bit for USB endpoint X transmittal (IN) +#define MASK_UEP_T_RES 0x03 // bit mask of handshake response type for USB endpoint X transmittal (IN) +#define UEP_T_RES_ACK 0x00 +#define UEP_T_RES_TOUT 0x01 +#define UEP_T_RES_NAK 0x02 +#define UEP_T_RES_STALL 0x03 +// bUEP_T_RES1 & bUEP_T_RES0: handshake response type for USB endpoint X transmittal (IN) +// 00: DATA0 or DATA1 then expecting ACK (ready) +// 01: DATA0 or DATA1 then expecting no response, time out from host, for non-zero endpoint isochronous transactions +// 10: NAK (busy) +// 11: STALL (error) +SFR(UEP1_T_LEN, 0xD3); // endpoint 1 transmittal length +SFR(UEP2_CTRL, 0xD4); // endpoint 2 control +SFR(UEP2_T_LEN, 0xD5); // endpoint 2 transmittal length +SFR(UEP3_CTRL, 0xD6); // endpoint 3 control +SFR(UEP3_T_LEN, 0xD7); // endpoint 3 transmittal length +SFR(USB_INT_FG, 0xD8); // USB interrupt flag +SBIT(U_IS_NAK, 0xD8, 7); // ReadOnly: indicate current USB transfer is NAK received +SBIT(U_TOG_OK, 0xD8, 6); // ReadOnly: indicate current USB transfer toggle is OK +SBIT(U_SIE_FREE, 0xD8, 5); // ReadOnly: indicate USB SIE free status +SBIT(UIF_FIFO_OV, 0xD8, 4); // FIFO overflow interrupt flag for USB, direct bit address clear or write 1 to clear +SBIT(UIF_SUSPEND, 0xD8, 2); // USB suspend or resume event interrupt flag, direct bit address clear or write 1 to clear +SBIT(UIF_TRANSFER, 0xD8, 1); // USB transfer completion interrupt flag, direct bit address clear or write 1 to clear +SBIT(UIF_BUS_RST, 0xD8, 0); // bus reset event interrupt flag, direct bit address clear or write 1 to clear +SFR(USB_INT_ST, 0xD9); // ReadOnly: USB interrupt status +#define bUIS_IS_NAK 0x80 // ReadOnly: indicate current USB transfer is NAK received +#define bUIS_TOG_OK 0x40 // ReadOnly: indicate current USB transfer toggle is OK +#define bUIS_TOKEN1 0x20 // ReadOnly: current token PID code bit 1 received +#define bUIS_TOKEN0 0x10 // ReadOnly: current token PID code bit 0 received +#define MASK_UIS_TOKEN 0x30 // ReadOnly: bit mask of current token PID code received +#define UIS_TOKEN_OUT 0x00 +#define UIS_TOKEN_SOF 0x10 +#define UIS_TOKEN_IN 0x20 +#define UIS_TOKEN_SETUP 0x30 +// bUIS_TOKEN1 & bUIS_TOKEN0: current token PID code received +// 00: OUT token PID received +// 01: SOF token PID received +// 10: IN token PID received +// 11: SETUP token PID received +#define MASK_UIS_ENDP 0x0F // ReadOnly: bit mask of current transfer endpoint number +SFR(USB_MIS_ST, 0xDA); // ReadOnly: USB miscellaneous status +#define bUMS_SIE_FREE 0x20 // ReadOnly: indicate USB SIE free status +#define bUMS_R_FIFO_RDY 0x10 // ReadOnly: indicate USB receiving FIFO ready status (not empty) +#define bUMS_BUS_RESET 0x08 // ReadOnly: indicate USB bus reset status +#define bUMS_SUSPEND 0x04 // ReadOnly: indicate USB suspend status +SFR(USB_RX_LEN, 0xDB); // ReadOnly: USB receiving length +SFR(UEP0_CTRL, 0xDC); // endpoint 0 control +SFR(UEP0_T_LEN, 0xDD); // endpoint 0 transmittal length +SFR(UEP4_CTRL, 0xDE); // endpoint 4 control +SFR(UEP4_T_LEN, 0xDF); // endpoint 4 transmittal length +SFR(USB_INT_EN, 0xE1); // USB interrupt enable +#define bUIE_DEV_SOF 0x80 // enable interrupt for SOF received +#define bUIE_DEV_NAK 0x40 // enable interrupt for NAK responded +#define bUIE_FIFO_OV 0x10 // enable interrupt for FIFO overflow +#define bUIE_SUSPEND 0x04 // enable interrupt for USB suspend or resume event +#define bUIE_TRANSFER 0x02 // enable interrupt for USB transfer completion +#define bUIE_BUS_RST 0x01 // enable interrupt for USB bus reset event +SFR(USB_CTRL, 0xE2); // USB base control +#define bUC_LOW_SPEED 0x40 // enable USB low speed: 0=full speed, 1=low speed +#define bUC_DEV_PU_EN 0x20 // USB device enable and internal pullup resistance enable +#define bUC_SYS_CTRL1 0x20 // USB system control high bit +#define bUC_SYS_CTRL0 0x10 // USB system control low bit +#define MASK_UC_SYS_CTRL 0x30 // bit mask of USB system control +// bUC_SYS_CTRL1 & bUC_SYS_CTRL0: USB system control +// 00: disable USB device and disable internal pullup resistance +// 01: enable USB device and disable internal pullup resistance, need external pullup resistance +// 1x: enable USB device and enable internal pullup resistance +#define bUC_INT_BUSY 0x08 // enable automatic responding busy during interrupt flag UIF_TRANSFER valid +#define bUC_RESET_SIE 0x04 // force reset USB SIE, need software clear +#define bUC_CLR_ALL 0x02 // force clear FIFO and count of USB +#define bUC_DMA_EN 0x01 // DMA enable and DMA interrupt enable for USB +SFR(USB_DEV_AD, 0xE3); // USB device address, lower 7 bits for USB device address +#define bUDA_GP_BIT 0x80 // general purpose bit +#define MASK_USB_ADDR 0x7F // bit mask for USB device address +SFR16(UEP2_DMA, 0xE4); // endpoint 2 buffer start address, little-endian +SFR(UEP2_DMA_L, 0xE4); // endpoint 2 buffer start address low byte +SFR(UEP2_DMA_H, 0xE5); // endpoint 2 buffer start address high byte +SFR16(UEP3_DMA, 0xE6); // endpoint 3 buffer start address, little-endian +SFR(UEP3_DMA_L, 0xE6); // endpoint 3 buffer start address low byte +SFR(UEP3_DMA_H, 0xE7); // endpoint 3 buffer start address high byte +SFR(UEP4_1_MOD, 0xEA); // endpoint 4/1 mode +#define bUEP1_RX_EN 0x80 // enable USB endpoint 1 receiving (OUT) +#define bUEP1_TX_EN 0x40 // enable USB endpoint 1 transmittal (IN) +#define bUEP1_BUF_MOD 0x10 // buffer mode of USB endpoint 1 +// bUEPn_RX_EN & bUEPn_TX_EN & bUEPn_BUF_MOD: USB endpoint 1/2/3 buffer mode, buffer start address is UEPn_DMA +// 0 0 x: disable endpoint and disable buffer +// 1 0 0: 64 bytes buffer for receiving (OUT endpoint) +// 1 0 1: dual 64 bytes buffer by toggle bit bUEP_R_TOG selection for receiving (OUT endpoint), total=128bytes +// 0 1 0: 64 bytes buffer for transmittal (IN endpoint) +// 0 1 1: dual 64 bytes buffer by toggle bit bUEP_T_TOG selection for transmittal (IN endpoint), total=128bytes +// 1 1 0: 64 bytes buffer for receiving (OUT endpoint) + 64 bytes buffer for transmittal (IN endpoint), total=128bytes +// 1 1 1: dual 64 bytes buffer by bUEP_R_TOG selection for receiving (OUT endpoint) + dual 64 bytes buffer by bUEP_T_TOG selection for transmittal (IN endpoint), total=256bytes +#define bUEP4_RX_EN 0x08 // enable USB endpoint 4 receiving (OUT) +#define bUEP4_TX_EN 0x04 // enable USB endpoint 4 transmittal (IN) +// bUEP4_RX_EN & bUEP4_TX_EN: USB endpoint 4 buffer mode, buffer start address is UEP0_DMA +// 0 0: single 64 bytes buffer for endpoint 0 receiving & transmittal (OUT & IN endpoint) +// 1 0: single 64 bytes buffer for endpoint 0 receiving & transmittal (OUT & IN endpoint) + 64 bytes buffer for endpoint 4 receiving (OUT endpoint), total=128bytes +// 0 1: single 64 bytes buffer for endpoint 0 receiving & transmittal (OUT & IN endpoint) + 64 bytes buffer for endpoint 4 transmittal (IN endpoint), total=128bytes +// 1 1: single 64 bytes buffer for endpoint 0 receiving & transmittal (OUT & IN endpoint) +// + 64 bytes buffer for endpoint 4 receiving (OUT endpoint) + 64 bytes buffer for endpoint 4 transmittal (IN endpoint), total=192bytes +SFR(UEP2_3_MOD, 0xEB); // endpoint 2/3 mode +#define bUEP3_RX_EN 0x80 // enable USB endpoint 3 receiving (OUT) +#define bUEP3_TX_EN 0x40 // enable USB endpoint 3 transmittal (IN) +#define bUEP3_BUF_MOD 0x10 // buffer mode of USB endpoint 3 +#define bUEP2_RX_EN 0x08 // enable USB endpoint 2 receiving (OUT) +#define bUEP2_TX_EN 0x04 // enable USB endpoint 2 transmittal (IN) +#define bUEP2_BUF_MOD 0x01 // buffer mode of USB endpoint 2 +SFR16(UEP0_DMA, 0xEC); // endpoint 0 buffer start address, little-endian +SFR(UEP0_DMA_L, 0xEC); // endpoint 0 buffer start address low byte +SFR(UEP0_DMA_H, 0xED); // endpoint 0 buffer start address high byte +SFR16(UEP1_DMA, 0xEE); // endpoint 1 buffer start address, little-endian +SFR(UEP1_DMA_L, 0xEE); // endpoint 1 buffer start address low byte +SFR(UEP1_DMA_H, 0xEF); // endpoint 1 buffer start address high byte + +/*----- XDATA: xRAM ------------------------------------------*/ + +#define XDATA_RAM_SIZE 0x0400 // size of expanded xRAM, xdata SRAM embedded chip + +/*----- Reference Information --------------------------------------------*/ +#define ID_CH552 0x52 // chip ID +#define ID_CH551 0x51 // chip ID + +/* Interrupt routine address and interrupt number */ +#define INT_ADDR_INT0 0x0003 // interrupt vector address for INT0 +#define INT_ADDR_TMR0 0x000B // interrupt vector address for timer0 +#define INT_ADDR_INT1 0x0013 // interrupt vector address for INT1 +#define INT_ADDR_TMR1 0x001B // interrupt vector address for timer1 +#define INT_ADDR_UART0 0x0023 // interrupt vector address for UART0 +#define INT_ADDR_TMR2 0x002B // interrupt vector address for timer2 +#define INT_ADDR_SPI0 0x0033 // interrupt vector address for SPI0 +#define INT_ADDR_TKEY 0x003B // interrupt vector address for touch-key timer +#define INT_ADDR_USB 0x0043 // interrupt vector address for USB +#define INT_ADDR_ADC 0x004B // interrupt vector address for ADC +#define INT_ADDR_UART1 0x0053 // interrupt vector address for UART1 +#define INT_ADDR_PWMX 0x005B // interrupt vector address for PWM1/2 +#define INT_ADDR_GPIO 0x0063 // interrupt vector address for GPIO +#define INT_ADDR_WDOG 0x006B // interrupt vector address for watch-dog timer +#define INT_NO_INT0 0 // interrupt number for INT0 +#define INT_NO_TMR0 1 // interrupt number for timer0 +#define INT_NO_INT1 2 // interrupt number for INT1 +#define INT_NO_TMR1 3 // interrupt number for timer1 +#define INT_NO_UART0 4 // interrupt number for UART0 +#define INT_NO_TMR2 5 // interrupt number for timer2 +#define INT_NO_SPI0 6 // interrupt number for SPI0 +#define INT_NO_TKEY 7 // interrupt number for touch-key timer +#define INT_NO_USB 8 // interrupt number for USB +#define INT_NO_ADC 9 // interrupt number for ADC +#define INT_NO_UART1 10 // interrupt number for UART1 +#define INT_NO_PWMX 11 // interrupt number for PWM1/2 +#define INT_NO_GPIO 12 // interrupt number for GPIO +#define INT_NO_WDOG 13 // interrupt number for watch-dog timer + +/* Special Program Space */ +#define DATA_FLASH_ADDR 0xC000 // start address of Data-Flash +#define BOOT_LOAD_ADDR 0x3800 // start address of boot loader program +#define ROM_CFG_ADDR 0x3FF8 // chip configuration information address +#define ROM_CHIP_ID_HX 0x3FFA // chip ID number highest byte (only low byte valid) +#define ROM_CHIP_ID_LO 0x3FFC // chip ID number low word +#define ROM_CHIP_ID_HI 0x3FFE // chip ID number high word + +/* +New Instruction: MOVX @DPTR1,A +Instruction Code: 0xA5 +Instruction Cycle: 1 +Instruction Operation: + step-1. write ACC @DPTR1 into xdata SRAM embedded chip + step-2. increase DPTR1 +ASM example: + INC XBUS_AUX + MOV DPTR,#TARGET_ADDR ;DPTR1 + DEC XBUS_AUX + MOV DPTR,#SOURCE_ADDR ;DPTR0 + MOV R7,#xxH + LOOP: MOVX A,@DPTR ;DPTR0 + INC DPTR ;DPTR0, if need + DB 0A5H ;MOVX @DPTR1,A & INC DPTR1 + DJNZ R7,LOOP +*/ + +void init_clock(void); + +#ifdef __cplusplus +} +#endif + +#endif // __CH552_H__ diff --git a/src/template/src/ch552_usb.h b/src/template/src/ch552_usb.h new file mode 100644 index 0000000..b3c9a2e --- /dev/null +++ b/src/template/src/ch552_usb.h @@ -0,0 +1,344 @@ +/*-------------------------------------------------------------------------- +ch552_usb.h +USB header file for CH552 microcontrollers. +**************************************** +** Copyright (C) W.ch 1999-2016 ** +** Web: http://wch.cn ** +** Adapted by Iscle ** +**************************************** +--------------------------------------------------------------------------*/ + +#ifndef __CH552_USB_H__ +#define __CH552_USB_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +/*----- USB constant and structure define --------------------------------*/ + +/* USB PID */ +#ifndef USB_PID_SETUP +#define USB_PID_NULL 0x00 /* reserved PID */ +#define USB_PID_SOF 0x05 +#define USB_PID_SETUP 0x0D +#define USB_PID_IN 0x09 +#define USB_PID_OUT 0x01 +#define USB_PID_ACK 0x02 +#define USB_PID_NAK 0x0A +#define USB_PID_STALL 0x0E +#define USB_PID_DATA0 0x03 +#define USB_PID_DATA1 0x0B +#define USB_PID_PRE 0x0C +#endif + +/* USB standard device request code */ +#ifndef USB_GET_DESCRIPTOR +#define USB_GET_STATUS 0x00 +#define USB_CLEAR_FEATURE 0x01 +#define USB_SET_FEATURE 0x03 +#define USB_SET_ADDRESS 0x05 +#define USB_GET_DESCRIPTOR 0x06 +#define USB_SET_DESCRIPTOR 0x07 +#define USB_GET_CONFIGURATION 0x08 +#define USB_SET_CONFIGURATION 0x09 +#define USB_GET_INTERFACE 0x0A +#define USB_SET_INTERFACE 0x0B +#define USB_SYNCH_FRAME 0x0C +#endif + +/* USB hub class request code */ +#ifndef HUB_GET_DESCRIPTOR +#define HUB_GET_STATUS 0x00 +#define HUB_CLEAR_FEATURE 0x01 +#define HUB_GET_STATE 0x02 +#define HUB_SET_FEATURE 0x03 +#define HUB_GET_DESCRIPTOR 0x06 +#define HUB_SET_DESCRIPTOR 0x07 +#endif + +/* USB HID class request code */ +#ifndef HID_GET_REPORT +#define HID_GET_REPORT 0x01 +#define HID_GET_IDLE 0x02 +#define HID_GET_PROTOCOL 0x03 +#define HID_SET_REPORT 0x09 +#define HID_SET_IDLE 0x0A +#define HID_SET_PROTOCOL 0x0B +#endif + +/* Bit define for USB request type */ +#ifndef USB_REQ_TYP_MASK +#define USB_REQ_TYP_IN 0x80 /* control IN, device to host */ +#define USB_REQ_TYP_OUT 0x00 /* control OUT, host to device */ +#define USB_REQ_TYP_READ 0x80 /* control read, device to host */ +#define USB_REQ_TYP_WRITE 0x00 /* control write, host to device */ +#define USB_REQ_TYP_MASK 0x60 /* bit mask of request type */ +#define USB_REQ_TYP_STANDARD 0x00 +#define USB_REQ_TYP_CLASS 0x20 +#define USB_REQ_TYP_VENDOR 0x40 +#define USB_REQ_TYP_RESERVED 0x60 +#define USB_REQ_RECIP_MASK 0x1F /* bit mask of request recipient */ +#define USB_REQ_RECIP_DEVICE 0x00 +#define USB_REQ_RECIP_INTERF 0x01 +#define USB_REQ_RECIP_ENDP 0x02 +#define USB_REQ_RECIP_OTHER 0x03 +#endif + +/* USB request type for hub class request */ +#ifndef HUB_GET_HUB_DESCRIPTOR +#define HUB_CLEAR_HUB_FEATURE 0x20 +#define HUB_CLEAR_PORT_FEATURE 0x23 +#define HUB_GET_BUS_STATE 0xA3 +#define HUB_GET_HUB_DESCRIPTOR 0xA0 +#define HUB_GET_HUB_STATUS 0xA0 +#define HUB_GET_PORT_STATUS 0xA3 +#define HUB_SET_HUB_DESCRIPTOR 0x20 +#define HUB_SET_HUB_FEATURE 0x20 +#define HUB_SET_PORT_FEATURE 0x23 +#endif + +/* Hub class feature selectors */ +#ifndef HUB_PORT_RESET +#define HUB_C_HUB_LOCAL_POWER 0 +#define HUB_C_HUB_OVER_CURRENT 1 +#define HUB_PORT_CONNECTION 0 +#define HUB_PORT_ENABLE 1 +#define HUB_PORT_SUSPEND 2 +#define HUB_PORT_OVER_CURRENT 3 +#define HUB_PORT_RESET 4 +#define HUB_PORT_POWER 8 +#define HUB_PORT_LOW_SPEED 9 +#define HUB_C_PORT_CONNECTION 16 +#define HUB_C_PORT_ENABLE 17 +#define HUB_C_PORT_SUSPEND 18 +#define HUB_C_PORT_OVER_CURRENT 19 +#define HUB_C_PORT_RESET 20 +#endif + +/* USB descriptor type */ +#ifndef USB_DESCR_TYP_DEVICE +#define USB_DESCR_TYP_DEVICE 0x01 +#define USB_DESCR_TYP_CONFIG 0x02 +#define USB_DESCR_TYP_STRING 0x03 +#define USB_DESCR_TYP_INTERF 0x04 +#define USB_DESCR_TYP_ENDP 0x05 +#define USB_DESCR_TYP_QUALIF 0x06 +#define USB_DESCR_TYP_SPEED 0x07 +#define USB_DESCR_TYP_OTG 0x09 +#define USB_DESCR_TYP_HID 0x21 +#define USB_DESCR_TYP_REPORT 0x22 +#define USB_DESCR_TYP_PHYSIC 0x23 +#define USB_DESCR_TYP_CS_INTF 0x24 +#define USB_DESCR_TYP_CS_ENDP 0x25 +#define USB_DESCR_TYP_HUB 0x29 +#endif + +/* USB device class */ +#ifndef USB_DEV_CLASS_HUB +#define USB_DEV_CLASS_RESERVED 0x00 +#define USB_DEV_CLASS_AUDIO 0x01 +#define USB_DEV_CLASS_COMMUNIC 0x02 +#define USB_DEV_CLASS_HID 0x03 +#define USB_DEV_CLASS_MONITOR 0x04 +#define USB_DEV_CLASS_PHYSIC_IF 0x05 +#define USB_DEV_CLASS_POWER 0x06 +#define USB_DEV_CLASS_PRINTER 0x07 +#define USB_DEV_CLASS_STORAGE 0x08 +#define USB_DEV_CLASS_HUB 0x09 +#define USB_DEV_CLASS_VEN_SPEC 0xFF +#endif + +/* USB endpoint type and attributes */ +#ifndef USB_ENDP_TYPE_MASK +#define USB_ENDP_DIR_MASK 0x80 +#define USB_ENDP_ADDR_MASK 0x0F +#define USB_ENDP_TYPE_MASK 0x03 +#define USB_ENDP_TYPE_CTRL 0x00 +#define USB_ENDP_TYPE_ISOCH 0x01 +#define USB_ENDP_TYPE_BULK 0x02 +#define USB_ENDP_TYPE_INTER 0x03 +#endif + +#ifndef USB_DEVICE_ADDR +#define USB_DEVICE_ADDR 0x02 /* default USB device address */ +#endif +#ifndef DEFAULT_ENDP0_SIZE +#define DEFAULT_ENDP0_SIZE 8 /* default maximum packet size for endpoint 0 */ +#endif +#ifndef MAX_PACKET_SIZE +#define MAX_PACKET_SIZE 64 /* maximum packet size */ +#endif +#ifndef USB_BO_CBW_SIZE +#define USB_BO_CBW_SIZE 0x1F /* total length of CBW command block */ +#define USB_BO_CSW_SIZE 0x0D /* total length of CSW status block*/ +#endif +#ifndef USB_BO_CBW_SIG0 +#define USB_BO_CBW_SIG0 0x55 /* command block CBW 'USBC' identification flag */ +#define USB_BO_CBW_SIG1 0x53 +#define USB_BO_CBW_SIG2 0x42 +#define USB_BO_CBW_SIG3 0x43 +#define USB_BO_CSW_SIG0 0x55 /* command status CSW 'USBS' identification flag*/ +#define USB_BO_CSW_SIG1 0x53 +#define USB_BO_CSW_SIG2 0x42 +#define USB_BO_CSW_SIG3 0x53 +#endif + +typedef struct _USB_SETUP_REQ { + uint8_t bRequestType; + uint8_t bRequest; + uint8_t wValueL; + uint8_t wValueH; + uint8_t wIndexL; + uint8_t wIndexH; + uint8_t wLengthL; + uint8_t wLengthH; +} USB_SETUP_REQ, *PUSB_SETUP_REQ; + +typedef USB_SETUP_REQ xdata *PXUSB_SETUP_REQ; + +typedef struct _USB_DEVICE_DESCR { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bcdUSBL; + uint8_t bcdUSBH; + uint8_t bDeviceClass; + uint8_t bDeviceSubClass; + uint8_t bDeviceProtocol; + uint8_t bMaxPacketSize0; + uint8_t idVendorL; + uint8_t idVendorH; + uint8_t idProductL; + uint8_t idProductH; + uint8_t bcdDeviceL; + uint8_t bcdDeviceH; + uint8_t iManufacturer; + uint8_t iProduct; + uint8_t iSerialNumber; + uint8_t bNumConfigurations; +} USB_DEV_DESCR, *PUSB_DEV_DESCR; + +typedef USB_DEV_DESCR xdata *PXUSB_DEV_DESCR; + +typedef struct _USB_CONFIG_DESCR { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t wTotalLengthL; + uint8_t wTotalLengthH; + uint8_t bNumInterfaces; + uint8_t bConfigurationValue; + uint8_t iConfiguration; + uint8_t bmAttributes; + uint8_t MaxPower; +} USB_CFG_DESCR, *PUSB_CFG_DESCR; + +typedef USB_CFG_DESCR xdata *PXUSB_CFG_DESCR; + +typedef struct _USB_INTERF_DESCR { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bInterfaceNumber; + uint8_t bAlternateSetting; + uint8_t bNumEndpoints; + uint8_t bInterfaceClass; + uint8_t bInterfaceSubClass; + uint8_t bInterfaceProtocol; + uint8_t iInterface; +} USB_ITF_DESCR, *PUSB_ITF_DESCR; + +typedef USB_ITF_DESCR xdata *PXUSB_ITF_DESCR; + +typedef struct _USB_ENDPOINT_DESCR { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bEndpointAddress; + uint8_t bmAttributes; + uint8_t wMaxPacketSizeL; + uint8_t wMaxPacketSizeH; + uint8_t bInterval; +} USB_ENDP_DESCR, *PUSB_ENDP_DESCR; + +typedef USB_ENDP_DESCR xdata *PXUSB_ENDP_DESCR; + +typedef struct _USB_CONFIG_DESCR_LONG { + USB_CFG_DESCR cfg_descr; + USB_ITF_DESCR itf_descr; + USB_ENDP_DESCR endp_descr[1]; +} USB_CFG_DESCR_LONG, *PUSB_CFG_DESCR_LONG; + +typedef USB_CFG_DESCR_LONG xdata *PXUSB_CFG_DESCR_LONG; + +typedef struct _USB_HUB_DESCR { + uint8_t bDescLength; + uint8_t bDescriptorType; + uint8_t bNbrPorts; + uint8_t wHubCharacteristicsL; + uint8_t wHubCharacteristicsH; + uint8_t bPwrOn2PwrGood; + uint8_t bHubContrCurrent; + uint8_t DeviceRemovable; + uint8_t PortPwrCtrlMask; +} USB_HUB_DESCR, *PUSB_HUB_DESCR; + +typedef USB_HUB_DESCR xdata *PXUSB_HUB_DESCR; + +typedef struct _USB_HID_DESCR { + uint8_t bLength; + uint8_t bDescriptorType; + uint8_t bcdHIDL; + uint8_t bcdHIDH; + uint8_t bCountryCode; + uint8_t bNumDescriptors; + uint8_t bDescriptorTypeX; + uint8_t wDescriptorLengthL; + uint8_t wDescriptorLengthH; +} USB_HID_DESCR, *PUSB_HID_DESCR; + +typedef USB_HID_DESCR xdata *PXUSB_HID_DESCR; + +typedef struct _UDISK_BOC_CBW { /* command of BulkOnly USB-FlashDisk */ + uint8_t mCBW_Sig0; + uint8_t mCBW_Sig1; + uint8_t mCBW_Sig2; + uint8_t mCBW_Sig3; + uint8_t mCBW_Tag0; + uint8_t mCBW_Tag1; + uint8_t mCBW_Tag2; + uint8_t mCBW_Tag3; + uint8_t mCBW_DataLen0; + uint8_t mCBW_DataLen1; + uint8_t mCBW_DataLen2; + uint8_t mCBW_DataLen3; /* uppest byte of data length, always is 0 */ + uint8_t mCBW_Flag; /* transfer direction and etc. */ + uint8_t mCBW_LUN; + uint8_t mCBW_CB_Len; /* length of command block */ + uint8_t mCBW_CB_Buf[16]; /* command block buffer */ +} UDISK_BOC_CBW, *PUDISK_BOC_CBW; + +typedef UDISK_BOC_CBW xdata *PXUDISK_BOC_CBW; + +typedef struct _UDISK_BOC_CSW { /* status of BulkOnly USB-FlashDisk */ + uint8_t mCSW_Sig0; + uint8_t mCSW_Sig1; + uint8_t mCSW_Sig2; + uint8_t mCSW_Sig3; + uint8_t mCSW_Tag0; + uint8_t mCSW_Tag1; + uint8_t mCSW_Tag2; + uint8_t mCSW_Tag3; + uint8_t mCSW_Residue0; /* return: remainder bytes */ + uint8_t mCSW_Residue1; + uint8_t mCSW_Residue2; + uint8_t mCSW_Residue3; /* uppest byte of remainder length, always is 0 */ + uint8_t mCSW_Status; /* return: result status */ +} UDISK_BOC_CSW, *PUDISK_BOC_CSW; + +typedef UDISK_BOC_CSW xdata *PXUDISK_BOC_CSW; + +#ifdef __cplusplus +} +#endif + +#endif // __USB_DEF__ diff --git a/src/template/src/main.c b/src/template/src/main.c new file mode 100644 index 0000000..a689280 --- /dev/null +++ b/src/template/src/main.c @@ -0,0 +1,11 @@ +#include "ch552.h" + +void main(void) { + + // Prepare the hardware here + init_clock(); + + while (1) { + // Do stuff here + } +} \ No newline at end of file diff --git a/tools/ch55xtool.py b/tools/ch55xtool.py index 94f98bb..2e976ca 100644 --- a/tools/ch55xtool.py +++ b/tools/ch55xtool.py @@ -1,3 +1,6 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- + import sys, os import time import array @@ -286,7 +289,7 @@ def __main(): if args.file != '': payload = list(open(args.file, 'rb').read()) - if ret[0] == 'V2.30': + if ret[0] in ['V2.30']: ret = __write_key_ch55x_v20(dev, chk_sum) if ret is None: sys.exit('Failed to write key to CH55x.') @@ -303,7 +306,7 @@ def __main(): if ret is None: sys.exit('Failed to verify firmware of CH55x.') else: - if ret[0] == 'V2.31': + if ret[0] in ['V2.31', 'V2.40']: ret = __write_key_ch55x_v23(dev) if ret is None: sys.exit('Failed to write key to CH55x.')