mirror of
https://github.com/tillitis/tillitis-key1.git
synced 2024-10-01 01:45:38 -04:00
Add (hardware) production tests for the TK-1 and TP-1 (#69)
* ch552 firmware: add ch55x support files directly * Add sdcc compiler to docker image, for building CH552 firmware * Rework production test script * Add menu-based test runner * Rewrite production test flows as lists of individual tests * Add both production flows and manual tests to menu * Switch to using included binaries * production test: Update message format * test_txrx_touchpad: Retry if device communications fail * production test: put all binaries in binaries/ folder * binaries/top.bin: replace broken binary * flash_check: Check for explicit flash IDs * Document most test procedures * Test plan documentation * Sample udev rules * Production test: allow external references to be overridden * Remove outdated descriptions * Correct shebang * Update shebangs to comply with PEP 394 Change the python scripts to call python instead of python3, as this works cross platform. See: https://peps.python.org/pep-0394/#for-python-script-publishers * Move production test to higher-level directory * Clarify production test setup * Move USB C connector test to separate directory Co-authored-by: Michael Cardell Widerkrantz <mc@tillitis.se>
This commit is contained in:
parent
f511a84ab4
commit
072b204d3d
7
contrib/99-tillitis.rules
Normal file
7
contrib/99-tillitis.rules
Normal file
@ -0,0 +1,7 @@
|
||||
# CH552 bootloader (for unprogrammed CH552 chips)
|
||||
SUBSYSTEM=="usb", ENV{DEVTYPE}=="usb_device", ATTR{idVendor}=="4348", ATTR{idProduct}=="55e0", MODE="0666", GROUP="dialout"
|
||||
|
||||
# TP-1 programmer
|
||||
SUBSYSTEMS=="hidraw", KERNEL=="hidraw*", MODE="0666", GROUP="dialout"
|
||||
ATTRS{idVendor}=="cafe", MODE="0660", GROUP="dialout"
|
||||
|
@ -38,6 +38,7 @@ RUN apt-get -qq update -y \
|
||||
verilator \
|
||||
vim \
|
||||
xdot \
|
||||
sdcc \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
|
||||
|
||||
|
@ -1,7 +1,7 @@
|
||||
TARGET = usb_device_cdc
|
||||
|
||||
CH554_SDCC=~/ch554_sdcc/
|
||||
CHPROG=~/chprog/chprog
|
||||
CHPROG=chprog
|
||||
|
||||
|
||||
# Adjust the XRAM location and size to leave space for the USB DMA buffers
|
||||
@ -21,7 +21,7 @@ usb_strings.h: encode_usb_strings.py
|
||||
|
||||
C_FILES = \
|
||||
main.c \
|
||||
${CH554_SDCC}/include/debug.c
|
||||
include/debug.c
|
||||
|
||||
pre-flash:
|
||||
|
||||
@ -31,4 +31,4 @@ flash_patched: usb_device_cdc.bin
|
||||
${CHPROG} patched.bin
|
||||
rm patched.bin
|
||||
|
||||
include ${CH554_SDCC}/examples/Makefile.include
|
||||
include Makefile.include
|
||||
|
68
hw/boards/mta1-usb-v1/ch552_fw/Makefile.include
Normal file
68
hw/boards/mta1-usb-v1/ch552_fw/Makefile.include
Normal file
@ -0,0 +1,68 @@
|
||||
#######################################################
|
||||
|
||||
# toolchain
|
||||
CC = sdcc
|
||||
OBJCOPY = objcopy
|
||||
PACK_HEX = packihx
|
||||
WCHISP ?= wchisptool -g -f
|
||||
|
||||
#######################################################
|
||||
|
||||
FREQ_SYS ?= 24000000
|
||||
|
||||
XRAM_SIZE ?= 0x0400
|
||||
|
||||
XRAM_LOC ?= 0x0000
|
||||
|
||||
CODE_SIZE ?= 0x3800
|
||||
|
||||
ROOT_DIR := $(dir $(abspath $(lastword $(MAKEFILE_LIST))))
|
||||
|
||||
CFLAGS := -V -mmcs51 --model-small \
|
||||
--xram-size $(XRAM_SIZE) --xram-loc $(XRAM_LOC) \
|
||||
--code-size $(CODE_SIZE) \
|
||||
-I$(ROOT_DIR)include -DFREQ_SYS=$(FREQ_SYS) \
|
||||
$(EXTRA_FLAGS)
|
||||
|
||||
LFLAGS := $(CFLAGS)
|
||||
|
||||
RELS := $(C_FILES:.c=.rel)
|
||||
|
||||
print-% : ; @echo $* = $($*)
|
||||
|
||||
%.rel : %.c
|
||||
$(CC) -c $(CFLAGS) $<
|
||||
|
||||
# Note: SDCC will dump all of the temporary files into this one, so strip the paths from RELS
|
||||
# For now, get around this by stripping the paths off of the RELS list.
|
||||
|
||||
$(TARGET).ihx: $(RELS)
|
||||
$(CC) $(notdir $(RELS)) $(LFLAGS) -o $(TARGET).ihx
|
||||
|
||||
$(TARGET).hex: $(TARGET).ihx
|
||||
$(PACK_HEX) $(TARGET).ihx > $(TARGET).hex
|
||||
|
||||
$(TARGET).bin: $(TARGET).ihx
|
||||
$(OBJCOPY) -I ihex -O binary $(TARGET).ihx $(TARGET).bin
|
||||
|
||||
flash: $(TARGET).bin pre-flash
|
||||
$(WCHISP) $(TARGET).bin
|
||||
|
||||
.DEFAULT_GOAL := all
|
||||
all: $(TARGET).bin $(TARGET).hex
|
||||
|
||||
clean:
|
||||
rm -f \
|
||||
$(notdir $(RELS:.rel=.asm)) \
|
||||
$(notdir $(RELS:.rel=.lst)) \
|
||||
$(notdir $(RELS:.rel=.mem)) \
|
||||
$(notdir $(RELS:.rel=.rel)) \
|
||||
$(notdir $(RELS:.rel=.rst)) \
|
||||
$(notdir $(RELS:.rel=.sym)) \
|
||||
$(notdir $(RELS:.rel=.adb)) \
|
||||
$(TARGET).lk \
|
||||
$(TARGET).map \
|
||||
$(TARGET).mem \
|
||||
$(TARGET).ihx \
|
||||
$(TARGET).hex \
|
||||
$(TARGET).bin
|
@ -6,17 +6,14 @@ SDCC:
|
||||
|
||||
sudo apt install build-essential sdcc
|
||||
|
||||
CH554 SDK:
|
||||
|
||||
cd ~
|
||||
git clone https://github.com/Blinkinlabs/ch554_sdcc.git
|
||||
|
||||
chprog (for flashing the firmware to a device):
|
||||
|
||||
cd ~
|
||||
sudo apt install libusb-1.0-0-dev
|
||||
git clone https://github.com/ole00/chprog.git
|
||||
cd chprog
|
||||
./build.linux.sh
|
||||
./build_linux.sh
|
||||
sudo cp chprog /usr/local/bin
|
||||
|
||||
## Usage
|
||||
|
||||
|
752
hw/boards/mta1-usb-v1/ch552_fw/include/ch554.h
Normal file
752
hw/boards/mta1-usb-v1/ch552_fw/include/ch554.h
Normal file
@ -0,0 +1,752 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
CH554.H
|
||||
Header file for CH554 microcontrollers.
|
||||
****************************************
|
||||
** Copyright (C) W.ch 1999-2014 **
|
||||
** Web: http://wch.cn **
|
||||
****************************************
|
||||
--------------------------------------------------------------------------*/
|
||||
|
||||
#ifndef __CH554_H__
|
||||
#define __CH554_H__
|
||||
|
||||
#include <compiler.h>
|
||||
|
||||
/*----- 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/Host/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 UHOST_CTRL = 0xD1; // USB host physical port control
|
||||
#define UHOST_CTRL UDEV_CTRL
|
||||
#define bUH_PD_DIS 0x80 // disable USB UDP/UDM pulldown resistance: 0=enable pulldown, 1=disable
|
||||
#define bUH_DP_PIN 0x20 // ReadOnly: indicate current UDP pin level
|
||||
#define bUH_DM_PIN 0x10 // ReadOnly: indicate current UDM pin level
|
||||
#define bUH_LOW_SPEED 0x04 // enable USB port low speed: 0=full speed, 1=low speed
|
||||
#define bUH_BUS_RESET 0x02 // control USB bus reset: 0=normal, 1=force bus reset
|
||||
#define bUH_PORT_EN 0x01 // enable USB port: 0=disable, 1=enable port, automatic disabled if USB device detached
|
||||
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_HST_SOF, 0xD8, 3); // host SOF timer interrupt flag for USB host, 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_DETECT, 0xD8, 0); // device detected event interrupt flag for USB host mode, direct bit address clear or write 1 to clear
|
||||
SBIT(UIF_BUS_RST, 0xD8, 0); // bus reset event interrupt flag for USB device mode, 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 for USB device mode
|
||||
#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 for USB device mode
|
||||
#define bUIS_TOKEN0 0x10 // ReadOnly: current token PID code bit 0 received for USB device mode
|
||||
#define MASK_UIS_TOKEN 0x30 // ReadOnly: bit mask of current token PID code received for USB device mode
|
||||
#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 for USB device mode
|
||||
// 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 for USB device mode
|
||||
#define MASK_UIS_H_RES 0x0F // ReadOnly: bit mask of current transfer handshake response for USB host mode: 0000=no response, time out from device, others=handshake response PID received
|
||||
SFR(USB_MIS_ST, 0xDA); // ReadOnly: USB miscellaneous status
|
||||
#define bUMS_SOF_PRES 0x80 // ReadOnly: indicate host SOF timer presage status
|
||||
#define bUMS_SOF_ACT 0x40 // ReadOnly: indicate host SOF timer action status for USB host
|
||||
#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
|
||||
#define bUMS_DM_LEVEL 0x02 // ReadOnly: indicate UDM level saved at device attached to USB host
|
||||
#define bUMS_DEV_ATTACH 0x01 // ReadOnly: indicate device attached status on USB host
|
||||
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 for USB device mode
|
||||
#define bUIE_DEV_NAK 0x40 // enable interrupt for NAK responded for USB device mode
|
||||
#define bUIE_FIFO_OV 0x10 // enable interrupt for FIFO overflow
|
||||
#define bUIE_HST_SOF 0x08 // enable interrupt for host SOF timer action for USB host mode
|
||||
#define bUIE_SUSPEND 0x04 // enable interrupt for USB suspend or resume event
|
||||
#define bUIE_TRANSFER 0x02 // enable interrupt for USB transfer completion
|
||||
#define bUIE_DETECT 0x01 // enable interrupt for USB device detected event for USB host mode
|
||||
#define bUIE_BUS_RST 0x01 // enable interrupt for USB bus reset event for USB device mode
|
||||
SFR(USB_CTRL, 0xE2); // USB base control
|
||||
#define bUC_HOST_MODE 0x80 // enable USB host mode: 0=device mode, 1=host mode
|
||||
#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_HOST_MODE & bUC_SYS_CTRL1 & bUC_SYS_CTRL0: USB system control
|
||||
// 0 00: disable USB device and disable internal pullup resistance
|
||||
// 0 01: enable USB device and disable internal pullup resistance, need external pullup resistance
|
||||
// 0 1x: enable USB device and enable internal pullup resistance
|
||||
// 1 00: enable USB host and normal status
|
||||
// 1 01: enable USB host and force UDP/UDM output SE0 state
|
||||
// 1 10: enable USB host and force UDP/UDM output J state
|
||||
// 1 11: enable USB host and force UDP/UDM output resume or K state
|
||||
#define bUC_INT_BUSY 0x08 // enable automatic responding busy for device mode or automatic pause for host mode 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
|
||||
//sfr UH_SETUP = 0xD2; // host aux setup
|
||||
#define UH_SETUP UEP1_CTRL
|
||||
#define bUH_PRE_PID_EN 0x80 // USB host PRE PID enable for low speed device via hub
|
||||
#define bUH_SOF_EN 0x40 // USB host automatic SOF enable
|
||||
//sfr UH_RX_CTRL = 0xD4; // host receiver endpoint control
|
||||
#define UH_RX_CTRL UEP2_CTRL
|
||||
#define bUH_R_TOG 0x80 // expected data toggle flag of host receiving (IN): 0=DATA0, 1=DATA1
|
||||
#define bUH_R_AUTO_TOG 0x10 // enable automatic toggle after successful transfer completion: 0=manual toggle, 1=automatic toggle
|
||||
#define bUH_R_RES 0x04 // prepared handshake response type for host receiving (IN): 0=ACK (ready), 1=no response, time out to device, for isochronous transactions
|
||||
//sfr UH_EP_PID = 0xD5; // host endpoint and token PID, lower 4 bits for endpoint number, upper 4 bits for token PID
|
||||
#define UH_EP_PID UEP2_T_LEN
|
||||
#define MASK_UH_TOKEN 0xF0 // bit mask of token PID for USB host transfer
|
||||
#define MASK_UH_ENDP 0x0F // bit mask of endpoint number for USB host transfer
|
||||
//sfr UH_TX_CTRL = 0xD6; // host transmittal endpoint control
|
||||
#define UH_TX_CTRL UEP3_CTRL
|
||||
#define bUH_T_TOG 0x40 // prepared data toggle flag of host transmittal (SETUP/OUT): 0=DATA0, 1=DATA1
|
||||
#define bUH_T_AUTO_TOG 0x10 // enable automatic toggle after successful transfer completion: 0=manual toggle, 1=automatic toggle
|
||||
#define bUH_T_RES 0x01 // expected handshake response type for host transmittal (SETUP/OUT): 0=ACK (ready), 1=no response, time out from device, for isochronous transactions
|
||||
//sfr UH_TX_LEN = 0xD7; // host transmittal endpoint transmittal length
|
||||
#define UH_TX_LEN UEP3_T_LEN
|
||||
//sfr UH_EP_MOD = 0xEB; // host endpoint mode
|
||||
#define UH_EP_MOD UEP2_3_MOD
|
||||
#define bUH_EP_TX_EN 0x40 // enable USB host OUT endpoint transmittal
|
||||
#define bUH_EP_TBUF_MOD 0x10 // buffer mode of USB host OUT endpoint
|
||||
// bUH_EP_TX_EN & bUH_EP_TBUF_MOD: USB host OUT endpoint buffer mode, buffer start address is UH_TX_DMA
|
||||
// 0 x: disable endpoint and disable buffer
|
||||
// 1 0: 64 bytes buffer for transmittal (OUT endpoint)
|
||||
// 1 1: dual 64 bytes buffer by toggle bit bUH_T_TOG selection for transmittal (OUT endpoint), total=128bytes
|
||||
#define bUH_EP_RX_EN 0x08 // enable USB host IN endpoint receiving
|
||||
#define bUH_EP_RBUF_MOD 0x01 // buffer mode of USB host IN endpoint
|
||||
// bUH_EP_RX_EN & bUH_EP_RBUF_MOD: USB host IN endpoint buffer mode, buffer start address is UH_RX_DMA
|
||||
// 0 x: disable endpoint and disable buffer
|
||||
// 1 0: 64 bytes buffer for receiving (IN endpoint)
|
||||
// 1 1: dual 64 bytes buffer by toggle bit bUH_R_TOG selection for receiving (IN endpoint), total=128bytes
|
||||
//sfr16 UH_RX_DMA = 0xE4; // host rx endpoint buffer start address, little-endian
|
||||
#define UH_RX_DMA UEP2_DMA
|
||||
//sfr UH_RX_DMA_L = 0xE4; // host rx endpoint buffer start address low byte
|
||||
#define UH_RX_DMA_L UEP2_DMA_L
|
||||
//sfr UH_RX_DMA_H = 0xE5; // host rx endpoint buffer start address high byte
|
||||
#define UH_RX_DMA_H UEP2_DMA_H
|
||||
//sfr16 UH_TX_DMA = 0xE6; // host tx endpoint buffer start address, little-endian
|
||||
#define UH_TX_DMA UEP3_DMA
|
||||
//sfr UH_TX_DMA_L = 0xE6; // host tx endpoint buffer start address low byte
|
||||
#define UH_TX_DMA_L UEP3_DMA_L
|
||||
//sfr UH_TX_DMA_H = 0xE7; // host tx endpoint buffer start address high byte
|
||||
#define UH_TX_DMA_H UEP3_DMA_H
|
||||
|
||||
/*----- XDATA: xRAM ------------------------------------------*/
|
||||
|
||||
#define XDATA_RAM_SIZE 0x0400 // size of expanded xRAM, xdata SRAM embedded chip
|
||||
|
||||
/*----- Reference Information --------------------------------------------*/
|
||||
#define ID_CH554 0x54 // 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 0xA5 ;MOVX @DPTR1,A & INC DPTR1
|
||||
DJNZ R7,LOOP
|
||||
*/
|
||||
|
||||
#endif // __CH554_H__
|
337
hw/boards/mta1-usb-v1/ch552_fw/include/ch554_usb.h
Normal file
337
hw/boards/mta1-usb-v1/ch552_fw/include/ch554_usb.h
Normal file
@ -0,0 +1,337 @@
|
||||
/*--------------------------------------------------------------------------
|
||||
CH554.H
|
||||
Header file for CH554 microcontrollers.
|
||||
****************************************
|
||||
** Copyright (C) W.ch 1999-2014 **
|
||||
** Web: http://wch.cn **
|
||||
****************************************
|
||||
--------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
#ifndef __USB_DEF__
|
||||
#define __USB_DEF__
|
||||
|
||||
/*----- 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 /* 默认的USB设备地址 */
|
||||
#endif
|
||||
#ifndef DEFAULT_ENDP0_SIZE
|
||||
#define DEFAULT_ENDP0_SIZE 8 /* default maximum packet size for endpoint 0 */
|
||||
#endif
|
||||
#ifndef DEFAULT_ENDP1_SIZE
|
||||
#define DEFAULT_ENDP1_SIZE 8 /* default maximum packet size for endpoint 1 */
|
||||
#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 /* 命令块CBW的总长度 */
|
||||
#define USB_BO_CSW_SIZE 0x0D /* 命令状态块CSW的总长度 */
|
||||
#endif
|
||||
#ifndef USB_BO_CBW_SIG0
|
||||
#define USB_BO_CBW_SIG0 0x55 /* 命令块CBW识别标志'USBC' */
|
||||
#define USB_BO_CBW_SIG1 0x53
|
||||
#define USB_BO_CBW_SIG2 0x42
|
||||
#define USB_BO_CBW_SIG3 0x43
|
||||
#define USB_BO_CSW_SIG0 0x55 /* 命令状态块CSW识别标志'USBS' */
|
||||
#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;
|
||||
|
||||
#endif // __USB_DEF__
|
162
hw/boards/mta1-usb-v1/ch552_fw/include/debug.c
Normal file
162
hw/boards/mta1-usb-v1/ch552_fw/include/debug.c
Normal file
@ -0,0 +1,162 @@
|
||||
/********************************** (C) COPYRIGHT *******************************
|
||||
* File Name : Debug.C
|
||||
* Author : WCH
|
||||
* Version : V1.0
|
||||
* Date : 2017/01/20
|
||||
* Description : CH554 DEBUG Interface
|
||||
CH554 main frequency modification, delay function definition
|
||||
Serial port 0 and serial port 1 initialization
|
||||
Serial port 0 and serial port 1 transceiver subfunctions
|
||||
Watchdog initialization
|
||||
*******************************************************************************/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "ch554.h"
|
||||
#include "debug.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : CfgFsys( )
|
||||
* Description : CH554 clock selection and configuration function, Fsys 6MHz is used by default, FREQ_SYS can be passed
|
||||
CLOCK_CFG configuration, the formula is as follows:
|
||||
Fsys = (Fosc * 4 / (CLOCK_CFG & MASK_SYS_CK_SEL); the specific clock needs to be configured by yourself
|
||||
*******************************************************************************/
|
||||
void CfgFsys( )
|
||||
{
|
||||
SAFE_MOD = 0x55;
|
||||
SAFE_MOD = 0xAA;
|
||||
// CLOCK_CFG |= bOSC_EN_XT; // Enable external crystal
|
||||
// CLOCK_CFG & = ~ bOSC_EN_INT; // Turn off the internal crystal
|
||||
|
||||
#if FREQ_SYS == 32000000
|
||||
CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x07; // 32MHz
|
||||
#elif FREQ_SYS == 24000000
|
||||
CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x06; // 24MHz
|
||||
#elif FREQ_SYS == 16000000
|
||||
CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x05; // 16MHz
|
||||
#elif FREQ_SYS == 12000000
|
||||
CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x04; // 12MHz
|
||||
#elif FREQ_SYS == 6000000
|
||||
CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x03; // 6MHz
|
||||
#elif FREQ_SYS == 3000000
|
||||
CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x02; // 3MHz
|
||||
#elif FREQ_SYS == 750000
|
||||
CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x01; // 750KHz
|
||||
#elif FREQ_SYS == 187500
|
||||
CLOCK_CFG = CLOCK_CFG & ~ MASK_SYS_CK_SEL | 0x00; // 187.5MHz
|
||||
#else
|
||||
#warning FREQ_SYS invalid or not set
|
||||
#endif
|
||||
|
||||
SAFE_MOD = 0x00;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : mDelayus(UNIT16 n)
|
||||
* Description : us delay function
|
||||
* Input : UNIT16 n
|
||||
* Output : None
|
||||
* Return : None
|
||||
*******************************************************************************/
|
||||
void mDelayuS( uint16_t n ) // Delay in uS
|
||||
{
|
||||
#ifdef FREQ_SYS
|
||||
#if FREQ_SYS <= 6000000
|
||||
n >>= 2;
|
||||
#endif
|
||||
#if FREQ_SYS <= 3000000
|
||||
n >>= 2;
|
||||
#endif
|
||||
#if FREQ_SYS <= 750000
|
||||
n >>= 4;
|
||||
#endif
|
||||
#endif
|
||||
while ( n ) { // total = 12~13 Fsys cycles, 1uS @Fsys=12MHz
|
||||
++ SAFE_MOD; // 2 Fsys cycles, for higher Fsys, add operation here
|
||||
#ifdef FREQ_SYS
|
||||
#if FREQ_SYS >= 14000000
|
||||
++ SAFE_MOD;
|
||||
#endif
|
||||
#if FREQ_SYS >= 16000000
|
||||
++ SAFE_MOD;
|
||||
#endif
|
||||
#if FREQ_SYS >= 18000000
|
||||
++ SAFE_MOD;
|
||||
#endif
|
||||
#if FREQ_SYS >= 20000000
|
||||
++ SAFE_MOD;
|
||||
#endif
|
||||
#if FREQ_SYS >= 22000000
|
||||
++ SAFE_MOD;
|
||||
#endif
|
||||
#if FREQ_SYS >= 24000000
|
||||
++ SAFE_MOD;
|
||||
#endif
|
||||
#if FREQ_SYS >= 26000000
|
||||
++ SAFE_MOD;
|
||||
#endif
|
||||
#if FREQ_SYS >= 28000000
|
||||
++ SAFE_MOD;
|
||||
#endif
|
||||
#if FREQ_SYS >= 30000000
|
||||
++ SAFE_MOD;
|
||||
#endif
|
||||
#if FREQ_SYS >= 32000000
|
||||
++ SAFE_MOD;
|
||||
#endif
|
||||
#endif
|
||||
-- n;
|
||||
}
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : mDelayms(UNIT16 n)
|
||||
* Description : ms delay function
|
||||
* Input : UNIT16 n
|
||||
* Output : None
|
||||
* Return : None
|
||||
*******************************************************************************/
|
||||
void mDelaymS( uint16_t n ) // Delay in mS
|
||||
{
|
||||
while ( n ) {
|
||||
#ifdef DELAY_MS_HW
|
||||
while ( ( TKEY_CTRL & bTKC_IF ) == 0 );
|
||||
while ( TKEY_CTRL & bTKC_IF );
|
||||
#else
|
||||
mDelayuS( 1000 );
|
||||
#endif
|
||||
-- n;
|
||||
}
|
||||
}
|
||||
|
||||
#if SDCC < 370
|
||||
void putchar(char c)
|
||||
{
|
||||
while (!TI); /* assumes UART is initialized */
|
||||
TI = 0;
|
||||
SBUF = c;
|
||||
}
|
||||
|
||||
char getchar() {
|
||||
while(!RI); /* assumes UART is initialized */
|
||||
RI = 0;
|
||||
return SBUF;
|
||||
}
|
||||
#else
|
||||
int putchar(int c)
|
||||
{
|
||||
while (!TI); /* assumes UART is initialized */
|
||||
TI = 0;
|
||||
SBUF = c & 0xFF;
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
int getchar() {
|
||||
while(!RI); /* assumes UART is initialized */
|
||||
RI = 0;
|
||||
return SBUF;
|
||||
}
|
||||
#endif
|
179
hw/boards/mta1-usb-v1/ch552_fw/include/debug.h
Normal file
179
hw/boards/mta1-usb-v1/ch552_fw/include/debug.h
Normal file
@ -0,0 +1,179 @@
|
||||
|
||||
/* Debug */
|
||||
/* Provide printf subroutine and delay function */
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef UART0_BAUD
|
||||
#define UART0_BAUD 9600
|
||||
#endif
|
||||
|
||||
#ifndef UART1_BAUD
|
||||
#define UART1_BAUD 9600
|
||||
#endif
|
||||
|
||||
void CfgFsys( ); // CH554 clock selection and configuration
|
||||
|
||||
void mDelayuS (uint16_t n); // Delay in units of uS
|
||||
void mDelaymS (uint16_t n); // Delay in mS
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : CH554UART0Alter()
|
||||
* Description : CH554 serial port 0 pin mapping, serial port mapping to P0.2 and P0.3
|
||||
|
||||
*******************************************************************************/
|
||||
inline void CH554UART0Alter()
|
||||
{
|
||||
PIN_FUNC |= bUART0_PIN_X; //串口映射到P1.2和P1.3
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : mInitSTDIO()
|
||||
* Description : CH554 serial port 0 is initialized, T1 is used as the baud rate generator of UART0 by default, T2 can also be used
|
||||
As a baud rate generator
|
||||
*******************************************************************************/
|
||||
inline void mInitSTDIO( )
|
||||
{
|
||||
uint32_t x;
|
||||
uint8_t x2;
|
||||
|
||||
SM0 = 0;
|
||||
SM1 = 1;
|
||||
SM2 = 0; //Serial port 0 usage mode 1
|
||||
//Use Timer1 as a baud rate generator
|
||||
RCLK = 0; //UART0 receive clock
|
||||
TCLK = 0; //UART0 transmit clock
|
||||
PCON |= SMOD;
|
||||
x = 10 * FREQ_SYS / UART0_BAUD / 16; //If you change the main frequency, be careful not to overflow the value of x
|
||||
x2 = x % 10;
|
||||
x /= 10;
|
||||
if ( x2 >= 5 ) x ++; //rounding
|
||||
|
||||
TMOD = TMOD & ~ bT1_GATE & ~ bT1_CT & ~ MASK_T1_MOD | bT1_M1; //0X20, Timer1 as 8-bit auto-reload timer
|
||||
T2MOD = T2MOD | bTMR_CLK | bT1_CLK; //Timer1 clock selection
|
||||
TH1 = 0-x; //12MHz crystal oscillator, buad / 12 is the actual need to set the baud rate
|
||||
TR1 = 1; //Start timer 1
|
||||
TI = 1;
|
||||
REN = 1; //Serial 0 receive enable
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : CH554UART0RcvByte()
|
||||
* Description : CH554UART0 receives a byte
|
||||
* Return : SBUF
|
||||
*******************************************************************************/
|
||||
inline uint8_t CH554UART0RcvByte( )
|
||||
{
|
||||
while(RI == 0); // wait for uart rx interrupt flag
|
||||
RI = 0;
|
||||
return SBUF;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : CH554UART0SendByte(uint8_t SendDat)
|
||||
* Description : CH554UART0 sends a byte
|
||||
* Input : uint8_t SendDat; the data to be sent
|
||||
*******************************************************************************/
|
||||
inline void CH554UART0SendByte(uint8_t SendDat)
|
||||
{
|
||||
|
||||
SBUF = SendDat;
|
||||
while(TI ==0); // wait for transmit to finish (TI == 1)
|
||||
TI = 0;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : CH554UART1Alter()
|
||||
* Description : Set the alternate pin mappings for UART1 (TX on P3.2, RX on P3.4)
|
||||
*******************************************************************************/
|
||||
inline void CH554UART1Alter()
|
||||
{
|
||||
PIN_FUNC |= bUART1_PIN_X;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : UART1Setup()
|
||||
* Description : CH554串口1初始化
|
||||
*******************************************************************************/
|
||||
inline void UART1Setup()
|
||||
{
|
||||
U1SM0 = 0; //UART1选择8位数据位
|
||||
U1SMOD = 1; //快速模式
|
||||
U1REN = 1; //使能接收
|
||||
// should correct for rounding in SBAUD1 calculation
|
||||
SBAUD1 = 256 - FREQ_SYS/16/UART1_BAUD;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : CH554UART1RcvByte()
|
||||
* Description : CH554UART1接收一个字节
|
||||
* Return : SBUF
|
||||
*******************************************************************************/
|
||||
inline uint8_t CH554UART1RcvByte( )
|
||||
{
|
||||
while(U1RI == 0); //查询接收,中断方式可不用
|
||||
U1RI = 0;
|
||||
return SBUF1;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : CH554UART1SendByte(uint8_t SendDat)
|
||||
* Description : CH554UART1发送一个字节
|
||||
* Input : uint8_t SendDat;要发送的数据
|
||||
*******************************************************************************/
|
||||
inline void CH554UART1SendByte(uint8_t SendDat)
|
||||
{
|
||||
SBUF1 = SendDat; //查询发送,中断方式可不用下面2条语句,但发送前需TI=0
|
||||
while(U1TI ==0);
|
||||
U1TI = 0;
|
||||
}
|
||||
|
||||
#if SDCC < 370
|
||||
void putchar(char c);
|
||||
char getchar();
|
||||
#else
|
||||
int putchar(int c);
|
||||
int getchar(void);
|
||||
#endif
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : CH554WDTModeSelect(uint8_t mode)
|
||||
* Description : CH554 watchdog mode selection
|
||||
* Input : uint8_t mode
|
||||
0 timer
|
||||
1 watchDog
|
||||
* Output : None
|
||||
* Return : None
|
||||
*******************************************************************************/
|
||||
inline void CH554WDTModeSelect(uint8_t mode)
|
||||
{
|
||||
SAFE_MOD = 0x55;
|
||||
SAFE_MOD = 0xaa; //Enter Safe Mode
|
||||
if(mode){
|
||||
GLOBAL_CFG |= bWDOG_EN; //Start watchdog reset
|
||||
}
|
||||
|
||||
else GLOBAL_CFG &= ~bWDOG_EN; //Start watchdog only as a timer
|
||||
SAFE_MOD = 0x00; //exit safe Mode
|
||||
WDOG_COUNT = 0; //Watchdog assignment initial value
|
||||
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Function Name : CH554WDTFeed(uint8_t tim)
|
||||
* Description : CH554 watchdog timer time setting
|
||||
* Input : uint8_t tim watchdog reset time setting
|
||||
|
||||
00H(6MHz)=2.8s
|
||||
80H(6MHz)=1.4s
|
||||
* Output : None
|
||||
* Return : None
|
||||
*******************************************************************************/
|
||||
inline void CH554WDTFeed(uint8_t tim)
|
||||
{
|
||||
|
||||
WDOG_COUNT = tim; // Watchdog counter assignment
|
||||
|
||||
}
|
@ -1,42 +0,0 @@
|
||||
# MTA1-USB-CH552 hardware test
|
||||
|
||||
This is a hardware bringup test for the MTA1-USB-CH552 board.
|
||||
|
||||
## Usage
|
||||
|
||||
The flash chip for the application FPGA must be programmed with the included firmware
|
||||
|
||||
## Voltage rails
|
||||
|
||||
The MTA1-USB board has three voltage supplies- 1.2V, 3.3V, and 2.5V. These are measured by hand using a sufficiently accurate DMM. Additionally, the power supplies must come up in a specific sequence (see the notes on schematic page 4). This can be verified using an oscilloscope.
|
||||
|
||||
## CH552 to App FPGA connections
|
||||
|
||||
This includes the signals TX, RX, RTS, and CTS. On the FPGA, these signals are routed as loopback connections. They can be tested using a script on a PC (TODO)
|
||||
|
||||
## Application FPGA programming connections
|
||||
|
||||
This inclues '_ICE_MISO, _ICE_MOSI, _ICE_SCK, _ICE_SS, _CRESET, _CDONE'. These nets are tested by using the FTDI chip to program the SPI flash. If the FPGA boots, then it is assumed that all of the connections on these nets are connected correctly.
|
||||
|
||||
## GPIO connections
|
||||
|
||||
The application FPGA has '_GPIO1, _GPIO2, _GPIO3, _GPIO4' expansion connections. These are tested by outputting different frequency clocks to them, which are manually verified using a logic analyzer or oscilloscope.
|
||||
|
||||
| GPIO | Expected clock frequency |
|
||||
| --- | --- |
|
||||
| 1 | 24 MHz |
|
||||
| 2 | 12 MHz |
|
||||
| 3 | 6 MHz |
|
||||
| 4 | 3 MHz |
|
||||
|
||||
## RGB LEDs
|
||||
|
||||
The application FPGAs has an RGB status LED. This is verified by feeding different clock signals into each color channel, so that the LEDs will cycle through the color sequence Red,Green,Blue,White.
|
||||
|
||||
## CH552 USB interface
|
||||
|
||||
The USB connection on the CH552 is verified by loading the USB-to-serial converter firmware onto it.
|
||||
|
||||
## Application FPGA touch sensor
|
||||
|
||||
The touch sensor is used to gate the output of the application FPGA LED. The touch sensor is considered connected if it turns off the application FPGA LED when it is touched.
|
@ -1,375 +0,0 @@
|
||||
#!/usr/bin/env python3
|
||||
import hid_test
|
||||
import time
|
||||
import numpy
|
||||
from subprocess import run
|
||||
import usb.core
|
||||
import uuid
|
||||
import encode_usb_strings
|
||||
import serial
|
||||
import serial.tools.list_ports;
|
||||
import shutil
|
||||
|
||||
# Locations for external utilities and files referenced by the test program
|
||||
file_locations = {
|
||||
'iceprog':'/home/matt/Other-Repos/icestorm/iceprog/iceprog',
|
||||
'chprog':'/home/matt/Other-Repos/chprog/chprog',
|
||||
'app_gateware':'/home/matt/Other-Repos/mta1_mkdf/hw/boards/mta1-usb-v1/test/app_test/top.bin',
|
||||
'ch552_firmware':'/home/matt/Other-Repos/mta1_mkdf/hw/boards/mta1-usb-v1/ch552_fw/usb_device_cdc.bin',
|
||||
'ch552_firmware_injected':'/tmp/ch552_fw_injected.bin',
|
||||
'pico_bootloader_source':'/home/matt/Blinkinlabs-Repos/ice40_flasher/bin/main.uf2',
|
||||
'pico_bootloader_target':'/media/matt/RPI-RP2/main.uf2'
|
||||
}
|
||||
|
||||
def measure_voltages(device, samples):
|
||||
""" Measure the voltage levels of the three mta1 power rails multiple times, and return the average values """
|
||||
adc_vals = numpy.array([0,0,0])
|
||||
for i in range(0,samples):
|
||||
adc_vals = adc_vals + device.adc_read_all()
|
||||
adc_vals = dict(zip(['1.2','2.5','3.3'],adc_vals/samples))
|
||||
return adc_vals
|
||||
|
||||
def voltage_test():
|
||||
"""Turn on the device, delay, measure voltage, then turn it off"""
|
||||
d = hid_test.ice40_flasher()
|
||||
|
||||
d.gpio_set_direction(7, True)
|
||||
d.gpio_put(7, True)
|
||||
time.sleep(.2)
|
||||
|
||||
vals = measure_voltages(d,20)
|
||||
|
||||
d.gpio_put(7, False)
|
||||
d.close()
|
||||
|
||||
print('voltages:',vals)
|
||||
if (
|
||||
(abs(vals['1.2'] - 1.2) > .2)
|
||||
| (abs(vals['2.5'] - 2.5) > .2)
|
||||
| (abs(vals['3.3'] - 3.3) > .2)
|
||||
):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def flash_validate_id():
|
||||
""" Read the ID from the flash, and verify that it's not all 0's or 1's (which would indicate a communications issue) """
|
||||
result = run([
|
||||
file_locations['iceprog'],
|
||||
'-t'
|
||||
],
|
||||
capture_output=True)
|
||||
|
||||
err = result.stderr.split(b'\n')
|
||||
for line in err:
|
||||
if line.startswith(b'flash ID:'):
|
||||
vals_b = line.split(b' 0x')[1:]
|
||||
flash_id = int(b''.join(vals_b),16)
|
||||
print(line, hex(flash_id))
|
||||
if (flash_id == 0) or (flash_id == 0xFFFFFFFF):
|
||||
return False
|
||||
return True
|
||||
|
||||
return (result.returncode == 0)
|
||||
|
||||
def flash_program():
|
||||
""" Program and verify the SPI flash """
|
||||
result = run([
|
||||
file_locations['iceprog'],
|
||||
file_locations['app_gateware']
|
||||
])
|
||||
print(result)
|
||||
|
||||
return (result.returncode == 0)
|
||||
|
||||
def flash_check():
|
||||
""" Verify the contents of the SPI flash """
|
||||
result = run([
|
||||
file_locations['iceprog'],
|
||||
'-c',
|
||||
file_locations['app_gateware']
|
||||
])
|
||||
print(result)
|
||||
|
||||
return (result.returncode == 0)
|
||||
|
||||
def test_extra_io():
|
||||
""" Test the RTS, CTS, and GPIO1-4 lines by measuring a test pattern generated by the app_test gateware when RTS is toggled """
|
||||
time.sleep(.1)
|
||||
d = hid_test.ice40_flasher()
|
||||
|
||||
d.gpio_put(16, False)
|
||||
d.gpio_set_direction(16, True)
|
||||
|
||||
expected_results = [1<<(i%5) for i in range(9,-1,-1)]
|
||||
|
||||
results = []
|
||||
for i in range(0,10):
|
||||
vals = d.gpio_get_all()
|
||||
pattern = (vals >> 17) & 0b11111
|
||||
results.append(pattern)
|
||||
|
||||
d.gpio_put(16, True)
|
||||
d.gpio_put(16, False)
|
||||
|
||||
d.gpio_set_direction(16, False)
|
||||
d.close()
|
||||
|
||||
print(results,expected_results,results == expected_results)
|
||||
return results == expected_results
|
||||
|
||||
def disable_power():
|
||||
""" Disable power to the mta1-usb device """
|
||||
time.sleep(.1)
|
||||
d = hid_test.ice40_flasher()
|
||||
d.gpio_put(7, False)
|
||||
d.close()
|
||||
|
||||
def test_found_bootloader():
|
||||
""" Search for a CH552 in USB bootloader mode """
|
||||
print('\n\n\nSearching for CH552 bootloader, plug in USB cable now!')
|
||||
for trys in range(0,50):
|
||||
devices= usb.core.find(idVendor=0x4348, idProduct=0x55e0, find_all=True)
|
||||
count = len(list(devices))
|
||||
|
||||
if count == 1:
|
||||
return True
|
||||
|
||||
time.sleep(0.1)
|
||||
|
||||
post = usb.core.find(idVendor=0x4348, idProduct=0x55e0, find_all=True)
|
||||
post_count = len(list(post))
|
||||
return (post_count == 1)
|
||||
|
||||
def inject_serial_number(infile, outfile, serial):
|
||||
""" Inject a serial number into the specified CH552 firmware file """
|
||||
magic = encode_usb_strings.string_to_descriptor("68de5d27-e223-4874-bc76-a54d6e84068f")
|
||||
replacement = encode_usb_strings.string_to_descriptor(serial)
|
||||
|
||||
f = bytearray(open(infile, 'rb').read())
|
||||
|
||||
pos = f.find(magic)
|
||||
|
||||
if pos < 0:
|
||||
print('failed to find magic string')
|
||||
exit(1)
|
||||
|
||||
f[pos:(pos+len(magic))] = replacement
|
||||
|
||||
with open(outfile, 'wb') as of:
|
||||
of.write(f)
|
||||
|
||||
def flash_ch552(serial):
|
||||
""" Flash an attached CH552 device (in bootloader mode) with the USB CDC firmware, injected with the given serial number """
|
||||
|
||||
print(serial)
|
||||
inject_serial_number(
|
||||
file_locations['ch552_firmware'],
|
||||
file_locations['ch552_firmware_injected'],
|
||||
serial)
|
||||
|
||||
# Program the CH552 using CHPROG
|
||||
result = run([
|
||||
file_locations['chprog'],
|
||||
file_locations['ch552_firmware_injected']
|
||||
])
|
||||
print(result)
|
||||
return (result.returncode == 0)
|
||||
|
||||
def find_serial_device(desc):
|
||||
""" Look for a serial device that has the given attributes """
|
||||
|
||||
for port in serial.tools.list_ports.comports():
|
||||
matched = True
|
||||
for key, value in desc.items():
|
||||
if not getattr(port, key) == value:
|
||||
matched = False
|
||||
|
||||
if matched:
|
||||
print(port.device)
|
||||
return port.device
|
||||
|
||||
return None
|
||||
|
||||
def test_found_ch552(serial):
|
||||
""" Search all serial devices for one that has the correct description and serial number """
|
||||
time.sleep(1)
|
||||
|
||||
description = {
|
||||
'vid':0x1207,
|
||||
'pid':0x8887,
|
||||
'manufacturer':'Tillitis',
|
||||
'product':'MTA1-USB-V1',
|
||||
'serial_number':serial
|
||||
}
|
||||
|
||||
if find_serial_device(description) == None:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def ch552_find_and_program():
|
||||
""" Load the CDC ACM firmware onto a CH552 with a randomly generated serial number, and verify that it boots correctly """
|
||||
if not test_found_bootloader():
|
||||
print('Error finding CH552!')
|
||||
return False
|
||||
|
||||
serial = str(uuid.uuid4())
|
||||
|
||||
if not flash_ch552(serial):
|
||||
print('Error flashing CH552!')
|
||||
return False
|
||||
|
||||
if not test_found_ch552(serial):
|
||||
print('Error finding flashed CH552!')
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
|
||||
def test_txrx_touchpad():
|
||||
""" Test UART communication by asking the operator to interact with the touch pad """
|
||||
description = {
|
||||
'vid':0x1207,
|
||||
'pid':0x8887,
|
||||
'manufacturer':'Tillitis',
|
||||
'product':'MTA1-USB-V1'
|
||||
}
|
||||
|
||||
s = serial.Serial(find_serial_device(description),9600, timeout=.2)
|
||||
|
||||
if not s.isOpen():
|
||||
print('couldn\'t find/open serial device')
|
||||
return False
|
||||
|
||||
|
||||
s.write(b'0123')
|
||||
time.sleep(0.1)
|
||||
s.read(20)
|
||||
|
||||
try:
|
||||
s.write(b'0')
|
||||
[count, touch_count] = s.read(2)
|
||||
print(count,touch_count)
|
||||
|
||||
input('\n\n\nPress touch pad once and check LED, then press Enter')
|
||||
s.write(b'0')
|
||||
[count_post, touch_count_post] = s.read(2)
|
||||
print(count_post,touch_count_post)
|
||||
|
||||
if (count_post - count != 1) or (touch_count_post - touch_count !=1):
|
||||
return False
|
||||
|
||||
return True
|
||||
except ValueError as e:
|
||||
print(e)
|
||||
return False
|
||||
|
||||
def production_test(args):
|
||||
""" mta1-usb-v1 production test. Specify --noflash to skip flashing the gateware to the SPI flash, and --noch552 to skip programming the USB CDC firmware to the CH552 """
|
||||
if not voltage_test():
|
||||
print('voltage out of range')
|
||||
return False
|
||||
|
||||
if not flash_validate_id():
|
||||
print('Error reading flash ID')
|
||||
return False
|
||||
|
||||
if not args.noflash:
|
||||
if not flash_program():
|
||||
print('Error programming flash')
|
||||
return False
|
||||
else:
|
||||
if not flash_check():
|
||||
print('Error checking flash')
|
||||
return False
|
||||
|
||||
if not test_extra_io():
|
||||
print('Error testing io')
|
||||
return False
|
||||
|
||||
if not args.noch552:
|
||||
disable_power()
|
||||
|
||||
if not ch552_find_and_program():
|
||||
return False
|
||||
|
||||
if not test_txrx_touchpad():
|
||||
print('Error reading touchpad!')
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def program_pico():
|
||||
""" Load the ice40 flasher firmware onto an rpi pico in bootloader mode """
|
||||
print('Attach test rig to USB')
|
||||
for trys in range(0,50):
|
||||
try:
|
||||
shutil.copyfile(
|
||||
file_locations['pico_bootloader_source'],
|
||||
file_locations['pico_bootloader_target']
|
||||
)
|
||||
return True
|
||||
except FileNotFoundError:
|
||||
time.sleep(0.1)
|
||||
except PermissionError:
|
||||
time.sleep(0.1)
|
||||
|
||||
return False
|
||||
|
||||
def programmer_production_test(args):
|
||||
""" mta1-usb-v1-programmer production test. Place a (programmed) mta1-usb-v1 into the programmer, connect the programmer to the PC, then start the test. """
|
||||
|
||||
if not program_pico():
|
||||
print('error programming the pico')
|
||||
return False
|
||||
|
||||
# Let the board start
|
||||
time.sleep(2)
|
||||
|
||||
if not voltage_test():
|
||||
print('voltage out of range')
|
||||
return False
|
||||
|
||||
if not flash_validate_id():
|
||||
print('Error reading flash ID')
|
||||
return False
|
||||
|
||||
if not flash_check():
|
||||
print('Error programming flash')
|
||||
return False
|
||||
|
||||
if not test_extra_io():
|
||||
print('Error testing io')
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
if __name__ == '__main__':
|
||||
import argparse
|
||||
parser = argparse.ArgumentParser(description='GPIO short connector test')
|
||||
parser.add_argument('--noch552', action='store_true', help='Skip programming the CH552. Used for re-testing an mta1-usb-v1 board.')
|
||||
parser.add_argument('--noflash', action='store_true', help='Skip programming the SPI flash. Used for re-testing an mta1-usb-v1 board')
|
||||
parser.add_argument('--programmer', action='store_true', help='Program/test the programmer')
|
||||
parser.add_argument('--ch552', action='store_true', help='Program/test (only) the CH552.')
|
||||
args = parser.parse_args()
|
||||
|
||||
while True:
|
||||
input('\n\n\nPress Enter to start')
|
||||
if args.programmer:
|
||||
result = programmer_production_test(args)
|
||||
elif args.ch552:
|
||||
result = ch552_find_and_program()
|
||||
else:
|
||||
result = production_test(args)
|
||||
|
||||
if result:
|
||||
print('\n\n\nDONE')
|
||||
else:
|
||||
print('\n\n\nFAIL')
|
||||
|
||||
try:
|
||||
disable_power()
|
||||
except AttributeError as e:
|
||||
print(e)
|
336
hw/production_test/README.md
Normal file
336
hw/production_test/README.md
Normal file
@ -0,0 +1,336 @@
|
||||
# TK-1 and TP-1 production tests
|
||||
|
||||
Production tests for the TK-1 and TP-1 PCBs
|
||||
|
||||
## Usage
|
||||
|
||||
These instructions are tested on Ubuntu 22.10.
|
||||
|
||||
Set up a python virtualenv to run the production test:
|
||||
|
||||
sudo apt install python3.10-venv
|
||||
python3 -m venv venv
|
||||
source venv/bin/activate
|
||||
pip install -r requirements.txt
|
||||
deactivate
|
||||
|
||||
To run the production test script:
|
||||
|
||||
source venv/bin/activate
|
||||
./production_test.py
|
||||
|
||||
The script will then print a menu with all available tests:
|
||||
|
||||
Tillitis TK-1 and TP-1 Production tests
|
||||
|
||||
|
||||
|
||||
=== Test sequences ===
|
||||
1. tk1_test_sequence: voltage_test, flash_validate_id, flash_program, sleep_2, test_extra_io, ch552_program, test_txrx_touchpad
|
||||
2. tp1_test_sequence: program_pico, sleep_2, flash_validate_id
|
||||
3. mta1_usb_v1_programmer_test_sequence: program_pico, sleep_2, voltage_test, flash_validate_id, sleep_2, test_extra_io
|
||||
|
||||
=== Manual tests ===
|
||||
4. program_pico: Load the ice40 flasher firmware onto the TP-1
|
||||
5. voltage_test: Measure 3.3V 2.5V, and 1.2V voltage rails on the TK-1
|
||||
6. flash_validate_id: Read the ID from TK-1 SPI flash, and verify that it matches the expected value
|
||||
7. flash_program: Program and verify the TK-1 SPI flash with the application test gateware
|
||||
8. flash_check: Verify the TK-1 SPI flash is programmed with the application test gateware
|
||||
9. test_extra_io: Test the TK-1 RTS, CTS, and GPIO1-4 lines by measuring a test pattern generated by the app_test gateware
|
||||
10. ch552_program: Load the CDC ACM firmware onto a CH552 with a randomly generated serial number, and verify that it boots correctly
|
||||
11. test_txrx_touchpad: Test UART communication, RGB LED, and touchpad by asking the operator to interact with the touch pad
|
||||
12. enable_power: Enable power to the TK-1
|
||||
13. disable_power: Disable power to the TK-1
|
||||
|
||||
|
||||
|
||||
Please type an option number and press return:
|
||||
|
||||
|
||||
There are two types of tests listed: test sequences, which are used
|
||||
to run full production tests, and manual tests, which are used to
|
||||
test a single subcircuit. It is recommended to test all boards using
|
||||
a test sequence first, and to use the manual tests for diagnosing
|
||||
issues with individual boards, or for re-testing repaired boards.
|
||||
|
||||
## Test Sequences
|
||||
|
||||
These sequences are used as production tests for the TK-1 and TP-1.
|
||||
|
||||
### TK-1 production test (tk1_test_sequence)
|
||||
|
||||
This test checks all major subcircuits on the TK-1, and is used to
|
||||
verify that the PCBA was assembled correctly. It should be run on all
|
||||
newly assembled TK-1 boards.
|
||||
|
||||
Requirements:
|
||||
|
||||
* Programmed MTA1_USB_V1_Programmer board, fitted with a wider (green)
|
||||
plastic clip
|
||||
* Unprogrammed TK-1
|
||||
* USB micro cable to attach TP-1 board to computer
|
||||
* USB C extension cable to attach TK-1 to computer
|
||||
|
||||
It runs the following tests, in order:
|
||||
|
||||
1. voltage_test
|
||||
2. flash_validate_id
|
||||
3. flash_program
|
||||
4. sleep_2
|
||||
5. test_extra_io
|
||||
6. ch552_program
|
||||
7. test_txrx_touchpad
|
||||
|
||||
Note: If the CH552 has been programmed already, then the test
|
||||
sequence will fail. In that case, manually run the other tests
|
||||
in the sequence, skipping the 'ch554_program' test.
|
||||
|
||||
### TP-1 (tp1_test_sequence)
|
||||
|
||||
This test programs a TP-1, then tests that it can program a TK-1.
|
||||
It should be run on all newly assembled TP-1 boards.
|
||||
|
||||
|
||||
Requirements:
|
||||
|
||||
* Unprogrammed TP-1
|
||||
* TK-1 programmed with the application test gateware
|
||||
* USB micro cable to attach TP-1 board to computer
|
||||
|
||||
The TP-1 production test runs the following tests, in order:
|
||||
|
||||
1. program_pico
|
||||
2. sleep_2
|
||||
3. flash_validate_id
|
||||
|
||||
### MTA1_USB_V1_Programmer (mta1_usb_v1_programmer_test_sequence)
|
||||
|
||||
Requirements:
|
||||
|
||||
* Unprogrammed MTA1_USB_V1_Programmer
|
||||
* TK-1 programmed with the application test gateware
|
||||
* USB micro cable to attach MTA1_USB_V1_Programmer board to computer
|
||||
|
||||
The TP-1 production test runs the following tests, in order:
|
||||
|
||||
1. program_pico
|
||||
2. sleep_2
|
||||
3. voltage_test
|
||||
4. flash_validate_id
|
||||
5. sleep_2
|
||||
6. test_extra_io
|
||||
|
||||
## Individual tests
|
||||
|
||||
These tests target a specific sub-circuit or funcationality on the
|
||||
TP-1 and TK-1. Each test is designed to be run successfully in
|
||||
isolation.
|
||||
|
||||
### program_pico: Load the ice40 flasher firmware onto the TP-1
|
||||
|
||||
This test loads the ice40_flasher firmware into the TP-1.
|
||||
|
||||
Usage instructions:
|
||||
1. Attach an unprogrammed TP-1 to the computer using a micro USB
|
||||
cable.
|
||||
2. Run the test.
|
||||
3. The test program will copy the firmware onto the TP-1.
|
||||
4. Once the firmware is copied, the TP-1 will automatically reset,
|
||||
and re-initialize as a ice40_flasher.
|
||||
|
||||
Notes:
|
||||
* This test assumes that the computer is configured to auto-mount USB
|
||||
storage devices, and that the Pico will be mounted to
|
||||
/media/lab/RPI-RP2. This is true for a computer runnnig Ubuntu 22.10
|
||||
when a user is logged into a Gnome GUI session. The script will need
|
||||
to be adjusted for other environments.
|
||||
|
||||
### voltage_test: Measure 3.3V 2.5V, and 1.2V voltage rails on the TK-1
|
||||
|
||||
This test uses ADC in the Pico to measure the power supplies on the
|
||||
TK-1. It samples the voltage of each power supply multiple times,
|
||||
averages the result, and verifies that they are within +/-0.2V of the
|
||||
specification.
|
||||
|
||||
Usage instructions:
|
||||
1. Attach a programmed/tested MTA1_USB_V1_Programmer to the computer
|
||||
using a micro USB cable.
|
||||
2. Place a TK-1 into the MTA1_USB_V1_Programmer. The TK-1 can be
|
||||
programmed or unprogrammed.
|
||||
3. Run the test.
|
||||
4. The test will use the MTA1_USB_V1_Programmer to power on the TK-1,
|
||||
measure the voltage rails, then power off the TK-1.
|
||||
5. The test will report the measurements and pass/fail metric.
|
||||
|
||||
Notes:
|
||||
* The accuracy of the ADC is poor; external hardware would be
|
||||
required to do a more extensive test. The power supplies used are
|
||||
all fixed-voltage devices, so the chance of of an off-spec (but
|
||||
still working) device is considered to be low.
|
||||
* This test does not verify that the power sequencing is correct.
|
||||
|
||||
### flash_validate_id: Read the ID from TK-1 SPI flash, and verify that it's not all 0's or 1's
|
||||
|
||||
This test uses the TP-1 or MTA1_USB_V1_Programmer to read a TK-1 SPI
|
||||
flash ID. It can be used to quickly check if a TK-1 device is
|
||||
inserted properly into the programmger.
|
||||
|
||||
Usage instructions:
|
||||
1. Attach a programmed/tested MTA1_USB_V1_Programmer or TP-1 to the
|
||||
computer using a micro USB cable.
|
||||
2. Place a TK-1 into the MTA1_USB_V1_Programmer. The TK-1 can be
|
||||
programmed or unprogrammed.
|
||||
3. Run the test.
|
||||
4. The test will use the programmer to power on the TP-1, read out
|
||||
the SPI flash ID, then power off the TK-1.
|
||||
5. The test will check if the flash ID matches any known valid flash
|
||||
ID types.
|
||||
6. If the flash ID matches an known value, the test will print the
|
||||
type and return a pass metric.
|
||||
7. If the flash ID does not match a known value, the test will print
|
||||
the type and return a pass metric.
|
||||
|
||||
Notes:
|
||||
* An earlier version of this test just checked if the flash ID was
|
||||
0x00000000 or 0xFFFFFFFF; this version is more exact.
|
||||
|
||||
### flash_program: Program and verify the TK-1 SPI flash with the application test gateware
|
||||
|
||||
This test uses the TP-1 or MTA1_USB_V1_Programmer to write the
|
||||
application test gateware a TK-1 SPI flash. This gateware is needed
|
||||
to run the test_extra_io and test_txrx_touchpad tests. The test uses
|
||||
the external iceprog utility to perform the flash operation.
|
||||
|
||||
Usage instructions:
|
||||
|
||||
1. Attach a programmed/tested MTA1_USB_V1_Programmer or TP-1 to the
|
||||
computer using a micro USB cable.
|
||||
2. Place a TK-1 into the MTA1_USB_V1_Programmer. The TK-1 can be
|
||||
programmed or unprogrammed.
|
||||
3. Run the test.
|
||||
4. The test will use the programmer to power on the TP-1, program the
|
||||
SPI flash with the gateware, verify the flash by reading the data
|
||||
back out, then power off the TK-1.
|
||||
5. The test will report a pass/fail metric vased on the result of the
|
||||
verification phase.
|
||||
|
||||
### flash_check: Verify the TK-1 SPI flash is programmed with the application test gateware
|
||||
|
||||
This test uses the TP-1 or MTA1_USB_V1_Programmer to verify that the
|
||||
application test gateware is written to a TK-1 SPI flash. The test
|
||||
uses the external iceprog utility to perform the verification
|
||||
operation.
|
||||
|
||||
Usage instructions:
|
||||
|
||||
1. Attach a programmed/tested MTA1_USB_V1_Programmer or TP-1 to the
|
||||
computer using a micro USB cable.
|
||||
2. Place a programmed TK-1 into the MTA1_USB_V1_Programmer.
|
||||
3. Run the test.
|
||||
4. The test will use the programmer to power on the TP-1, verify the
|
||||
flash by reading the data back out, then power off the TK-1.
|
||||
5. The test will report a pass/fail metric vased on the result of the
|
||||
verification phase.
|
||||
|
||||
### test_extra_io: Test the TK-1 RTS, CTS, and GPIO1-4 lines by measuring a test pattern generated by the app_test gateware
|
||||
|
||||
This test uses MTA1_USB_V1_Programmer to verify that the RTS, CTS, and
|
||||
GPIO1-4 lines are connected correctly to the ICE40 FPGA.
|
||||
|
||||
On the FPGA side, the application gateware implements a simple state
|
||||
machine for this test. The RTS line is configured as an input, and
|
||||
the CTS, GPIO1, GPIO2, GPIO3, and GPIO4 lines are configured as
|
||||
outputs. The values of the outputs are configured so that only one
|
||||
output is high at a time, while the rest are low. After reset, the
|
||||
GPIO4 line is high. Each time the RTS line is toggled, the next
|
||||
output on the list is set high.
|
||||
|
||||
On the programmer side, the Pico GPIO pin connected to the TK-1 RTS
|
||||
line is configured as an output, and the Pico GPIO pins connected to
|
||||
the other TK-1 line are configured as inputs. The pico checks that
|
||||
each input line is working by cycling the RTS output high and low,
|
||||
then reading the values of each input. This process is repeated 5
|
||||
times until all output lines are measured, then the results are
|
||||
compared to a table of expected values.
|
||||
|
||||
Usage instructions:
|
||||
|
||||
1. Attach a programmed/tested MTA1_USB_V1_Programmer or TP-1 to the
|
||||
computer using a micro USB cable.
|
||||
2. Place a programmed TK-1 into the MTA1_USB_V1_Programmer.
|
||||
3. Run the test.
|
||||
4. The test will use the programmer to power on the TP-1, run the IO
|
||||
test, then power off the TK-1.
|
||||
5. The test will report a pass/fail metric vased on the result of the
|
||||
test.
|
||||
|
||||
### ch552_program: Load the CDC ACM firmware onto a CH552 with a randomly generated serial number, and verify that it boots correctly
|
||||
|
||||
TODO
|
||||
|
||||
### test_txrx_touchpad: Test UART communication, RGB LED, and touchpad by asking the operator to interact with the touch pad
|
||||
|
||||
TODO
|
||||
|
||||
### enable_power: Enable power to the TK-1
|
||||
|
||||
This test uses the TP-1 or MTA1_USB_V1_Programmer to enable power to
|
||||
an attached TK-1. This isn't a functional test, but can be used for
|
||||
manual testing such as measuring voltage rails with a multimeter,
|
||||
probing clock signals with an oscilloscope, etc.
|
||||
|
||||
Usage instructions:
|
||||
|
||||
1. Attach a programmed/tested MTA1_USB_V1_Programmer or TP-1 to the
|
||||
computer using a micro USB cable.
|
||||
2. Place a TK-1 into the MTA1_USB_V1_Programmer. The TK-1 can be
|
||||
programmed or unprogrammed.
|
||||
3. Run the test.
|
||||
4. The test will use the programmer to power on the TP-1
|
||||
5. The test will report a pass metric if the command completed
|
||||
successfully.
|
||||
|
||||
### disable_power: Disable power to the TK-1
|
||||
|
||||
This test uses the TP-1 or MTA1_USB_V1_Programmer to disable power to
|
||||
an attached TK-1. This isn't a functional test, but can be used after
|
||||
the enable_power command was used to turn on a device.
|
||||
|
||||
Usage instructions:
|
||||
|
||||
1. Attach a programmed/tested MTA1_USB_V1_Programmer or TP-1 to the
|
||||
computer using a micro USB cable.
|
||||
2. Place a TK-1 into the MTA1_USB_V1_Programmer. The TK-1 can be
|
||||
programmed or unprogrammed.
|
||||
3. Run the test.
|
||||
4. The test will use the programmer to power off the TP-1
|
||||
5. The test will report a pass metric if the command completed
|
||||
successfully.
|
||||
|
||||
## Firmware binaries
|
||||
|
||||
To make the test environment easier to set up, some pre-compiled
|
||||
binares are included in the binaries/ subdirectory. These can also be
|
||||
built from source, by following the below instructions.
|
||||
|
||||
Before building the firmware, follow the [toolchain setup](https://github.com/tillitis/tillitis-key1/blob/main/doc/toolchain_setup.md)
|
||||
instructions.
|
||||
|
||||
### CH552 firmware
|
||||
|
||||
See the build instructions in the
|
||||
[ch552_fw](../boards/mta1-usb-v1/ch552_fw/README.md) directory.
|
||||
|
||||
### Test Application gateware
|
||||
|
||||
This uses the Symbiflow toolchain:
|
||||
|
||||
cd ~/tillitis-key1/hw/production_test/application_fpga_test_gateware
|
||||
make
|
||||
cp top.bin ../binaries/
|
||||
|
||||
### TP-1 Raspberry Pi Pico firmware
|
||||
|
||||
Follow the instructions in the [ice40_flasher](https://github.com/Blinkinlabs/ice40_flasher#building-the-firmware)
|
||||
repository, then copy the output 'main.uf2' file to the binaries
|
||||
directory.
|
BIN
hw/production_test/binaries/main.uf2
Normal file
BIN
hw/production_test/binaries/main.uf2
Normal file
Binary file not shown.
BIN
hw/production_test/binaries/usb_device_cdc.bin
Normal file
BIN
hw/production_test/binaries/usb_device_cdc.bin
Normal file
Binary file not shown.
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python3
|
||||
#!/usr/bin/env python
|
||||
import hid_test
|
||||
|
||||
def import_pins(pin_filename):
|
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/python3
|
||||
#!/usr/bin/python
|
||||
import tkinter as tk
|
||||
from tkinter import filedialog as fd
|
||||
from tkinter.messagebox import askyesno
|
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python3
|
||||
#!/usr/bin/env python
|
||||
|
||||
manufacturer = 'Mullvad'
|
||||
product = 'MTA1-USB-V1'
|
493
hw/production_test/production_test.py
Executable file
493
hw/production_test/production_test.py
Executable file
@ -0,0 +1,493 @@
|
||||
#!/usr/bin/env python
|
||||
import hid_test
|
||||
import time
|
||||
import numpy
|
||||
from subprocess import run
|
||||
import usb.core
|
||||
import uuid
|
||||
import encode_usb_strings
|
||||
import serial
|
||||
import serial.tools.list_ports;
|
||||
import shutil
|
||||
import os
|
||||
|
||||
# Locations for external utilities and files referenced by the test program
|
||||
file_locations = {
|
||||
'iceprog':'tillitis-iceprog',
|
||||
'chprog':'chprog',
|
||||
'app_gateware':'binaries/top.bin',
|
||||
'ch552_firmware':'binaries/usb_device_cdc.bin',
|
||||
'ch552_firmware_injected':'/tmp/ch552_fw_injected.bin',
|
||||
'pico_bootloader_source':'binaries/main.uf2',
|
||||
'pico_bootloader_target_dir':'/media/lab/RPI-RP2/'
|
||||
}
|
||||
|
||||
def enable_power():
|
||||
"""Enable power to the TK-1"""
|
||||
d = hid_test.ice40_flasher()
|
||||
d.gpio_set_direction(7, True)
|
||||
d.gpio_put(7, True)
|
||||
d.close()
|
||||
time.sleep(.2)
|
||||
|
||||
return True
|
||||
|
||||
def disable_power():
|
||||
"""Disable power to the TK-1"""
|
||||
time.sleep(.1)
|
||||
d = hid_test.ice40_flasher()
|
||||
d.gpio_set_direction(7, True)
|
||||
d.gpio_put(7, False)
|
||||
d.close()
|
||||
|
||||
return True
|
||||
|
||||
def measure_voltages(device, samples):
|
||||
"""Measure the voltage levels of the three mta1 power rails multiple times, and return the average values"""
|
||||
adc_vals = numpy.array([0,0,0])
|
||||
for i in range(0,samples):
|
||||
adc_vals = adc_vals + device.adc_read_all()
|
||||
adc_vals = dict(zip(['1.2','2.5','3.3'],adc_vals/samples))
|
||||
return adc_vals
|
||||
|
||||
def voltage_test():
|
||||
"""Measure 3.3V 2.5V, and 1.2V voltage rails on the TK-1"""
|
||||
enable_power()
|
||||
|
||||
d = hid_test.ice40_flasher()
|
||||
vals = measure_voltages(d,20)
|
||||
|
||||
d.close()
|
||||
disable_power()
|
||||
|
||||
print('voltages:',', '.join('{:}V:{:.3f}'.format(val[0],val[1]) for val in vals.items()))
|
||||
if (
|
||||
(abs(vals['1.2'] - 1.2) > .2)
|
||||
| (abs(vals['2.5'] - 2.5) > .2)
|
||||
| (abs(vals['3.3'] - 3.3) > .2)
|
||||
):
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def flash_validate_id():
|
||||
"""Read the ID from TK-1 SPI flash, and verify that it matches the expected value"""
|
||||
result = run([
|
||||
file_locations['iceprog'],
|
||||
'-t'
|
||||
],
|
||||
capture_output=True)
|
||||
|
||||
err = result.stderr.split(b'\n')
|
||||
for line in err:
|
||||
if line.startswith(b'flash ID:'):
|
||||
vals_b = line.split(b' 0x')[1:]
|
||||
flash_id = int(b''.join(vals_b),16)
|
||||
print(line, hex(flash_id))
|
||||
|
||||
# Note: Flash IDs reported by iceprog are slightly wrong
|
||||
flash_types = {
|
||||
0xb40140b40140b40140b40140b4014: 'XT25F08BDFIGT-S (MTA1-USB-V1)',
|
||||
0xef401400: 'W25Q80DVUXIE (TK-1)'
|
||||
}
|
||||
|
||||
flash_type = flash_types.get(flash_id)
|
||||
|
||||
if flash_type == None:
|
||||
print('Flash ID invalid')
|
||||
return False
|
||||
print('Detected flash type: {:}'.format(flash_type))
|
||||
return True
|
||||
|
||||
return (result.returncode == 0)
|
||||
|
||||
def flash_program():
|
||||
"""Program and verify the TK-1 SPI flash with the application test gateware"""
|
||||
result = run([
|
||||
file_locations['iceprog'],
|
||||
file_locations['app_gateware']
|
||||
])
|
||||
print(result)
|
||||
|
||||
return (result.returncode == 0)
|
||||
|
||||
def flash_check():
|
||||
"""Verify the TK-1 SPI flash is programmed with the application test gateware"""
|
||||
result = run([
|
||||
file_locations['iceprog'],
|
||||
'-c',
|
||||
file_locations['app_gateware']
|
||||
])
|
||||
print(result)
|
||||
|
||||
return (result.returncode == 0)
|
||||
|
||||
def test_extra_io():
|
||||
"""Test the TK-1 RTS, CTS, and GPIO1-4 lines by measuring a test pattern generated by the app_test gateware"""
|
||||
enable_power()
|
||||
|
||||
time.sleep(.1)
|
||||
d = hid_test.ice40_flasher()
|
||||
|
||||
d.gpio_put(16, False)
|
||||
d.gpio_set_direction(16, True)
|
||||
|
||||
expected_results = [1<<(i%5) for i in range(9,-1,-1)]
|
||||
|
||||
results = []
|
||||
for i in range(0,10):
|
||||
vals = d.gpio_get_all()
|
||||
pattern = (vals >> 17) & 0b11111
|
||||
results.append(pattern)
|
||||
|
||||
d.gpio_put(16, True)
|
||||
d.gpio_put(16, False)
|
||||
|
||||
d.gpio_set_direction(16, False)
|
||||
d.close()
|
||||
|
||||
disable_power()
|
||||
|
||||
print(results,expected_results,results == expected_results)
|
||||
return results == expected_results
|
||||
|
||||
|
||||
def test_found_bootloader():
|
||||
"""Search for a CH552 in USB bootloader mode"""
|
||||
print('\n\n\nSearching for CH552 bootloader, plug in USB cable now (times out in 10 seconds)!')
|
||||
for trys in range(0,100): # retry every 0.1s, up to 10 seconds
|
||||
devices= usb.core.find(idVendor=0x4348, idProduct=0x55e0, find_all=True)
|
||||
count = len(list(devices))
|
||||
|
||||
if count == 1:
|
||||
return True
|
||||
|
||||
time.sleep(0.1)
|
||||
|
||||
post = usb.core.find(idVendor=0x4348, idProduct=0x55e0, find_all=True)
|
||||
post_count = len(list(post))
|
||||
return (post_count == 1)
|
||||
|
||||
def inject_serial_number(infile, outfile, serial):
|
||||
"""Inject a serial number into the specified CH552 firmware file"""
|
||||
magic = encode_usb_strings.string_to_descriptor("68de5d27-e223-4874-bc76-a54d6e84068f")
|
||||
replacement = encode_usb_strings.string_to_descriptor(serial)
|
||||
|
||||
f = bytearray(open(infile, 'rb').read())
|
||||
|
||||
pos = f.find(magic)
|
||||
|
||||
if pos < 0:
|
||||
print('failed to find magic string')
|
||||
exit(1)
|
||||
|
||||
f[pos:(pos+len(magic))] = replacement
|
||||
|
||||
with open(outfile, 'wb') as of:
|
||||
of.write(f)
|
||||
|
||||
def flash_ch552(serial):
|
||||
"""Flash an attached CH552 device with the USB CDC firmware, injected with the given serial number"""
|
||||
|
||||
print(serial)
|
||||
inject_serial_number(
|
||||
file_locations['ch552_firmware'],
|
||||
file_locations['ch552_firmware_injected'],
|
||||
serial)
|
||||
|
||||
# Program the CH552 using CHPROG
|
||||
result = run([
|
||||
file_locations['chprog'],
|
||||
file_locations['ch552_firmware_injected']
|
||||
])
|
||||
print(result)
|
||||
return (result.returncode == 0)
|
||||
|
||||
def find_serial_device(desc):
|
||||
"""Look for a serial device that has the given attributes"""
|
||||
|
||||
for port in serial.tools.list_ports.comports():
|
||||
matched = True
|
||||
for key, value in desc.items():
|
||||
if not getattr(port, key) == value:
|
||||
matched = False
|
||||
|
||||
if matched:
|
||||
print(port.device)
|
||||
return port.device
|
||||
|
||||
return None
|
||||
|
||||
def find_ch552(serial):
|
||||
"""Search all serial devices for one that has the correct description and serial number"""
|
||||
time.sleep(1)
|
||||
|
||||
description = {
|
||||
'vid':0x1207,
|
||||
'pid':0x8887,
|
||||
'manufacturer':'Tillitis',
|
||||
'product':'MTA1-USB-V1',
|
||||
'serial_number':serial
|
||||
}
|
||||
|
||||
if find_serial_device(description) == None:
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def ch552_program():
|
||||
"""Load the CDC ACM firmware onto a CH552 with a randomly generated serial number, and verify that it boots correctly"""
|
||||
if not test_found_bootloader():
|
||||
print('Error finding CH552!')
|
||||
return False
|
||||
|
||||
serial = str(uuid.uuid4())
|
||||
|
||||
if not flash_ch552(serial):
|
||||
print('Error flashing CH552!')
|
||||
return False
|
||||
|
||||
if not find_ch552(serial):
|
||||
print('Error finding flashed CH552!')
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def test_txrx_touchpad():
|
||||
"""Test UART communication, RGB LED, and touchpad by asking the operator to interact with the touch pad"""
|
||||
description = {
|
||||
'vid':0x1207,
|
||||
'pid':0x8887,
|
||||
'manufacturer':'Tillitis',
|
||||
'product':'MTA1-USB-V1'
|
||||
}
|
||||
|
||||
s = serial.Serial(find_serial_device(description),9600, timeout=.2)
|
||||
|
||||
if not s.isOpen():
|
||||
print('couldn\'t find/open serial device')
|
||||
return False
|
||||
|
||||
for i in range(0,5):
|
||||
# Attempt to clear any buffered data from the serial port
|
||||
s.write(b'0123')
|
||||
time.sleep(0.2)
|
||||
s.read(20)
|
||||
|
||||
try:
|
||||
s.write(b'0')
|
||||
[count, touch_count] = s.read(2)
|
||||
print('read count:{:}, touch count:{:}'.format(count,touch_count))
|
||||
|
||||
input('\n\n\nPress touch pad once and check LED, then press Enter')
|
||||
s.write(b'0')
|
||||
[count_post, touch_count_post] = s.read(2)
|
||||
print('read count:{:}, touch count:{:}'.format(count_post,touch_count_post))
|
||||
|
||||
if (count_post - count != 1) or (touch_count_post - touch_count !=1):
|
||||
print('Unexpected values returned, trying again')
|
||||
continue
|
||||
|
||||
return True
|
||||
except ValueError as e:
|
||||
print(e)
|
||||
continue
|
||||
|
||||
print('Max retries exceeded, failure!')
|
||||
return False
|
||||
|
||||
|
||||
def program_pico():
|
||||
"""Load the ice40 flasher firmware onto the TP-1"""
|
||||
print('Attach test rig to USB (times out in 10 seconds)')
|
||||
|
||||
firmware_filename = os.path.split(file_locations['pico_bootloader_source'])[1]
|
||||
|
||||
for trys in range(0,100): # retry every 0.1s
|
||||
try:
|
||||
shutil.copyfile(
|
||||
file_locations['pico_bootloader_source'],
|
||||
file_locations['pico_bootloader_target_dir'] + firmware_filename
|
||||
)
|
||||
|
||||
# TODO: Test if the pico identifies as a USB-HID device after programming
|
||||
|
||||
return True
|
||||
except FileNotFoundError:
|
||||
time.sleep(0.1)
|
||||
except PermissionError:
|
||||
time.sleep(0.1)
|
||||
|
||||
return False
|
||||
|
||||
|
||||
def sleep_2():
|
||||
"""Sleep for 2 seconds"""
|
||||
time.sleep(2)
|
||||
return True
|
||||
|
||||
manual_tests = [
|
||||
program_pico,
|
||||
voltage_test,
|
||||
flash_validate_id,
|
||||
flash_program,
|
||||
flash_check,
|
||||
test_extra_io,
|
||||
ch552_program,
|
||||
test_txrx_touchpad,
|
||||
enable_power,
|
||||
disable_power
|
||||
]
|
||||
|
||||
test_sequences = {
|
||||
'tk1_test_sequence' : [
|
||||
voltage_test,
|
||||
flash_validate_id,
|
||||
flash_program,
|
||||
sleep_2,
|
||||
test_extra_io,
|
||||
ch552_program,
|
||||
test_txrx_touchpad
|
||||
],
|
||||
'tp1_test_sequence' : [
|
||||
program_pico,
|
||||
sleep_2,
|
||||
flash_validate_id
|
||||
],
|
||||
'mta1_usb_v1_programmer_test_sequence' : [
|
||||
program_pico,
|
||||
sleep_2,
|
||||
voltage_test,
|
||||
flash_validate_id,
|
||||
sleep_2,
|
||||
test_extra_io
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
|
||||
pass_msg = '''
|
||||
_____ _____ _____
|
||||
| __ \ /\ / ____| / ____|
|
||||
| |__) | / \ | (___ | (___
|
||||
| ___/ / /\ \ \___ \ \___ \
|
||||
| | / ____ \ ____) | ____) |
|
||||
|_| /_/ \_\ |_____/ |_____/
|
||||
'''
|
||||
|
||||
fail_msg = '''
|
||||
______ _____ _
|
||||
| ____| /\ |_ _| | |
|
||||
| |__ / \ | | | |
|
||||
| __| / /\ \ | | | |
|
||||
| | / ____ \ _| |_ | |____
|
||||
|_| /_/ \_\ |_____| |______|
|
||||
'''
|
||||
|
||||
ANSI = {
|
||||
'fg_black':"\u001b[30m",
|
||||
'fg_red':"\u001b[31m",
|
||||
'fg_green':"\u001b[32m",
|
||||
'fg_yellow':"\u001b[33m",
|
||||
'fg_blue':"\u001b[34m",
|
||||
'fg_magenta':"\u001b[35m",
|
||||
'fg_cyan':"\u001b[36m",
|
||||
'fg_white':"\u001b[37m",
|
||||
'bg_black':"\u001b[40m",
|
||||
'bg_red':"\u001b[41m",
|
||||
'bg_green':"\u001b[42m",
|
||||
'bg_yellow':"\u001b[43m",
|
||||
'bg_blue':"\u001b[44m",
|
||||
'bg_magenta':"\u001b[45m",
|
||||
'bg_cyan':"\u001b[46m",
|
||||
'bg_white':"\u001b[47m",
|
||||
'reset':"\u001b[0m",
|
||||
'bold':"\u001b[1m",
|
||||
'underline':"\u001b[4m"
|
||||
}
|
||||
|
||||
def run_tests(test_list):
|
||||
|
||||
for test in test_list:
|
||||
print("\n{:}Test step: {:}{:} ({:})".format(ANSI['bold'],test.__name__, ANSI['reset'], test.__doc__))
|
||||
if not test():
|
||||
print('error running test step ' + test.__name__)
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
if __name__ == '__main__':
|
||||
last_a = 0
|
||||
|
||||
# Allow any of the settings in the file_locations structure to be overridden
|
||||
import argparse
|
||||
parser = argparse.ArgumentParser()
|
||||
|
||||
for setting, value in file_locations.items():
|
||||
parser.add_argument('--' + setting, help='Default setting: ' + value)
|
||||
args = parser.parse_args()
|
||||
|
||||
for arg in args.__dict__:
|
||||
if args.__dict__[arg] is not None:
|
||||
print(arg, args.__dict__[arg])
|
||||
file_locations[arg] = args.__dict__[arg]
|
||||
|
||||
print(file_locations)
|
||||
|
||||
print('\n\nTillitis TK-1 and TP-1 Production tests')
|
||||
|
||||
while True:
|
||||
print('\n\n')
|
||||
|
||||
options = []
|
||||
|
||||
print('=== Test sequences ===')
|
||||
i = 1
|
||||
for name, tests in test_sequences.items():
|
||||
print('{:}{:}. {:}{:}: {:}'.format(ANSI['bold'], i, name, ANSI['reset'], ', '.join([test.__name__ for test in tests])))
|
||||
options.append(tests)
|
||||
i += 1
|
||||
|
||||
print('\n=== Manual tests ===')
|
||||
for test in manual_tests:
|
||||
print('{:}{:}. {:}{:}: {:}'.format(ANSI['bold'], i, test.__name__, ANSI['reset'], test.__doc__))
|
||||
options.append([test])
|
||||
i += 1
|
||||
|
||||
|
||||
if(int(last_a) == 0):
|
||||
a = input('\n\n\nPlease type an option number and press return:')
|
||||
else:
|
||||
a = input('\n\n\nPress return to re-run test {:}, or type in a new option number and press return:'.format(last_a))
|
||||
if a == '':
|
||||
a = last_a
|
||||
|
||||
try:
|
||||
test_sequence = options[int(a)-1]
|
||||
except IndexError as e:
|
||||
print('Invalid input')
|
||||
continue
|
||||
except ValueError as e:
|
||||
print('Invalid input')
|
||||
continue
|
||||
|
||||
try:
|
||||
result = run_tests(test_sequence)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
result = False
|
||||
|
||||
if not result:
|
||||
print(ANSI['bg_red'] + fail_msg + ANSI['reset'])
|
||||
|
||||
try:
|
||||
disable_power()
|
||||
except AttributeError as e:
|
||||
pass
|
||||
except OSError as e:
|
||||
pass
|
||||
else:
|
||||
print(ANSI['bg_green'] + pass_msg + ANSI['reset'])
|
||||
|
||||
last_a = a
|
||||
|
@ -1,4 +1,4 @@
|
||||
#!/usr/bin/env python3
|
||||
#!/usr/bin/env python
|
||||
import hid_test
|
||||
import time
|
||||
|
Loading…
Reference in New Issue
Block a user