diff options
-rw-r--r-- | Makefile.fpc | 3 | ||||
-rw-r--r-- | compiler/Makefile.fpc | 14 | ||||
-rw-r--r-- | compiler/utils/fpc.pp | 6 | ||||
-rw-r--r-- | rtl/embedded/Makefile.fpc | 9 | ||||
-rw-r--r-- | rtl/embedded/xtensa/esp8266.pp | 254 |
5 files changed, 282 insertions, 4 deletions
diff --git a/Makefile.fpc b/Makefile.fpc index dcc814d0f0..2a2c512582 100644 --- a/Makefile.fpc +++ b/Makefile.fpc @@ -91,6 +91,9 @@ endif ifeq ($(CPU_TARGET),riscv64) PPSUF=rv64 endif +ifeq ($(CPU_TARGET),xtensa) +PPSUF=xtensa +endif # cross compilers uses full cpu_target, not just ppc-suffix # (except if the target cannot run a native compiler) diff --git a/compiler/Makefile.fpc b/compiler/Makefile.fpc index 813764f2e1..38e2f00d57 100644 --- a/compiler/Makefile.fpc +++ b/compiler/Makefile.fpc @@ -32,7 +32,7 @@ fpcdir=.. unexport FPC_VERSION FPC_COMPILERINFO # Which platforms are ready for inclusion in the cycle -CYCLETARGETS=i386 powerpc sparc arm x86_64 powerpc64 m68k armeb mipsel mips avr jvm i8086 aarch64 sparc64 riscv32 riscv64 +CYCLETARGETS=i386 powerpc sparc arm x86_64 powerpc64 m68k armeb mipsel mips avr jvm i8086 aarch64 sparc64 riscv32 riscv64 xtensa # All supported targets used for clean ALLTARGETS=$(CYCLETARGETS) @@ -89,6 +89,9 @@ endif ifdef RISCV64 PPC_TARGET=riscv64 endif +ifdef XTENSA +PPC_TARGET=xtensa +endif # Default is to generate a compiler for the same # platform as CPU_TARGET (a native compiler) @@ -224,6 +227,9 @@ endif ifeq ($(CPC_TARGET),riscv64) CPUSUF=rv64 endif +ifeq ($(CPC_TARGET),xtensa) +CPUSUF=xtensa +endif # Do not define the default -d$(CPU_TARGET) because that # will conflict with our -d$(CPC_TARGET) @@ -585,8 +591,8 @@ endif # cpu targets ##################################################################### -PPC_TARGETS=i386 m68k powerpc sparc arm armeb x86_64 powerpc64 mips mipsel avr jvm i8086 aarch64 sparc64 riscv32 riscv64 -PPC_SUFFIXES=386 68k ppc sparc arm armeb x64 ppc64 mips mipsel avr jvm 8086 a64 sparc64 rv32 rv64 +PPC_TARGETS=i386 m68k powerpc sparc arm armeb x86_64 powerpc64 mips mipsel avr jvm i8086 aarch64 sparc64 riscv32 riscv64 xtensa +PPC_SUFFIXES=386 68k ppc sparc arm armeb x64 ppc64 mips mipsel avr jvm 8086 a64 sparc64 rv32 rv64 xtensa INSTALL_TARGETS=$(addsuffix _exe_install,$(sort $(CYCLETARGETS) $(PPC_TARGETS))) SYMLINKINSTALL_TARGETS=$(addsuffix _symlink_install,$(sort $(CYCLETARGETS) $(PPC_TARGETS))) @@ -984,7 +990,7 @@ ifeq ($(OS_SOURCE),win64) EXCLUDE_80BIT_TARGETS=1 endif -ifneq ($(findstring $(CPU_SOURCE),aarch64 arm avr jvm m68k mips mipsel powerpc powerpc64 sparc sparc64 riscv32 riscv64),) +ifneq ($(findstring $(CPU_SOURCE),aarch64 arm avr jvm m68k mips mipsel powerpc powerpc64 sparc sparc64 riscv32 riscv64 xtensa),) EXCLUDE_80BIT_TARGETS=1 endif diff --git a/compiler/utils/fpc.pp b/compiler/utils/fpc.pp index 7465bedf99..06cfa13111 100644 --- a/compiler/utils/fpc.pp +++ b/compiler/utils/fpc.pp @@ -180,6 +180,10 @@ program fpc; ppcbin:='ppcrv64'; processorname:='riscv64'; {$endif riscv64} +{$ifdef xtensa} + ppcbin:='ppcxtensa'; + processorname:='xtensa'; +{$endif xtensa} versionstr:=''; { Default is just the name } if ParamCount = 0 then begin @@ -263,6 +267,8 @@ program fpc; cpusuffix:='sparc64' else if processorstr='x86_64' then cpusuffix:='x64' + else if processorstr='xtensa' then + cpusuffix:='xtensa' else error('Illegal processor type "'+processorstr+'"'); diff --git a/rtl/embedded/Makefile.fpc b/rtl/embedded/Makefile.fpc index cb55006786..0566231c3c 100644 --- a/rtl/embedded/Makefile.fpc +++ b/rtl/embedded/Makefile.fpc @@ -221,6 +221,15 @@ $(error No CPUs enabled for given SUBARCH, pass either a SUBARCH or set CPU_UNIT endif endif +ifeq ($(ARCH),xtensa) +CPU_SPECIFIC_COMMON_UNITS=sysutils math classes fgl macpas typinfo types rtlconsts getopts lineinfo +CPU_UNITS=esp8266 +CPU_UNITS_DEFINED=1 +ifeq ($(CPU_UNITS_DEFINED),) +$(error No CPUs enabled for given SUBARCH, pass either a SUBARCH or set CPU_UNITS_DEFINED=1 if you know what you are doing) +endif +endif + # Paths OBJPASDIR=$(RTL)/objpas GRAPHDIR=$(INC)/graph diff --git a/rtl/embedded/xtensa/esp8266.pp b/rtl/embedded/xtensa/esp8266.pp new file mode 100644 index 0000000000..00706d843f --- /dev/null +++ b/rtl/embedded/xtensa/esp8266.pp @@ -0,0 +1,254 @@ +unit esp8266; + +interface + +const + //unit: Hz + APB_CLK_FREQ = 80*1000000; + UART_CLK_FREQ = APB_CLK_FREQ; + //divided by 256 + TIMER_CLK_FREQ = (APB_CLK_FREQ shr 8); + + //Peripheral device base address + PERIPHS_DPORT_BASEADDR = $3ff00000; + PERIPHS_GPIO_BASEADDR = $60000300; + PERIPHS_TIMER_BASEDDR = $60000600; + PERIPHS_RTC_BASEADDR = $60000700; + PERIPHS_IO_MUX = $60000800; + + //Interrupt remap control registers + EDGE_INT_ENABLE_REG = (PERIPHS_DPORT_BASEADDR+$04); + // TM1_EDGE_INT_ENABLE() = SET_PERI_REG_MASK(EDGE_INT_ENABLE_REG, BIT1); + // TM1_EDGE_INT_DISABLE() = CLEAR_PERI_REG_MASK(EDGE_INT_ENABLE_REG, BIT1); + + //GPIO reg + // GPIO_REG_READ(reg) = READ_PERI_REG(PERIPHS_GPIO_BASEADDR + reg); + // GPIO_REG_WRITE(reg, val) = WRITE_PERI_REG(PERIPHS_GPIO_BASEADDR + reg, val); + GPIO_OUT_ADDRESS = $00; + GPIO_OUT_W1TS_ADDRESS = $04; + GPIO_OUT_W1TC_ADDRESS = $08; + + GPIO_ENABLE_ADDRESS = $0c; + GPIO_ENABLE_W1TS_ADDRESS = $10; + GPIO_ENABLE_W1TC_ADDRESS = $14; + GPIO_OUT_W1TC_DATA_MASK = $0000ffff; + + GPIO_IN_ADDRESS = $18; + + GPIO_STATUS_ADDRESS = $1c; + GPIO_STATUS_W1TS_ADDRESS = $20; + GPIO_STATUS_W1TC_ADDRESS = $24; + GPIO_STATUS_INTERRUPT_MASK = $0000ffff; + + GPIO_RTC_CALIB_SYNC = PERIPHS_GPIO_BASEADDR+$6c; + //first write to zero, then to one to start + RTC_CALIB_START = BIT31; + //max 8ms + RTC_PERIOD_NUM_MASK = $3ff; + GPIO_RTC_CALIB_VALUE = PERIPHS_GPIO_BASEADDR+$70; + //after measure, flag to one, when start from zero to one, turn to zero + RTC_CALIB_RDY_S = 31; + RTC_CALIB_VALUE_MASK = $fffff; + + GPIO_PIN0_ADDRESS = $28; + + GPIO_ID_PIN0 = 0; + // GPIO_ID_PIN(n) = (GPIO_ID_PIN0+(n)); + GPIO_LAST_REGISTER_ID = 15; + GPIO_ID_NONE = $ffffffff; + + GPIO_PIN_COUNT = 16; + + GPIO_PIN_CONFIG_MSB = 12; + GPIO_PIN_CONFIG_LSB = 11; + GPIO_PIN_CONFIG_MASK = $00001800; + // GPIO_PIN_CONFIG_GET(x) = (((x) and GPIO_PIN_CONFIG_MASK) shr GPIO_PIN_CONFIG_LSB); + // GPIO_PIN_CONFIG_SET(x) = (((x) shl GPIO_PIN_CONFIG_LSB) and GPIO_PIN_CONFIG_MASK); + + GPIO_WAKEUP_ENABLE = 1; + GPIO_WAKEUP_DISABLE = (not GPIO_WAKEUP_ENABLE); + GPIO_PIN_WAKEUP_ENABLE_MSB = 10; + GPIO_PIN_WAKEUP_ENABLE_LSB = 10; + GPIO_PIN_WAKEUP_ENABLE_MASK = $00000400; + // GPIO_PIN_WAKEUP_ENABLE_GET(x) = (((x) and GPIO_PIN_WAKEUP_ENABLE_MASK) shr GPIO_PIN_WAKEUP_ENABLE_LSB); + // GPIO_PIN_WAKEUP_ENABLE_SET(x) = (((x) shl GPIO_PIN_WAKEUP_ENABLE_LSB) and GPIO_PIN_WAKEUP_ENABLE_MASK); + + GPIO_PIN_INT_TYPE_MASK = $380; + GPIO_PIN_INT_TYPE_MSB = 9; + GPIO_PIN_INT_TYPE_LSB = 7; + // GPIO_PIN_INT_TYPE_GET(x) = (((x) and GPIO_PIN_INT_TYPE_MASK) shr GPIO_PIN_INT_TYPE_LSB); + // GPIO_PIN_INT_TYPE_SET(x) = (((x) shl GPIO_PIN_INT_TYPE_LSB) and GPIO_PIN_INT_TYPE_MASK); + + GPIO_PAD_DRIVER_ENABLE = 1; + GPIO_PAD_DRIVER_DISABLE = (not GPIO_PAD_DRIVER_ENABLE); + GPIO_PIN_PAD_DRIVER_MSB = 2; + GPIO_PIN_PAD_DRIVER_LSB = 2; + GPIO_PIN_PAD_DRIVER_MASK = $00000004; + // GPIO_PIN_PAD_DRIVER_GET(x) = (((x) and GPIO_PIN_PAD_DRIVER_MASK) shr GPIO_PIN_PAD_DRIVER_LSB); + // GPIO_PIN_PAD_DRIVER_SET(x) = (((x) shl GPIO_PIN_PAD_DRIVER_LSB) and GPIO_PIN_PAD_DRIVER_MASK); + + GPIO_AS_PIN_SOURCE = 0; + SIGMA_AS_PIN_SOURCE = (not GPIO_AS_PIN_SOURCE); + GPIO_PIN_SOURCE_MSB = 0; + GPIO_PIN_SOURCE_LSB = 0; + GPIO_PIN_SOURCE_MASK = $00000001; + // GPIO_PIN_SOURCE_GET(x) = (((x) and GPIO_PIN_SOURCE_MASK) shr GPIO_PIN_SOURCE_LSB); + // GPIO_PIN_SOURCE_SET(x) = (((x) shl GPIO_PIN_SOURCE_LSB) and GPIO_PIN_SOURCE_MASK); + + // TIMER reg + // RTC_REG_READ(addr) = READ_PERI_REG(PERIPHS_TIMER_BASEDDR + addr); + // RTC_REG_WRITE(addr, val) = WRITE_PERI_REG(PERIPHS_TIMER_BASEDDR + addr, val); + // RTC_CLR_REG_MASK(reg, mask) = CLEAR_PERI_REG_MASK(PERIPHS_TIMER_BASEDDR +reg, mask); + // Returns the current time according to the timer timer. + // NOW() = RTC_REG_READ(FRC2_COUNT_ADDRESS); + + //load initial_value to timer1 + FRC1_LOAD_ADDRESS = $00; + + //timer1's counter value(count from initial_value to 0) + FRC1_COUNT_ADDRESS = $04; + + FRC1_CTRL_ADDRESS = $08; + + //clear timer1's interrupt when write this address + FRC1_INT_ADDRESS = $0c; + FRC1_INT_CLR_MASK = $00000001; + + //timer2's counter value(count from initial_value to 0) + FRC2_COUNT_ADDRESS = $24; + + //RTC reg + REG_RTC_BASE = PERIPHS_RTC_BASEADDR; + + RTC_STORE0 = (REG_RTC_BASE + $030); + RTC_STORE1 = (REG_RTC_BASE + $034); + RTC_STORE2 = (REG_RTC_BASE + $038); + RTC_STORE3 = (REG_RTC_BASE + $03C); + + RTC_GPIO_OUT = (REG_RTC_BASE + $068); + RTC_GPIO_ENABLE = (REG_RTC_BASE + $074); + RTC_GPIO_IN_DATA = (REG_RTC_BASE + $08C); + RTC_GPIO_CONF = (REG_RTC_BASE + $090); + PAD_XPD_DCDC_CONF = (REG_RTC_BASE + $0A0); + + //PIN Mux reg + PERIPHS_IO_MUX_FUNC = $13; + PERIPHS_IO_MUX_FUNC_S = 4; + PERIPHS_IO_MUX_PULLUP = BIT7; + PERIPHS_IO_MUX_PULLUP2 = BIT6; + PERIPHS_IO_MUX_SLEEP_PULLUP = BIT3; + PERIPHS_IO_MUX_SLEEP_PULLUP2 = BIT2; + PERIPHS_IO_MUX_SLEEP_OE = BIT1; + PERIPHS_IO_MUX_OE = BIT0; + + PERIPHS_IO_MUX_CONF_U = (PERIPHS_IO_MUX + $00); + SPI0_CLK_EQU_SYS_CLK = BIT8; + SPI1_CLK_EQU_SYS_CLK = BIT9; + PERIPHS_IO_MUX_MTDI_U = (PERIPHS_IO_MUX + $04); + FUNC_GPIO12 = 3; + PERIPHS_IO_MUX_MTCK_U = (PERIPHS_IO_MUX + $08); + FUNC_GPIO13 = 3; + PERIPHS_IO_MUX_MTMS_U = (PERIPHS_IO_MUX + $0C); + FUNC_GPIO14 = 3; + PERIPHS_IO_MUX_MTDO_U = (PERIPHS_IO_MUX + $10); + FUNC_GPIO15 = 3; + FUNC_U0RTS = 4; + PERIPHS_IO_MUX_U0RXD_U = (PERIPHS_IO_MUX + $14); + FUNC_GPIO3 = 3; + PERIPHS_IO_MUX_U0TXD_U = (PERIPHS_IO_MUX + $18); + FUNC_U0TXD = 0; + FUNC_GPIO1 = 3; + PERIPHS_IO_MUX_SD_CLK_U = (PERIPHS_IO_MUX + $1c); + FUNC_SDCLK = 0; + FUNC_SPICLK = 1; + PERIPHS_IO_MUX_SD_DATA0_U = (PERIPHS_IO_MUX + $20); + FUNC_SDDATA0 = 0; + FUNC_SPIQ = 1; + FUNC_U1TXD = 4; + PERIPHS_IO_MUX_SD_DATA1_U = (PERIPHS_IO_MUX + $24); + FUNC_SDDATA1 = 0; + FUNC_SPID = 1; + FUNC_U1RXD = 4; + FUNC_SDDATA1_U1RXD = 7; + PERIPHS_IO_MUX_SD_DATA2_U = (PERIPHS_IO_MUX + $28); + FUNC_SDDATA2 = 0; + FUNC_SPIHD = 1; + FUNC_GPIO9 = 3; + PERIPHS_IO_MUX_SD_DATA3_U = (PERIPHS_IO_MUX + $2c); + FUNC_SDDATA3 = 0; + FUNC_SPIWP = 1; + FUNC_GPIO10 = 3; + PERIPHS_IO_MUX_SD_CMD_U = (PERIPHS_IO_MUX + $30); + FUNC_SDCMD = 0; + FUNC_SPICS0 = 1; + PERIPHS_IO_MUX_GPIO0_U = (PERIPHS_IO_MUX + $34); + FUNC_GPIO0 = 0; + PERIPHS_IO_MUX_GPIO2_U = (PERIPHS_IO_MUX + $38); + FUNC_GPIO2 = 0; + FUNC_U1TXD_BK = 2; + FUNC_U0TXD_BK = 4; + PERIPHS_IO_MUX_GPIO4_U = (PERIPHS_IO_MUX + $3C); + FUNC_GPIO4 = 0; + PERIPHS_IO_MUX_GPIO5_U = (PERIPHS_IO_MUX + $40); + FUNC_GPIO5 = 0; + + // PIN_PULLUP_DIS(PIN_NAME) = CLEAR_PERI_REG_MASK(PIN_NAME, PERIPHS_IO_MUX_PULLUP); + // PIN_PULLUP_EN(PIN_NAME) = SET_PERI_REG_MASK(PIN_NAME, PERIPHS_IO_MUX_PULLUP); + +implementation + +var + _stack_top: record end; external name '_stack_top'; + _data: record end; external name '_data'; + _edata: record end; external name '_edata'; + _text_start: record end; external name '_text_start'; + _etext: record end; external name '_etext'; + _bss_start: record end; external name '_bss_start'; + _bss_end: record end; external name '_bss_end'; + +procedure Pascalmain; external name 'PASCALMAIN'; + +procedure HaltProc; assembler; nostackframe; public name'_haltproc'; +asm +.Lloop: + b .Lloop +end; + +procedure Startup; +var + psrc,pdst,pend: plongword; +begin + // Copy .text + psrc:=@_etext; + pdst:=@_data; + pend:=@_edata; + while pdst<pend do + begin + pdst^:=psrc^; + inc(pdst); + inc(psrc); + end; + + // Clear .bss + pend:=@_bss_end; + while pdst<pend do + begin + pdst^:=0; + inc(pdst); + end; + + PascalMain; + Haltproc; +end; + +procedure LowLevelStartup; assembler; nostackframe; +asm + l32r a1, .Lstack_ptr + + j Startup + +.Lstack_ptr: + .long _stack_top +end; + +end. |