commit e0d07fd491117a2e56cf902c9d9b96b0ad691ba1 Author: rebane Date: Mon Aug 22 11:22:31 2016 +0300 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7cdd368 --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +make_array +rtl8710_flasher.bin +rtl8710_flasher.elf + diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..957631e --- /dev/null +++ b/Makefile @@ -0,0 +1,26 @@ +FIRMWARE_ADDRESS = 0x10001000 +BUFFER = 0x10008000 +BUFFER_SIZE = 262144 +FLASH_SECTOR_SIZE = 4096 + +all: + arm-none-eabi-gcc -Wall -g -Os -mlittle-endian -mlong-calls -mthumb -mcpu=cortex-m3 -mfloat-abi=soft -mthumb-interwork -ffunction-sections -ffreestanding -fsingle-precision-constant -Wstrict-aliasing=0 -Wl,-T,rtl8710.ld -nostartfiles -nostdlib -u main -Wl,--section-start=.text=$(FIRMWARE_ADDRESS) -DBUFFER=$(BUFFER) rtl8710_flasher.c spi_flash.c -o rtl8710_flasher.elf + arm-none-eabi-objcopy -O binary rtl8710_flasher.elf rtl8710_flasher.bin + gcc make_array.c -o make_array + cp rtl8710_cpu.ocd rtl8710.ocd + echo "set rtl8710_flasher_firmware_ptr $(FIRMWARE_ADDRESS)" >>rtl8710.ocd + echo "set rtl8710_flasher_buffer $(BUFFER)" >>rtl8710.ocd + echo "set rtl8710_flasher_buffer_size $(BUFFER_SIZE)" >>rtl8710.ocd + echo >>rtl8710.ocd + echo "array set rtl8710_flasher_code {" >>rtl8710.ocd + ./make_array >rtl8710.ocd + echo "}" >>rtl8710.ocd + echo >>rtl8710.ocd + cat rtl8710_flasher.ocd >>rtl8710.ocd + +clean: + rm -rf rtl8710_flasher.elf rtl8710_flasher.bin make_array rtl8710.ocd + +test: + openocd -f interface/stlink-v2-1.cfg -f rtl8710.ocd -c "init" -c "reset halt" -c "rtl8710_flash_read_id" -c "shutdown" + diff --git a/make_array.c b/make_array.c new file mode 100644 index 0000000..683bf1c --- /dev/null +++ b/make_array.c @@ -0,0 +1,25 @@ +#include +#include +#include + +int main(){ + ssize_t i, l; + uint32_t value; + uint8_t buffer[24]; + int started, index; + started = index = 0; + while(1){ + l = read(0, buffer, 24); + if(l < 1)break; + if(started)printf(",\n"); + started = 1; + printf("\t"); + for(i = 0; i < l; i += 4){ + value = ((uint32_t)buffer[i + 0] << 0) | ((uint32_t)buffer[i + 1] << 8) | ((uint32_t)buffer[i + 2] << 16) | ((uint32_t)buffer[i + 3] << 24); + if(i)printf(", "); + printf("%d, 0x%08X", index++, (unsigned int)value); + } + } + printf("\n"); +} + diff --git a/mask.h b/mask.h new file mode 100644 index 0000000..1ef49e7 --- /dev/null +++ b/mask.h @@ -0,0 +1,19 @@ +#ifndef _MASK_H_ +#define _MASK_H_ + +#include + +#define mask8(mask, value) ((((uint8_t)(value)) << __builtin_ctz((mask))) & ((uint8_t)(mask))) +#define mask8_set(target, mask, value) do{ (target) = ((target) & ~((uint8_t)(mask))) | mask8(mask, value); }while(0) +#define mask8_get(target, mask) (((target) & ((uint8_t)(mask))) >> __builtin_ctz((mask))) + +#define mask16(mask, value) ((((uint16_t)(value)) << __builtin_ctz((mask))) & ((uint16_t)(mask))) +#define mask16_set(target, mask, value) do{ (target) = ((target) & ~((uint16_t)(mask))) | mask16(mask, value); }while(0) +#define mask16_get(target, mask) (((target) & ((uint16_t)(mask))) >> __builtin_ctz((mask))) + +#define mask32(mask, value) ((((uint32_t)(value)) << __builtin_ctz((mask))) & ((uint32_t)(mask))) +#define mask32_set(target, mask, value) do{ (target) = ((target) & ~((uint32_t)(mask))) | mask32(mask, value); }while(0) +#define mask32_get(target, mask) (((target) & ((uint32_t)(mask))) >> __builtin_ctz((mask))) + +#endif + diff --git a/rtl8710.h b/rtl8710.h new file mode 100644 index 0000000..07d7bc2 --- /dev/null +++ b/rtl8710.h @@ -0,0 +1,220 @@ +#ifndef _RTL8710_H_ +#define _RTL8710_H_ + +#include + +typedef struct{ + volatile uint32_t CTRLR0; + volatile uint32_t CTRLR1; + volatile uint32_t SSIENR; + volatile uint32_t MWCR; + volatile uint32_t SER; + volatile uint32_t BAUDR; + volatile uint32_t TXFTLR; + volatile uint32_t RXFTLR; + volatile uint32_t TXFLR; + volatile uint32_t RXFLR; + volatile uint32_t SR; + volatile uint32_t IMR; + volatile uint32_t ISR; + volatile uint32_t RISR; + volatile uint32_t TXOICR; + volatile uint32_t RXOICR; + volatile uint32_t RXUICR; + volatile uint32_t MSTICR; + volatile uint32_t ICR; + volatile uint32_t DMACR; + volatile uint32_t DMATDLR; + volatile uint32_t DMARDLR; + volatile uint32_t IDR; + volatile uint32_t SSI_COMP_VERSION; + union{ + struct{ + union{ + volatile uint8_t DR; + volatile uint8_t DR8; + }; + uint8_t RESERVED1[3]; + }__attribute__((packed)); + struct{ + volatile uint16_t DR16; + uint16_t RESERVED2[1]; + }__attribute__((packed)); + volatile uint32_t DR32; + }; + uint32_t RESERVED3[31]; + volatile uint32_t READ_FAST_SINGLE; + volatile uint32_t READ_DUAL_DATA; + volatile uint32_t READ_DUAL_ADDR_DATA; + volatile uint32_t READ_QUAD_DATA; + union{ + volatile uint32_t READ_QUAD_ADDR_DATA; + volatile uint32_t RX_SAMPLE_DLY; + }; + volatile uint32_t WRITE_SIGNLE; + volatile uint32_t WRITE_DUAL_DATA; + volatile uint32_t WRITE_DUAL_ADDR_DATA; + volatile uint32_t WRITE_QUAD_DATA; + volatile uint32_t WRITE_QUAD_ADDR_DATA; + volatile uint32_t WRITE_ENABLE; + volatile uint32_t READ_STATUS; + volatile uint32_t CTRLR2; + volatile uint32_t FBAUDR; + volatile uint32_t ADDR_LENGTH; + volatile uint32_t AUTO_LENGTH; + volatile uint32_t VALID_CMD; + volatile uint32_t FLASE_SIZE; + volatile uint32_t FLUSH_FIFO; +}__attribute__((packed)) SPI_TypeDef; + +#define SPI_FLASH ((SPI_TypeDef *)0x40006000) + +// SPI_CTRLR0 +#define SPI_CTRLR0_FRF (((uint32_t)0x03) << 4) +#define SPI_CTRLR0_SCPH (((uint32_t)0x01) << 6) +#define SPI_CTRLR0_SCPOL (((uint32_t)0x01) << 7) +#define SPI_CTRLR0_TMOD (((uint32_t)0x03) << 8) +#define SPI_CTRLR0_SLV_OE (((uint32_t)0x01) << 10) +#define SPI_CTRLR0_SRL (((uint32_t)0x01) << 11) +#define SPI_CTRLR0_CFS (((uint32_t)0x0F) << 12) +#define SPI_CTRLR0_ADDR_CH (((uint32_t)0x03) << 16) +#define SPI_CTRLR0_DATA_CH (((uint32_t)0x03) << 18) +#define SPI_CTRLR0_CMD_CH (((uint32_t)0x03) << 20) +#define SPI_CTRLR0_FAST_RD (((uint32_t)0x01) << 22) +#define SPI_CTRLR0_SHIFT_CK_MTIMES (((uint32_t)0x1F) << 23) + +// SPI_SER +#define SPI_SER_SS0 (((uint32_t)0x01) << 0) +#define SPI_SER_SS1 (((uint32_t)0x01) << 1) +#define SPI_SER_SS2 (((uint32_t)0x01) << 2) + +// SPI_SR +#define SPI_SR_SSI (((uint32_t)0x01) << 0) +#define SPI_SR_TFNF (((uint32_t)0x01) << 1) +#define SPI_SR_TFE (((uint32_t)0x01) << 2) +#define SPI_SR_RFNE (((uint32_t)0x01) << 3) +#define SPI_SR_RFF (((uint32_t)0x01) << 4) +#define SPI_SR_TXE (((uint32_t)0x01) << 5) + +typedef struct{ + volatile uint32_t PEON_PWR_CTRL; // 0x0200 + volatile uint32_t PON_ISO_CTRL; // 0x0204 + uint32_t RESERVED1[2]; + volatile uint32_t SOC_FUNC_EN; // 0x0210 + volatile uint32_t SOC_HCI_COM_FUNC_EN; // 0x0214 + volatile uint32_t SOC_PERI_FUNC0_EN; // 0x0218 + volatile uint32_t SOC_PERI_FUNC1_EN; // 0x021C + volatile uint32_t SOC_PERI_DB_FUNC0_EN; // 0x0220 + uint32_t RESERVED2[3]; + volatile uint32_t PESOC_CLK_CTRL; // 0x0230 + volatile uint32_t PESOC_PERI_CLK_CTRL0; // 0x0234 + volatile uint32_t PESOC_PERI_CLK_CTRL1; // 0x0238 + volatile uint32_t PESOC_CLK_CTRL3; // 0x023C + volatile uint32_t PESOC_HCI_CLK_CTRL0; // 0x0240 + volatile uint32_t PESOC_COM_CLK_CTRL1; // 0x0244 + volatile uint32_t PESOC_HW_ENG_CLK_CTRL; // 0x0248 + uint32_t RESERVED3[1]; + volatile uint32_t PESOC_CLK_SEL; // 0x0250 + uint32_t RESERVED4[6]; + volatile uint32_t SYS_ANACK_CAL_CTRL; // 0x026C + volatile uint32_t OSC32K_CTRL; // 0x0270 + volatile uint32_t OSC32K_REG_CTRL0; // 0x0274 + volatile uint32_t OSC32K_REG_CTRL1; // 0x0278 + volatile uint32_t THERMAL_METER_CTRL; // 0x027C + volatile uint32_t UART_MUX_CTRL; // 0x0280 + volatile uint32_t SPI_MUX_CTRL; // 0x0284 + volatile uint32_t I2C_MUX_CTRL; // 0x0288 + volatile uint32_t I2S_MUX_CTRL; // 0x028C + uint32_t RESERVED5[4]; + volatile uint32_t HCI_PINMUX_CTRL; // 0x02A0 + volatile uint32_t WL_PINMUX_CTRL; // 0x02A4 + volatile uint32_t BT_PINMUX_CTRL; // 0x02A8 + volatile uint32_t PWM_PINMUX_CTRL; // 0x02AC + uint32_t RESERVED6[4]; + volatile uint32_t CPU_PERIPHERAL_CTRL; // 0x02C0 + uint32_t RESERVED7[7]; + volatile uint32_t HCI_CTRL_STATUS_0; // 0x02E0 + volatile uint32_t HCI_CTRL_STATUS_1; // 0x02E4 + uint32_t RESERVED8[6]; + volatile uint32_t PESOC_MEM_CTRL; // 0x0300 + volatile uint32_t PESOC_SOC_CTRL; // 0x0304 + volatile uint32_t PESOC_PERI_CTRL; // 0x0308 + uint32_t RESERVED9[5]; + volatile uint32_t GPIO_SHTDN_CTRL; // 0x0320 + volatile uint32_t GPIO_DRIVING_CTRL; // 0x0324 + uint32_t RESERVED10[2]; + volatile uint32_t GPIO_PULL_CTRL0; // 0x0330 + volatile uint32_t GPIO_PULL_CTRL1; // 0x0334 + volatile uint32_t GPIO_PULL_CTRL2; // 0x0338 + volatile uint32_t GPIO_PULL_CTRL3; // 0x033C + volatile uint32_t GPIO_PULL_CTRL4; // 0x0340 + volatile uint32_t GPIO_PULL_CTRL5; // 0x0344 + volatile uint32_t GPIO_PULL_CTRL6; // 0x0348 + uint32_t RESERVED11[5]; + volatile uint32_t PERI_PWM0_CTRL; // 0x0360 + volatile uint32_t PERI_PWM1_CTRL; // 0x0364 + volatile uint32_t PERI_PWM2_CTRL; // 0x0368 + volatile uint32_t PERI_PWM3_CTRL; // 0x036C + volatile uint32_t PERI_TIM_EVT_CTRL; // 0x0370 + volatile uint32_t PERI_EGTIM_CTRL; // 0x0374 + uint32_t RESERVED12[30]; + volatile uint32_t PEON_CFG; // 0x03F0 + volatile uint32_t PEON_STATUS; // 0x03F4 +}__attribute__((packed)) PERI_ON_TypeDef; + +#define PERI_ON ((PERI_ON_TypeDef *)0x40000200) + +// PERI_ON_SOC_FUNC_EN +#define PERI_ON_SOC_FUNC_EN_FUN (((uint32_t)0x01) << 0) +#define PERI_ON_SOC_FUNC_EN_OCP (((uint32_t)0x01) << 1) +#define PERI_ON_SOC_FUNC_EN_LXBUS (((uint32_t)0x01) << 2) +#define PERI_ON_SOC_FUNC_EN_FLASH (((uint32_t)0x01) << 4) +#define PERI_ON_SOC_FUNC_EN_MEM_CTRL (((uint32_t)0x01) << 6) +#define PERI_ON_SOC_FUNC_EN_CPU (((uint32_t)0x01) << 8) +#define PERI_ON_SOC_FUNC_EN_LOG_UART (((uint32_t)0x01) << 12) +#define PERI_ON_SOC_FUNC_EN_GDMA0 (((uint32_t)0x01) << 13) +#define PERI_ON_SOC_FUNC_EN_GDMA1 (((uint32_t)0x01) << 14) +#define PERI_ON_SOC_FUNC_EN_GTIMER (((uint32_t)0x01) << 16) +#define PERI_ON_SOC_FUNC_EN_SECURITY_ENGINE (((uint32_t)0x01) << 20) + +// PERI_ON_SOC_PERI_FUNC1_EN +#define PERI_ON_SOC_PERI_FUNC1_EN_ADC0 (((uint32_t)0x01) << 0) +#define PERI_ON_SOC_PERI_FUNC1_EN_DAC0 (((uint32_t)0x01) << 4) +#define PERI_ON_SOC_PERI_FUNC1_EN_DAC1 (((uint32_t)0x01) << 5) +#define PERI_ON_SOC_PERI_FUNC1_EN_GPIO (((uint32_t)0x01) << 8) + +// PERI_ON_PESOC_CLK_CTRL +#define PERI_ON_CLK_CTRL_CKE_OCP (((uint32_t)0x01) << 0) +#define PERI_ON_CLK_CTRL_CKE_PLFM (((uint32_t)0x01) << 2) +#define PERI_ON_CLK_CTRL_ACTCK_TRACE_EN (((uint32_t)0x01) << 4) +#define PERI_ON_CLK_CTRL_SLPCK_TRACE_EN (((uint32_t)0x01) << 5) +#define PERI_ON_CLK_CTRL_ACTCK_VENDOR_REG_EN (((uint32_t)0x01) << 6) +#define PERI_ON_CLK_CTRL_SLPCK_VENDOR_REG_EN (((uint32_t)0x01) << 7) +#define PERI_ON_CLK_CTRL_ACTCK_FLASH_EN (((uint32_t)0x01) << 8) +#define PERI_ON_CLK_CTRL_SLPCK_FLASH_EN (((uint32_t)0x01) << 9) +#define PERI_ON_CLK_CTRL_ACTCK_SDR_EN (((uint32_t)0x01) << 10) +#define PERI_ON_CLK_CTRL_SLPCK_SDR_EN (((uint32_t)0x01) << 11) +#define PERI_ON_CLK_CTRL_ACTCK_LOG_UART_EN (((uint32_t)0x01) << 12) +#define PERI_ON_CLK_CTRL_SLPCK_LOG_UART_EN (((uint32_t)0x01) << 13) +#define PERI_ON_CLK_CTRL_ACTCK_TIMER_EN (((uint32_t)0x01) << 14) +#define PERI_ON_CLK_CTRL_SLPCK_TIMER_EN (((uint32_t)0x01) << 15) +#define PERI_ON_CLK_CTRL_ACTCK_GDMA0_EN (((uint32_t)0x01) << 16) +#define PERI_ON_CLK_CTRL_SLPCK_GDMA0_EN (((uint32_t)0x01) << 17) +#define PERI_ON_CLK_CTRL_ACTCK_GDMA1_EN (((uint32_t)0x01) << 18) +#define PERI_ON_CLK_CTRL_SLPCK_GDMA1_EN (((uint32_t)0x01) << 19) +#define PERI_ON_CLK_CTRL_ACTCK_GPIO_EN (((uint32_t)0x01) << 24) +#define PERI_ON_CLK_CTRL_SLPCK_GPIO_EN (((uint32_t)0x01) << 25) +#define PERI_ON_CLK_CTRL_ACTCK_BTCMD_EN (((uint32_t)0x01) << 28) +#define PERI_ON_CLK_CTRL_SLPCK_BTCMD_EN (((uint32_t)0x01) << 29) + +// PERI_ON_CPU_PERIPHERAL_CTRL +#define PERI_ON_CPU_PERIPHERAL_CTRL_SPI_FLASH_PIN_EN (((uint32_t)0x01) << 0) +#define PERI_ON_CPU_PERIPHERAL_CTRL_SPI_FLASH_PIN_SEL (((uint32_t)0x03) << 1) +#define PERI_ON_CPU_PERIPHERAL_CTRL_SDR_PIN_EN (((uint32_t)0x01) << 4) +#define PERI_ON_CPU_PERIPHERAL_CTRL_TRACE_PIN_EN (((uint32_t)0x01) << 17) +#define PERI_ON_CPU_PERIPHERAL_CTRL_LOG_UART_PIN_EN (((uint32_t)0x01) << 20) +#define PERI_ON_CPU_PERIPHERAL_CTRL_LOG_UART_IR_EN (((uint32_t)0x01) << 21) +#define PERI_ON_CPU_PERIPHERAL_CTRL_LOG_UART_PIN_SEL (((uint32_t)0x03) << 22) + +#endif + diff --git a/rtl8710.ld b/rtl8710.ld new file mode 100644 index 0000000..5b8537d --- /dev/null +++ b/rtl8710.ld @@ -0,0 +1,19 @@ +MEMORY{ + tcm (rwx) : ORIGIN = 0x1FFF0000, LENGTH = 64k + ram (rwx) : ORIGIN = 0x10000000, LENGTH = 448k +} + +PROVIDE(STACK_TOP = 0x1FFF0000 + 64k); + +SECTIONS{ + .text : { __text_beg__ = . ; *(.vectors*) *(.header) *(.text) *(.text*) *(.rodata) *(.rodata*) *(.glue_7) *(.glue_7t) *(.eh_frame) *(.ARM.extab*) . = ALIGN(4); __text_end__ = . ; } >ram + .data : { . = ALIGN(4); __data_beg__ = . ; *(.ram_vectors) *(.data) *(.data*) *(.ram_func) . = ALIGN(4); __data_end__ = . ; } >ram + .bss : { . = ALIGN(4); __bss_beg__ = . ; *(.bss) *(COMMON) . = ALIGN(4); __bss_end__ = . ; } >ram + __exidx_start = .; + .ARM.exidx : { ___exidx_start = . ; *(.ARM.exidx*) ; ___exidx_end = . ; } >ram + __exidx_end = .; + .ARM.extab : { *(.ARM.extab*) } >ram + . = ALIGN(4); + end = .; PROVIDE (end = .); +} + diff --git a/rtl8710.ocd b/rtl8710.ocd new file mode 100644 index 0000000..b0f08d2 --- /dev/null +++ b/rtl8710.ocd @@ -0,0 +1,340 @@ +# +# script for RTL8710 +# + +source [find target/swj-dp.tcl] + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME rtl8710 +} + +if { [info exists ENDIAN] } { + set _ENDIAN $ENDIAN +} else { + set _ENDIAN little +} + +# Work-area is a space in RAM used for flash programming +# By default use 2kB +if { [info exists WORKAREASIZE] } { + set _WORKAREASIZE $WORKAREASIZE +} else { + set _WORKAREASIZE 0x800 +} + +if { [info exists CPUTAPID] } { + set _CPUTAPID $CPUTAPID +} else { + set _CPUTAPID 0x2ba01477 +} + +swj_newdap $_CHIPNAME cpu -irlen 4 -expected-id $_CPUTAPID + +set _TARGETNAME $_CHIPNAME.cpu +target create $_TARGETNAME cortex_m -endian $_ENDIAN -chain-position $_TARGETNAME + +$_TARGETNAME configure -work-area-phys 0x10001000 -work-area-size $_WORKAREASIZE -work-area-backup 0 + +adapter_khz 500 +adapter_nsrst_delay 100 + +if {![using_hla]} { + # if srst is not fitted use SYSRESETREQ to + # perform a soft reset + cortex_m reset_config sysresetreq +} + +set rtl8710_flasher_firmware_ptr 0x10001000 +set rtl8710_flasher_buffer 0x10008000 +set rtl8710_flasher_buffer_size 262144 + +array set rtl8710_flasher_code { + 0, 0x4B59B57F, 1, 0x6B1A25FF, 2, 0xF0426B19, 3, 0x63187040, 4, 0x4E5669D9, 5, 0x7480F441, + 6, 0x61DC69D9, 7, 0x2120F8D3, 8, 0x5120F8C3, 9, 0x1124F8D3, 10, 0x5124F8C3, 11, 0x4E5047B0, + 12, 0x4B5047B0, 13, 0x4A504798, 14, 0x47B06010, 15, 0x2100484F, 16, 0x68046001, 17, 0xD0FC2C00, + 18, 0x682E4D4D, 19, 0x4C4AB93E, 20, 0x4E476026, 21, 0x4B4747B0, 22, 0x60204798, 23, 0x682BE7ED, + 24, 0xD1092B01, 25, 0x47B04E42, 26, 0x20064C46, 27, 0x4A4647A0, 28, 0x20C74790, 29, 0xE00D47A0, + 30, 0x2A02682A, 31, 0x4E3CD10E, 32, 0x4C4047B0, 33, 0x47A02006, 34, 0x4780483F, 35, 0x4D40493F, + 36, 0x47A86808, 37, 0x200447B0, 38, 0xE7CE47A0, 39, 0x28036828, 40, 0x4C33D113, 41, 0x483947A0, + 42, 0x68052400, 43, 0x19604E39, 44, 0x428C6831, 45, 0x4A38D206, 46, 0x18A14B38, 47, 0x47982210, + 48, 0xE7F33410, 49, 0x47A84D2A, 50, 0x6829E7B8, 51, 0xD11B2904, 52, 0x48302400, 53, 0x42B46806, + 54, 0x4D25D2B0, 55, 0x4E2947A8, 56, 0x47B02006, 57, 0x47984B28, 58, 0x4B2B4928, 59, 0x18E1680A, + 60, 0x4B2B18A0, 61, 0x7280F44F, 62, 0x47A84798, 63, 0x47B02004, 64, 0x7480F504, 65, 0xE7E447A8, + 66, 0x2C05682C, 67, 0x4B18D123, 68, 0x24004798, 69, 0x682A4D1F, 70, 0xD28F4294, 71, 0x2210481B, + 72, 0x4E1E6801, 73, 0x46691860, 74, 0x682B47B0, 75, 0x29101B19, 76, 0x2110BF28, 77, 0x428B2300, + 78, 0x4A17D011, 79, 0x5003F81D, 80, 0x5CC618A0, 81, 0xD10142B5, 82, 0xE7F43301, 83, 0x21014A15, + 84, 0x60546011, 85, 0x4E13E772, 86, 0x60352501, 87, 0x4D04E76E, 88, 0x341047A8, 89, 0xBF00E7D6, + 90, 0x40000200, 91, 0x100011BD, 92, 0x100013DD, 93, 0x10001289, 94, 0x1000800C, 95, 0x10008000, + 96, 0x10008004, 97, 0x1000130D, 98, 0x100013ED, 99, 0x10008010, 100, 0x10001335, 101, 0x10008014, + 102, 0x10008020, 103, 0x10001221, 104, 0x10001375, 105, 0x10008008, 106, 0x6A5A4B03, 107, 0xD0FB0512, + 108, 0x0060F893, 109, 0xBF004770, 110, 0x40006000, 111, 0x6B194B17, 112, 0xF4416B1A, 113, 0x63187040, + 114, 0x69186919, 115, 0x0110F041, 116, 0xF8D36119, 117, 0x220000C0, 118, 0x0106F020, 119, 0x00C0F8D3, + 120, 0x10C0F8C3, 121, 0x00C0F8D3, 122, 0x0101F040, 123, 0x00C0F8D3, 124, 0x10C0F8C3, 125, 0x43BCF503, + 126, 0x609A6899, 127, 0x20016AD9, 128, 0x691962DA, 129, 0x69596118, 130, 0x61592102, 131, 0x619A6999, + 132, 0x61DA69D9, 133, 0x64DA6CD9, 134, 0xBF004770, 135, 0x40000200, 136, 0x460EB570, 137, 0xB34A4614, + 138, 0xF3C04B15, 139, 0x681A4507, 140, 0x7240F44F, 141, 0x685A601A, 142, 0xF3C02103, 143, 0x2C102207, + 144, 0x2410BF28, 145, 0x605CB2C0, 146, 0x1060F883, 147, 0x5060F883, 148, 0xF8832101, 149, 0xF8832060, + 150, 0x689A0060, 151, 0x60992500, 152, 0x47984B08, 153, 0x35015570, 154, 0x42A2B2AA, 155, 0x4804D3F8, + 156, 0xF0116A81, 157, 0xD1FA0301, 158, 0x60836881, 159, 0xBD704620, 160, 0x40006000, 161, 0x100011A9, + 162, 0x4C10B5F8, 163, 0x68232003, 164, 0x7340F44F, 165, 0x68636023, 166, 0x60602101, 167, 0x68A3229F, + 168, 0x60A14D0B, 169, 0x2060F884, 170, 0x460647A8, 171, 0x460747A8, 172, 0x040347A8, 173, 0x2707EA43, + 174, 0x0006EA47, 175, 0x4B036AA1, 176, 0x0201F011, 177, 0x6899D1FA, 178, 0xBDF8609A, 179, 0x40006000, + 180, 0x100011A9, 181, 0x4C0BB510, 182, 0x68232001, 183, 0x7340F44F, 184, 0x68636023, 185, 0x60602105, + 186, 0x60A068A2, 187, 0xF8844A06, 188, 0x47901060, 189, 0x4B036AA1, 190, 0x0201F011, 191, 0x6899D1FA, + 192, 0xBD10609A, 193, 0x40006000, 194, 0x100011A9, 195, 0x21014B08, 196, 0xF44F681A, 197, 0x601A7280, + 198, 0x6099689A, 199, 0x0060F883, 200, 0x48036A9A, 201, 0x0101F012, 202, 0x6883D1FA, 203, 0x47706081, + 204, 0x40006000, 205, 0x21014B0E, 206, 0xF44F681A, 207, 0x601A7280, 208, 0x2220689A, 209, 0xF8836099, + 210, 0xF3C02060, 211, 0xF3C04107, 212, 0xB2C02207, 213, 0x1060F883, 214, 0x2060F883, 215, 0x0060F883, + 216, 0x4A036A99, 217, 0x0001F011, 218, 0x6893D1FA, 219, 0x47706090, 220, 0x40006000, 221, 0xB36AB530, + 222, 0x25014B17, 223, 0xF44F681C, 224, 0x601C7480, 225, 0x2402689C, 226, 0xF883609D, 227, 0xF3C04060, + 228, 0xF3C04507, 229, 0xB2C02407, 230, 0x5060F883, 231, 0x7F80F5B2, 232, 0xF44FBF28, 233, 0xF8837280, + 234, 0xF8834060, 235, 0x20000060, 236, 0x4C095C0D, 237, 0xF8843001, 238, 0xB2855060, 239, 0xD3F74295, + 240, 0x07496A99, 241, 0x6AA0D5FC, 242, 0xF0104B03, 243, 0xD1FA0101, 244, 0x60996898, 245, 0xBD304610, + 246, 0x40006000, 247, 0x4B02B508, 248, 0x07C04798, 249, 0xBD08D4FB, 250, 0x100012D5, 251, 0x4B04B508, + 252, 0xF0004798, 253, 0xB2C10002, 254, 0xD0F82900, 255, 0xBF00BD08, 256, 0x100012D5 +} + +set rtl8710_flasher_firmware_ptr 0x10001D00 +set rtl8710_flasher_buffer 0x10008000 +set rtl8710_flasher_buffer_size 262144 +set rtl8710_flasher_sector_size 4096 + +set rtl8710_flasher_command_read_id 0 +set rtl8710_flasher_command_mass_erase 1 +set rtl8710_flasher_command_sector_erase 2 +set rtl8710_flasher_command_read 3 +set rtl8710_flasher_command_write 4 +set rtl8710_flasher_command_verify 5 + +set rtl8710_flasher_ready 0 +set rtl8710_flasher_capacity 0 +set rtl8710_flasher_auto_erase 0 +set rtl8710_flasher_auto_verify 0 +set rtl8710_flasher_auto_erase_sector 0xFFFFFFFF + +proc rtl8710_flasher_init {} { + global rtl8710_flasher_firmware_ptr + global rtl8710_flasher_buffer + global rtl8710_flasher_capacity + global rtl8710_flasher_ready + + if {[expr {$rtl8710_flasher_ready == 0}]} { + echo "initializing RTL8710 SPI programmer" + halt + mww [expr {$rtl8710_flasher_buffer + 0x08}] 0x00000000 + mww [expr {$rtl8710_flasher_buffer + 0x00}] 0x00000001 + array2mem rtl8710_flasher_code 32 $rtl8710_flasher_firmware_ptr + reg faultmask 0x01 + reg sp 0x20000000 + reg pc $rtl8710_flasher_firmware_ptr + resume + rtl8710_flasher_wait + set id [rtl8710_flasher_mrw [expr {$rtl8710_flasher_buffer + 0x0C}]] + set rtl8710_flasher_capacity [expr {2 ** [expr {($id >> 16) & 0xFF}]}] + set rtl8710_flasher_ready 1 + } + return "" +} + +proc rtl8710_flasher_mrw {reg} { + set value "" + mem2array value 32 $reg 1 + return $value(0) +} + +proc rtl8710_flasher_wait {} { + global rtl8710_flasher_buffer + while {[rtl8710_flasher_mrw [expr {$rtl8710_flasher_buffer + 0x00}]]} { } +} + +proc rtl8710_flasher_load_block {local_filename offset len} { + global rtl8710_flasher_buffer + load_image $local_filename [expr {$rtl8710_flasher_buffer + 0x20 - $offset}] bin [expr {$rtl8710_flasher_buffer + 0x20}] $len +} + +proc rtl8710_flasher_read_block {offset len} { + global rtl8710_flasher_buffer + global rtl8710_flasher_command_read + mww [expr {$rtl8710_flasher_buffer + 0x04}] $rtl8710_flasher_command_read + mww [expr {$rtl8710_flasher_buffer + 0x08}] 0x00000000 + mww [expr {$rtl8710_flasher_buffer + 0x10}] $offset + mww [expr {$rtl8710_flasher_buffer + 0x14}] $len + mww [expr {$rtl8710_flasher_buffer + 0x00}] 0x00000001 + rtl8710_flasher_wait + set status [rtl8710_flasher_mrw [expr {$rtl8710_flasher_buffer + 0x08}]] + if {[expr {$status > 0}]} { + error "read error, offset $offset" + } + dump_image /tmp/_flasher.bin [expr {$rtl8710_flasher_buffer + 0x20}] $len +} + +proc rtl8710_flasher_write_block {offset len} { + global rtl8710_flasher_buffer + global rtl8710_flasher_command_write + mww [expr {$rtl8710_flasher_buffer + 0x04}] $rtl8710_flasher_command_write + mww [expr {$rtl8710_flasher_buffer + 0x08}] 0x00000000 + mww [expr {$rtl8710_flasher_buffer + 0x10}] $offset + mww [expr {$rtl8710_flasher_buffer + 0x14}] $len + mww [expr {$rtl8710_flasher_buffer + 0x00}] 0x00000001 + rtl8710_flasher_wait + set status [rtl8710_flasher_mrw [expr {$rtl8710_flasher_buffer + 0x08}]] + if {[expr {$status > 0}]} { + error "write error, offset $offset" + } +} + +proc rtl8710_flasher_verify_block {offset len} { + global rtl8710_flasher_buffer + global rtl8710_flasher_command_verify + mww [expr {$rtl8710_flasher_buffer + 0x04}] $rtl8710_flasher_command_verify + mww [expr {$rtl8710_flasher_buffer + 0x08}] 0x00000000 + mww [expr {$rtl8710_flasher_buffer + 0x10}] $offset + mww [expr {$rtl8710_flasher_buffer + 0x14}] $len + mww [expr {$rtl8710_flasher_buffer + 0x00}] 0x00000001 + rtl8710_flasher_wait + set status [rtl8710_flasher_mrw [expr {$rtl8710_flasher_buffer + 0x08}]] + if {[expr {$status > 0}]} { + set status [rtl8710_flasher_mrw [expr {$rtl8710_flasher_buffer + 0x0C}]] + set status [expr {$status + $offset}] + error "verify error, offset $status" + } +} + +proc rtl8710_flasher_read_id {} { + global rtl8710_flasher_buffer + global rtl8710_flasher_capacity + global rtl8710_flasher_command_read_id + mww [expr {$rtl8710_flasher_buffer + 0x04}] $rtl8710_flasher_command_read_id + mww [expr {$rtl8710_flasher_buffer + 0x08}] 0x00000000 + mww [expr {$rtl8710_flasher_buffer + 0x00}] 0x00000001 + rtl8710_flasher_wait + set id [rtl8710_flasher_mrw [expr {$rtl8710_flasher_buffer + 0x0C}]] + set manufacturer_id [format "0x%02X" [expr {$id & 0xFF}]] + set memory_type [format "0x%02X" [expr {($id >> 8) & 0xFF}]] + set memory_capacity [expr {2 ** [expr {($id >> 16) & 0xFF}]}] + echo "manufacturer ID: $manufacturer_id, memory type: $memory_type, memory capacity: $memory_capacity byte(s)" +} + +proc rtl8710_flasher_mass_erase {} { + global rtl8710_flasher_buffer + global rtl8710_flasher_command_mass_erase + mww [expr {$rtl8710_flasher_buffer + 0x04}] $rtl8710_flasher_command_mass_erase + mww [expr {$rtl8710_flasher_buffer + 0x08}] 0x00000000 + mww [expr {$rtl8710_flasher_buffer + 0x00}] 0x00000001 + rtl8710_flasher_wait +} + +proc rtl8710_flasher_sector_erase {offset} { + global rtl8710_flasher_buffer + global rtl8710_flasher_command_sector_erase + mww [expr {$rtl8710_flasher_buffer + 0x04}] $rtl8710_flasher_command_sector_erase + mww [expr {$rtl8710_flasher_buffer + 0x08}] 0x00000000 + mww [expr {$rtl8710_flasher_buffer + 0x10}] $offset + mww [expr {$rtl8710_flasher_buffer + 0x00}] 0x00000001 + rtl8710_flasher_wait +} + +proc rtl8710_flasher_read {local_filename loc size} { + global rtl8710_flasher_buffer_size + for {set offset 0} {$offset < $size} {set offset [expr {$offset + $rtl8710_flasher_buffer_size}]} { + set len [expr {$size - $offset}] + if {[expr {$len > $rtl8710_flasher_buffer_size}]} { + set len $rtl8710_flasher_buffer_size + } + set flash_offset [expr {$loc + $offset}] + echo "read offset $flash_offset" + rtl8710_flasher_read_block $flash_offset $len + exec dd conv=notrunc if=/tmp/_flasher.bin "of=$local_filename" bs=1 "seek=$offset" + } +} + +proc rtl8710_flasher_write {local_filename loc} { + global rtl8710_flasher_buffer_size + global rtl8710_flasher_sector_size + global rtl8710_flasher_auto_erase + global rtl8710_flasher_auto_verify + global rtl8710_flasher_auto_erase_sector + set sector 0 + set size [file size $local_filename] + for {set offset 0} {$offset < $size} {set offset [expr {$offset + $rtl8710_flasher_buffer_size}]} { + set len [expr {$size - $offset}] + if {[expr {$len > $rtl8710_flasher_buffer_size}]} { + set len $rtl8710_flasher_buffer_size + } + set flash_offset [expr {$loc + $offset}] + rtl8710_flasher_load_block $local_filename $offset $len + if {[expr {$rtl8710_flasher_auto_erase != 0}]} { + for {set i $flash_offset} {$i < [expr {$flash_offset + $len}]} {incr i} { + set sector [expr {$i / $rtl8710_flasher_sector_size}] + if {[expr {$rtl8710_flasher_auto_erase_sector != $sector}]} { + echo "erase sector $sector" + rtl8710_flasher_sector_erase [expr {$sector * $rtl8710_flasher_sector_size}] + set rtl8710_flasher_auto_erase_sector $sector + } + } + } + echo "write offset $flash_offset" + rtl8710_flasher_write_block $flash_offset $len + if {[expr {$rtl8710_flasher_auto_verify != 0}]} { + echo "verify offset $flash_offset" + rtl8710_flasher_verify_block $flash_offset $len + } + } +} + +proc rtl8710_flasher_verify {local_filename loc} { + global rtl8710_flasher_buffer_size + set size [file size $local_filename] + for {set offset 0} {$offset < $size} {set offset [expr {$offset + $rtl8710_flasher_buffer_size}]} { + set len [expr {$size - $offset}] + if {[expr {$len > $rtl8710_flasher_buffer_size}]} { + set len $rtl8710_flasher_buffer_size + } + set flash_offset [expr {$loc + $offset}] + rtl8710_flasher_load_block $local_filename $offset $len + echo "verify offset $flash_offset" + rtl8710_flasher_verify_block $flash_offset $len + } +} + +proc rtl8710_auto_erase {on} { + global rtl8710_flasher_auto_erase + if {[expr {$on != 0}]} { + set rtl8710_flasher_auto_erase 1 + echo "auto erase on" + } else { + set rtl8710_flasher_auto_erase 0 + echo "auto erase off" + } +} + +proc rtl8710_auto_verify {on} { + global rtl8710_flasher_auto_verify + if {[expr {$on != 0}]} { + set rtl8710_flasher_auto_verify 1 + echo "auto verify on" + } else { + set rtl8710_flasher_auto_verify 0 + echo "auto verify off" + } +} + +proc rtl8710_mass_erase {} { + echo "mass erase" + rtl8710_flasher_mass_erase +} + +proc rtl8710_flash_read {local_filename loc size} { + rtl8710_flasher_read $local_filename $loc $size +} + +proc rtl8710_flash_write {local_filename loc} { + rtl8710_flasher_write $local_filename $loc +} + +proc rtl8710_reboot {} { + mww 0xE000ED0C 0x05FA0007 +} + diff --git a/rtl8710_cpu.ocd b/rtl8710_cpu.ocd new file mode 100644 index 0000000..14ad27f --- /dev/null +++ b/rtl8710_cpu.ocd @@ -0,0 +1,48 @@ +# +# script for RTL8710 +# + +source [find target/swj-dp.tcl] + +if { [info exists CHIPNAME] } { + set _CHIPNAME $CHIPNAME +} else { + set _CHIPNAME rtl8710 +} + +if { [info exists ENDIAN] } { + set _ENDIAN $ENDIAN +} else { + set _ENDIAN little +} + +# Work-area is a space in RAM used for flash programming +# By default use 2kB +if { [info exists WORKAREASIZE] } { + set _WORKAREASIZE $WORKAREASIZE +} else { + set _WORKAREASIZE 0x800 +} + +if { [info exists CPUTAPID] } { + set _CPUTAPID $CPUTAPID +} else { + set _CPUTAPID 0x2ba01477 +} + +swj_newdap $_CHIPNAME cpu -irlen 4 -expected-id $_CPUTAPID + +set _TARGETNAME $_CHIPNAME.cpu +target create $_TARGETNAME cortex_m -endian $_ENDIAN -chain-position $_TARGETNAME + +$_TARGETNAME configure -work-area-phys 0x10001000 -work-area-size $_WORKAREASIZE -work-area-backup 0 + +adapter_khz 500 +adapter_nsrst_delay 100 + +if {![using_hla]} { + # if srst is not fitted use SYSRESETREQ to + # perform a soft reset + cortex_m reset_config sysresetreq +} + diff --git a/rtl8710_flasher.c b/rtl8710_flasher.c new file mode 100644 index 0000000..0289e90 --- /dev/null +++ b/rtl8710_flasher.c @@ -0,0 +1,101 @@ +#include "rtl8710.h" +#include +#include "spi_flash.h" + +#define MEM_START (*(volatile uint32_t *)(BUFFER + 0x00)) +#define MEM_COMMAND (*(volatile uint32_t *)(BUFFER + 0x04)) +#define MEM_STATUS (*(volatile uint32_t *)(BUFFER + 0x08)) +#define MEM_PARAM (*(volatile uint32_t *)(BUFFER + 0x0C)) +#define MEM_OFFSET (*(volatile uint32_t *)(BUFFER + 0x10)) +#define MEM_LEN (*(volatile uint32_t *)(BUFFER + 0x14)) +#define MEM_DATA ((volatile uint8_t *)(BUFFER + 0x20)) + +#define COMMAND_READ_ID 0 +#define COMMAND_MASS_ERASE 1 +#define COMMAND_SECTOR_ERASE 2 +#define COMMAND_READ 3 +#define COMMAND_WRITE 4 +#define COMMAND_VERIFY 5 + +int __attribute__((section(".vectors"))) main(){ + uint32_t p, i, l; + uint8_t read_buffer[16]; + + PERI_ON->PESOC_CLK_CTRL |= PERI_ON_CLK_CTRL_ACTCK_GPIO_EN | PERI_ON_CLK_CTRL_SLPCK_GPIO_EN; // enable gpio peripheral clock + PERI_ON->SOC_PERI_FUNC1_EN |= PERI_ON_SOC_PERI_FUNC1_EN_GPIO; // enable gpio peripheral + + PERI_ON->GPIO_SHTDN_CTRL = 0xFF; + PERI_ON->GPIO_DRIVING_CTRL = 0xFF; + + spi_flash_init(); + + // read jedec info + spi_flash_wait_busy(); + MEM_PARAM = spi_flash_jedec_id(); + spi_flash_wait_busy(); + + while(1){ + MEM_START = 0x00000000; + while(MEM_START == 0x00000000); + if(MEM_COMMAND == COMMAND_READ_ID){ + MEM_PARAM = 0x00000000; + spi_flash_wait_busy(); + MEM_PARAM = spi_flash_jedec_id(); + spi_flash_wait_busy(); + }else if(MEM_COMMAND == COMMAND_MASS_ERASE){ + spi_flash_wait_busy(); + spi_flash_cmd(0x06); + spi_flash_wait_wel(); + spi_flash_cmd(0xC7); + spi_flash_wait_busy(); + spi_flash_cmd(0x04); + spi_flash_wait_busy(); + }else if(MEM_COMMAND == COMMAND_SECTOR_ERASE){ + spi_flash_wait_busy(); + spi_flash_cmd(0x06); + spi_flash_wait_wel(); + spi_flash_sector_erase(MEM_OFFSET); + spi_flash_wait_busy(); + spi_flash_cmd(0x04); + spi_flash_wait_busy(); + }else if(MEM_COMMAND == COMMAND_READ){ + spi_flash_wait_busy(); + p = MEM_OFFSET; + for(i = 0; i < MEM_LEN; i += 16, p += 16){ + spi_flash_read(p, (void *)&MEM_DATA[i], 16); + } + spi_flash_wait_busy(); + }else if(MEM_COMMAND == COMMAND_WRITE){ + for(p = 0; p < MEM_LEN; p += 256){ + spi_flash_wait_busy(); + spi_flash_cmd(0x06); + spi_flash_wait_wel(); + spi_flash_write((MEM_OFFSET + p), (void *)&MEM_DATA[p], 256); + spi_flash_wait_busy(); + spi_flash_cmd(0x04); + spi_flash_wait_busy(); + } + }else if(MEM_COMMAND == COMMAND_VERIFY){ + spi_flash_wait_busy(); + for(p = 0; p < MEM_LEN; p += 16){ + spi_flash_read((MEM_OFFSET + p), read_buffer, 16); + l = MEM_LEN - p; + if(l > 16)l = 16; + for(i = 0; i < l; i++){ + if(read_buffer[i] != MEM_DATA[p + i]){ + break; + } + } + if(i < l){ + MEM_STATUS = 0x00000001; + MEM_PARAM = p; + break; + } + spi_flash_wait_busy(); + } + }else{ + MEM_STATUS = 0x00000001; + } + } +} + diff --git a/rtl8710_flasher.ocd b/rtl8710_flasher.ocd new file mode 100644 index 0000000..9c5365b --- /dev/null +++ b/rtl8710_flasher.ocd @@ -0,0 +1,242 @@ +set rtl8710_flasher_firmware_ptr 0x10001D00 +set rtl8710_flasher_buffer 0x10008000 +set rtl8710_flasher_buffer_size 262144 +set rtl8710_flasher_sector_size 4096 + +set rtl8710_flasher_command_read_id 0 +set rtl8710_flasher_command_mass_erase 1 +set rtl8710_flasher_command_sector_erase 2 +set rtl8710_flasher_command_read 3 +set rtl8710_flasher_command_write 4 +set rtl8710_flasher_command_verify 5 + +set rtl8710_flasher_ready 0 +set rtl8710_flasher_capacity 0 +set rtl8710_flasher_auto_erase 0 +set rtl8710_flasher_auto_verify 0 +set rtl8710_flasher_auto_erase_sector 0xFFFFFFFF + +proc rtl8710_flasher_init {} { + global rtl8710_flasher_firmware_ptr + global rtl8710_flasher_buffer + global rtl8710_flasher_capacity + global rtl8710_flasher_ready + + if {[expr {$rtl8710_flasher_ready == 0}]} { + echo "initializing RTL8710 SPI programmer" + halt + mww [expr {$rtl8710_flasher_buffer + 0x08}] 0x00000000 + mww [expr {$rtl8710_flasher_buffer + 0x00}] 0x00000001 + array2mem rtl8710_flasher_code 32 $rtl8710_flasher_firmware_ptr + reg faultmask 0x01 + reg sp 0x20000000 + reg pc $rtl8710_flasher_firmware_ptr + resume + rtl8710_flasher_wait + set id [rtl8710_flasher_mrw [expr {$rtl8710_flasher_buffer + 0x0C}]] + set rtl8710_flasher_capacity [expr {2 ** [expr {($id >> 16) & 0xFF}]}] + set rtl8710_flasher_ready 1 + } + return "" +} + +proc rtl8710_flasher_mrw {reg} { + set value "" + mem2array value 32 $reg 1 + return $value(0) +} + +proc rtl8710_flasher_wait {} { + global rtl8710_flasher_buffer + while {[rtl8710_flasher_mrw [expr {$rtl8710_flasher_buffer + 0x00}]]} { } +} + +proc rtl8710_flasher_load_block {local_filename offset len} { + global rtl8710_flasher_buffer + load_image $local_filename [expr {$rtl8710_flasher_buffer + 0x20 - $offset}] bin [expr {$rtl8710_flasher_buffer + 0x20}] $len +} + +proc rtl8710_flasher_read_block {offset len} { + global rtl8710_flasher_buffer + global rtl8710_flasher_command_read + mww [expr {$rtl8710_flasher_buffer + 0x04}] $rtl8710_flasher_command_read + mww [expr {$rtl8710_flasher_buffer + 0x08}] 0x00000000 + mww [expr {$rtl8710_flasher_buffer + 0x10}] $offset + mww [expr {$rtl8710_flasher_buffer + 0x14}] $len + mww [expr {$rtl8710_flasher_buffer + 0x00}] 0x00000001 + rtl8710_flasher_wait + set status [rtl8710_flasher_mrw [expr {$rtl8710_flasher_buffer + 0x08}]] + if {[expr {$status > 0}]} { + error "read error, offset $offset" + } + dump_image /tmp/_flasher.bin [expr {$rtl8710_flasher_buffer + 0x20}] $len +} + +proc rtl8710_flasher_write_block {offset len} { + global rtl8710_flasher_buffer + global rtl8710_flasher_command_write + mww [expr {$rtl8710_flasher_buffer + 0x04}] $rtl8710_flasher_command_write + mww [expr {$rtl8710_flasher_buffer + 0x08}] 0x00000000 + mww [expr {$rtl8710_flasher_buffer + 0x10}] $offset + mww [expr {$rtl8710_flasher_buffer + 0x14}] $len + mww [expr {$rtl8710_flasher_buffer + 0x00}] 0x00000001 + rtl8710_flasher_wait + set status [rtl8710_flasher_mrw [expr {$rtl8710_flasher_buffer + 0x08}]] + if {[expr {$status > 0}]} { + error "write error, offset $offset" + } +} + +proc rtl8710_flasher_verify_block {offset len} { + global rtl8710_flasher_buffer + global rtl8710_flasher_command_verify + mww [expr {$rtl8710_flasher_buffer + 0x04}] $rtl8710_flasher_command_verify + mww [expr {$rtl8710_flasher_buffer + 0x08}] 0x00000000 + mww [expr {$rtl8710_flasher_buffer + 0x10}] $offset + mww [expr {$rtl8710_flasher_buffer + 0x14}] $len + mww [expr {$rtl8710_flasher_buffer + 0x00}] 0x00000001 + rtl8710_flasher_wait + set status [rtl8710_flasher_mrw [expr {$rtl8710_flasher_buffer + 0x08}]] + if {[expr {$status > 0}]} { + set status [rtl8710_flasher_mrw [expr {$rtl8710_flasher_buffer + 0x0C}]] + set status [expr {$status + $offset}] + error "verify error, offset $status" + } +} + +proc rtl8710_flasher_read_id {} { + global rtl8710_flasher_buffer + global rtl8710_flasher_capacity + global rtl8710_flasher_command_read_id + mww [expr {$rtl8710_flasher_buffer + 0x04}] $rtl8710_flasher_command_read_id + mww [expr {$rtl8710_flasher_buffer + 0x08}] 0x00000000 + mww [expr {$rtl8710_flasher_buffer + 0x00}] 0x00000001 + rtl8710_flasher_wait + set id [rtl8710_flasher_mrw [expr {$rtl8710_flasher_buffer + 0x0C}]] + set manufacturer_id [format "0x%02X" [expr {$id & 0xFF}]] + set memory_type [format "0x%02X" [expr {($id >> 8) & 0xFF}]] + set memory_capacity [expr {2 ** [expr {($id >> 16) & 0xFF}]}] + echo "manufacturer ID: $manufacturer_id, memory type: $memory_type, memory capacity: $memory_capacity byte(s)" +} + +proc rtl8710_flasher_mass_erase {} { + global rtl8710_flasher_buffer + global rtl8710_flasher_command_mass_erase + mww [expr {$rtl8710_flasher_buffer + 0x04}] $rtl8710_flasher_command_mass_erase + mww [expr {$rtl8710_flasher_buffer + 0x08}] 0x00000000 + mww [expr {$rtl8710_flasher_buffer + 0x00}] 0x00000001 + rtl8710_flasher_wait +} + +proc rtl8710_flasher_sector_erase {offset} { + global rtl8710_flasher_buffer + global rtl8710_flasher_command_sector_erase + mww [expr {$rtl8710_flasher_buffer + 0x04}] $rtl8710_flasher_command_sector_erase + mww [expr {$rtl8710_flasher_buffer + 0x08}] 0x00000000 + mww [expr {$rtl8710_flasher_buffer + 0x10}] $offset + mww [expr {$rtl8710_flasher_buffer + 0x00}] 0x00000001 + rtl8710_flasher_wait +} + +proc rtl8710_flasher_read {local_filename loc size} { + global rtl8710_flasher_buffer_size + for {set offset 0} {$offset < $size} {set offset [expr {$offset + $rtl8710_flasher_buffer_size}]} { + set len [expr {$size - $offset}] + if {[expr {$len > $rtl8710_flasher_buffer_size}]} { + set len $rtl8710_flasher_buffer_size + } + set flash_offset [expr {$loc + $offset}] + echo "read offset $flash_offset" + rtl8710_flasher_read_block $flash_offset $len + exec dd conv=notrunc if=/tmp/_flasher.bin "of=$local_filename" bs=1 "seek=$offset" + } +} + +proc rtl8710_flasher_write {local_filename loc} { + global rtl8710_flasher_buffer_size + global rtl8710_flasher_sector_size + global rtl8710_flasher_auto_erase + global rtl8710_flasher_auto_verify + global rtl8710_flasher_auto_erase_sector + set sector 0 + set size [file size $local_filename] + for {set offset 0} {$offset < $size} {set offset [expr {$offset + $rtl8710_flasher_buffer_size}]} { + set len [expr {$size - $offset}] + if {[expr {$len > $rtl8710_flasher_buffer_size}]} { + set len $rtl8710_flasher_buffer_size + } + set flash_offset [expr {$loc + $offset}] + rtl8710_flasher_load_block $local_filename $offset $len + if {[expr {$rtl8710_flasher_auto_erase != 0}]} { + for {set i $flash_offset} {$i < [expr {$flash_offset + $len}]} {incr i} { + set sector [expr {$i / $rtl8710_flasher_sector_size}] + if {[expr {$rtl8710_flasher_auto_erase_sector != $sector}]} { + echo "erase sector $sector" + rtl8710_flasher_sector_erase [expr {$sector * $rtl8710_flasher_sector_size}] + set rtl8710_flasher_auto_erase_sector $sector + } + } + } + echo "write offset $flash_offset" + rtl8710_flasher_write_block $flash_offset $len + if {[expr {$rtl8710_flasher_auto_verify != 0}]} { + echo "verify offset $flash_offset" + rtl8710_flasher_verify_block $flash_offset $len + } + } +} + +proc rtl8710_flasher_verify {local_filename loc} { + global rtl8710_flasher_buffer_size + set size [file size $local_filename] + for {set offset 0} {$offset < $size} {set offset [expr {$offset + $rtl8710_flasher_buffer_size}]} { + set len [expr {$size - $offset}] + if {[expr {$len > $rtl8710_flasher_buffer_size}]} { + set len $rtl8710_flasher_buffer_size + } + set flash_offset [expr {$loc + $offset}] + rtl8710_flasher_load_block $local_filename $offset $len + echo "verify offset $flash_offset" + rtl8710_flasher_verify_block $flash_offset $len + } +} + +proc rtl8710_auto_erase {on} { + global rtl8710_flasher_auto_erase + if {[expr {$on != 0}]} { + set rtl8710_flasher_auto_erase 1 + echo "auto erase on" + } else { + set rtl8710_flasher_auto_erase 0 + echo "auto erase off" + } +} + +proc rtl8710_auto_verify {on} { + global rtl8710_flasher_auto_verify + if {[expr {$on != 0}]} { + set rtl8710_flasher_auto_verify 1 + echo "auto verify on" + } else { + set rtl8710_flasher_auto_verify 0 + echo "auto verify off" + } +} + +proc rtl8710_mass_erase {} { + echo "mass erase" + rtl8710_flasher_mass_erase +} + +proc rtl8710_flash_read {local_filename loc size} { + rtl8710_flasher_read $local_filename $loc $size +} + +proc rtl8710_flash_write {local_filename loc} { + rtl8710_flasher_write $local_filename $loc +} + +proc rtl8710_reboot {} { + mww 0xE000ED0C 0x05FA0007 +} + diff --git a/spi_flash.c b/spi_flash.c new file mode 100644 index 0000000..00e0990 --- /dev/null +++ b/spi_flash.c @@ -0,0 +1,128 @@ +#include "spi_flash.h" +#include "rtl8710.h" +#include "mask.h" + +static void spi_flash_send(uint8_t byte){ + // while(!(SPI_FLASH->SR & SPI_SR_TFNF)); + SPI_FLASH->DR = byte; +} + +static uint8_t spi_flash_recv(){ + while(!(SPI_FLASH->RXFLR & 0x0FFF)); + return(SPI_FLASH->DR); +} + +void spi_flash_init(){ + PERI_ON->PESOC_CLK_CTRL |= PERI_ON_CLK_CTRL_ACTCK_FLASH_EN | PERI_ON_CLK_CTRL_SLPCK_FLASH_EN; // enable spi flash peripheral clock + PERI_ON->SOC_FUNC_EN |= PERI_ON_SOC_FUNC_EN_FLASH; // enable spi flash peripheral + mask32_set(PERI_ON->CPU_PERIPHERAL_CTRL, PERI_ON_CPU_PERIPHERAL_CTRL_SPI_FLASH_PIN_SEL, 0); // select spi flash pinout (0 - internal) + PERI_ON->CPU_PERIPHERAL_CTRL |= PERI_ON_CPU_PERIPHERAL_CTRL_SPI_FLASH_PIN_EN; // enable spi flash pins + + SPI_FLASH->SSIENR = 0; // disable SPI FLASH operation + SPI_FLASH->IMR = 0; // disable all interrupts + SPI_FLASH->SER = SPI_SER_SS0; // use first "slave select" pin + SPI_FLASH->BAUDR = 2; // baud rate, default value + SPI_FLASH->TXFTLR = 0; // tx fifo threshold + SPI_FLASH->RXFTLR = 0; // rx fifo threshold + SPI_FLASH->DMACR = 0; // disable DMA +} + +uint16_t spi_flash_read(uint32_t address, void *buf, uint16_t count){ + uint16_t i; + if(!count)return(0); + if(count > 16)count = 16; + SPI_FLASH->CTRLR0 = mask32(SPI_CTRLR0_TMOD, 3) | mask32(SPI_CTRLR0_CMD_CH, 0) | mask32(SPI_CTRLR0_ADDR_CH, 0) | mask32(SPI_CTRLR0_DATA_CH, 0); + SPI_FLASH->CTRLR1 = count; + + spi_flash_send(0x03); // flash command "read" + spi_flash_send((address >> 16) & 0xFF); // address * 3 + spi_flash_send((address >> 8) & 0xFF); + spi_flash_send((address >> 0) & 0xFF); + + SPI_FLASH->SSIENR = 1; + + for(i = 0; i < count; i++){ + ((uint8_t *)buf)[i] = spi_flash_recv(); + } + while(SPI_FLASH->SR & SPI_SR_SSI); + SPI_FLASH->SSIENR = 0; + return(count); +} + +uint32_t spi_flash_jedec_id(){ + uint32_t id; + SPI_FLASH->CTRLR0 = mask32(SPI_CTRLR0_TMOD, 3) | mask32(SPI_CTRLR0_CMD_CH, 0) | mask32(SPI_CTRLR0_ADDR_CH, 0) | mask32(SPI_CTRLR0_DATA_CH, 0); + SPI_FLASH->CTRLR1 = 3; + + SPI_FLASH->SSIENR = 1; + spi_flash_send(0x9F); // jedec id + id = spi_flash_recv(); + id |= ((uint32_t)spi_flash_recv() << 8); + id |= ((uint32_t)spi_flash_recv() << 16); + while(SPI_FLASH->SR & SPI_SR_SSI); + SPI_FLASH->SSIENR = 0; + return(id); +} + +uint8_t spi_flash_status(){ + uint8_t status; + SPI_FLASH->CTRLR0 = mask32(SPI_CTRLR0_TMOD, 3) | mask32(SPI_CTRLR0_CMD_CH, 0) | mask32(SPI_CTRLR0_ADDR_CH, 0) | mask32(SPI_CTRLR0_DATA_CH, 0); + SPI_FLASH->CTRLR1 = 1; + + SPI_FLASH->SSIENR = 1; + spi_flash_send(0x05); // read status + status = spi_flash_recv(); + while(SPI_FLASH->SR & SPI_SR_SSI); + SPI_FLASH->SSIENR = 0; + return(status); +} + +void spi_flash_cmd(uint8_t cmd){ + SPI_FLASH->CTRLR0 = mask32(SPI_CTRLR0_TMOD, 1) | mask32(SPI_CTRLR0_CMD_CH, 0) | mask32(SPI_CTRLR0_ADDR_CH, 0) | mask32(SPI_CTRLR0_DATA_CH, 0); + + SPI_FLASH->SSIENR = 1; + spi_flash_send(cmd); + while(SPI_FLASH->SR & SPI_SR_SSI); + SPI_FLASH->SSIENR = 0; +} + +void spi_flash_sector_erase(uint32_t address){ + SPI_FLASH->CTRLR0 = mask32(SPI_CTRLR0_TMOD, 1) | mask32(SPI_CTRLR0_CMD_CH, 0) | mask32(SPI_CTRLR0_ADDR_CH, 0) | mask32(SPI_CTRLR0_DATA_CH, 0); + + SPI_FLASH->SSIENR = 1; + spi_flash_send(0x20); // sector erase + spi_flash_send((address >> 16) & 0xFF); + spi_flash_send((address >> 8) & 0xFF); + spi_flash_send((address >> 0) & 0xFF); + while(SPI_FLASH->SR & SPI_SR_SSI); + SPI_FLASH->SSIENR = 0; +} + +uint16_t spi_flash_write(uint32_t address, const void *buf, uint16_t count){ + uint16_t i; + if(!count)return(0); + if(count > 256)count = 256; + SPI_FLASH->CTRLR0 = mask32(SPI_CTRLR0_TMOD, 1) | mask32(SPI_CTRLR0_CMD_CH, 0) | mask32(SPI_CTRLR0_ADDR_CH, 0) | mask32(SPI_CTRLR0_DATA_CH, 0); + + SPI_FLASH->SSIENR = 1; + spi_flash_send(0x02); // write + spi_flash_send((address >> 16) & 0xFF); + spi_flash_send((address >> 8) & 0xFF); + spi_flash_send((address >> 0) & 0xFF); + for(i = 0; i < count; i++){ + spi_flash_send(((uint8_t *)buf)[i]); + } + while(!(SPI_FLASH->SR & SPI_SR_TFE)); + while(SPI_FLASH->SR & SPI_SR_SSI); + SPI_FLASH->SSIENR = 0; + return(count); +} + +void spi_flash_wait_busy(){ + while(spi_flash_status() & 0x01); +} + +void spi_flash_wait_wel(){ + while(!(spi_flash_status() & 0x02)); +} + diff --git a/spi_flash.h b/spi_flash.h new file mode 100644 index 0000000..07f0420 --- /dev/null +++ b/spi_flash.h @@ -0,0 +1,17 @@ +#ifndef _SPI_FLASH_H_ +#define _SPI_FLASH_H_ + +#include + +void spi_flash_init(); +uint16_t spi_flash_read(uint32_t address, void *buf, uint16_t count); +uint16_t spi_flash_write(uint32_t address, const void *buf, uint16_t count); +uint32_t spi_flash_jedec_id(); +uint8_t spi_flash_status(); +void spi_flash_cmd(uint8_t cmd); +void spi_flash_sector_erase(uint32_t address); +void spi_flash_wait_busy(); +void spi_flash_wait_wel(); + +#endif +