diff --git a/Makefile b/Makefile index 3ea259fe..5b3cb8f5 100644 --- a/Makefile +++ b/Makefile @@ -297,6 +297,8 @@ smoketest: @$(MD5SUM) test.hex $(TINYGO) build -size short -o test.hex -target=pinetime-devkit0 examples/blinky1 @$(MD5SUM) test.hex + $(TINYGO) build -size short -o test.hex -target=lgt92 examples/blinky1 + @$(MD5SUM) test.hex $(TINYGO) build -size short -o test.hex -target=x9pro examples/blinky1 @$(MD5SUM) test.hex $(TINYGO) build -size short -o test.hex -target=pca10056-s140v7 examples/blinky1 diff --git a/src/machine/board_lgt92.go b/src/machine/board_lgt92.go new file mode 100644 index 00000000..ed2e6b5e --- /dev/null +++ b/src/machine/board_lgt92.go @@ -0,0 +1,80 @@ +// +build lgt92 + +package machine + +import ( + "device/stm32" + "runtime/interrupt" +) + +const ( + LED1 = PA12 + LED2 = PA8 + LED3 = PA11 + + LED_RED = LED1 + LED_BLUE = LED2 + LED_GREEN = LED3 + + // Default led + LED = LED1 + + BUTTON = PB14 + + // LG GPS module + GPS_STANDBY_PIN = PB3 + GPS_RESET_PIN = PB4 + GPS_POWER_PIN = PB5 + + MEMS_ACCEL_CS = PE3 + MEMS_ACCEL_INT1 = PE0 + MEMS_ACCEL_INT2 = PE1 + + // SPI + SPI1_SCK_PIN = PA5 + SPI1_SDI_PIN = PA6 + SPI1_SDO_PIN = PA7 + SPI0_SCK_PIN = SPI1_SCK_PIN + SPI0_SDI_PIN = SPI1_SDI_PIN + SPI0_SDO_PIN = SPI1_SDO_PIN + + // LORA RFM95 Radio + RFM95_DIO0_PIN = PC13 + + //TinyGo UART is MCU LPUSART1 + UART_RX_PIN = PA13 + UART_TX_PIN = PA14 + + //TinyGo UART1 is MCU USART1 + UART1_RX_PIN = PB6 + UART1_TX_PIN = PB7 +) + +var ( + + // Console UART (LPUSART1) + UART0 = UART{ + Buffer: NewRingBuffer(), + Bus: stm32.LPUSART1, + AltFuncSelector: 6, + } + + // Gps UART + UART1 = UART{ + Buffer: NewRingBuffer(), + Bus: stm32.USART1, + AltFuncSelector: 0, + } + + // SPI + SPI0 = SPI{ + Bus: stm32.SPI1, + } + SPI1 = &SPI0 +) + +func init() { + // Enable UARTs Interrupts + UART0.Interrupt = interrupt.New(stm32.IRQ_AES_RNG_LPUART1, UART0.handleInterrupt) + UART1.Interrupt = interrupt.New(stm32.IRQ_USART1, UART1.handleInterrupt) +} diff --git a/src/machine/i2c.go b/src/machine/i2c.go index 9a461d02..aa804f6b 100644 --- a/src/machine/i2c.go +++ b/src/machine/i2c.go @@ -1,4 +1,4 @@ -// +build avr nrf sam stm32,!stm32f407,!stm32f7x2 fe310 k210 +// +build avr nrf sam stm32,!stm32f407,!stm32f7x2,!stm32l0 fe310 k210 package machine diff --git a/src/machine/machine_stm32_i2c.go b/src/machine/machine_stm32_i2c.go index 899e55a7..b502582e 100644 --- a/src/machine/machine_stm32_i2c.go +++ b/src/machine/machine_stm32_i2c.go @@ -1,4 +1,4 @@ -// +build stm32,!stm32f103xx,!stm32f407,!stm32f7x2 +// +build stm32,!stm32f103xx,!stm32f407,!stm32f7x2,!stm32l0 package machine diff --git a/src/machine/machine_stm32_uart.go b/src/machine/machine_stm32_uart.go index 9d2bab9c..e4fa4708 100644 --- a/src/machine/machine_stm32_uart.go +++ b/src/machine/machine_stm32_uart.go @@ -1,4 +1,4 @@ -// +build stm32,!stm32f7 +// +build stm32,!stm32f7,!stm32l0 package machine diff --git a/src/machine/machine_stm32l0.go b/src/machine/machine_stm32l0.go new file mode 100644 index 00000000..115e0ec4 --- /dev/null +++ b/src/machine/machine_stm32l0.go @@ -0,0 +1,288 @@ +// +build stm32l0 + +package machine + +// Peripheral abstraction layer for the stm32l0 + +import ( + "device/stm32" + "runtime/interrupt" + "unsafe" +) + +func CPUFrequency() uint32 { + return 32000000 +} + +const ( + PA0 = portA + 0 + PA1 = portA + 1 + PA2 = portA + 2 + PA3 = portA + 3 + PA4 = portA + 4 + PA5 = portA + 5 + PA6 = portA + 6 + PA7 = portA + 7 + PA8 = portA + 8 + PA9 = portA + 9 + PA10 = portA + 10 + PA11 = portA + 11 + PA12 = portA + 12 + PA13 = portA + 13 + PA14 = portA + 14 + PA15 = portA + 15 + + PB0 = portB + 0 + PB1 = portB + 1 + PB2 = portB + 2 + PB3 = portB + 3 + PB4 = portB + 4 + PB5 = portB + 5 + PB6 = portB + 6 + PB7 = portB + 7 + PB8 = portB + 8 + PB9 = portB + 9 + PB10 = portB + 10 + PB11 = portB + 11 + PB12 = portB + 12 + PB13 = portB + 13 + PB14 = portB + 14 + PB15 = portB + 15 + + PC0 = portC + 0 + PC1 = portC + 1 + PC2 = portC + 2 + PC3 = portC + 3 + PC4 = portC + 4 + PC5 = portC + 5 + PC6 = portC + 6 + PC7 = portC + 7 + PC8 = portC + 8 + PC9 = portC + 9 + PC10 = portC + 10 + PC11 = portC + 11 + PC12 = portC + 12 + PC13 = portC + 13 + PC14 = portC + 14 + PC15 = portC + 15 + + PD0 = portD + 0 + PD1 = portD + 1 + PD2 = portD + 2 + PD3 = portD + 3 + PD4 = portD + 4 + PD5 = portD + 5 + PD6 = portD + 6 + PD7 = portD + 7 + PD8 = portD + 8 + PD9 = portD + 9 + PD10 = portD + 10 + PD11 = portD + 11 + PD12 = portD + 12 + PD13 = portD + 13 + PD14 = portD + 14 + PD15 = portD + 15 + + PE0 = portE + 0 + PE1 = portE + 1 + PE2 = portE + 2 + PE3 = portE + 3 + PE4 = portE + 4 + PE5 = portE + 5 + PE6 = portE + 6 + PE7 = portE + 7 + PE8 = portE + 8 + PE9 = portE + 9 + PE10 = portE + 10 + PE11 = portE + 11 + PE12 = portE + 12 + PE13 = portE + 13 + PE14 = portE + 14 + PE15 = portE + 15 + + PH0 = portH + 0 + PH1 = portH + 1 +) + +func (p Pin) getPort() *stm32.GPIO_Type { + switch p / 16 { + case 0: + return stm32.GPIOA + case 1: + return stm32.GPIOB + case 2: + return stm32.GPIOC + case 3: + return stm32.GPIOD + case 4: + return stm32.GPIOE + case 7: + return stm32.GPIOH + default: + panic("machine: unknown port") + } +} + +// enableClock enables the clock for this desired GPIO port. +func (p Pin) enableClock() { + switch p / 16 { + case 0: + stm32.RCC.IOPENR.SetBits(stm32.RCC_IOPENR_IOPAEN) + case 1: + stm32.RCC.IOPENR.SetBits(stm32.RCC_IOPENR_IOPBEN) + case 2: + stm32.RCC.IOPENR.SetBits(stm32.RCC_IOPENR_IOPCEN) + case 3: + stm32.RCC.IOPENR.SetBits(stm32.RCC_IOPENR_IOPDEN) + case 4: + stm32.RCC.IOPENR.SetBits(stm32.RCC_IOPENR_IOPEEN) + case 7: + stm32.RCC.IOPENR.SetBits(stm32.RCC_IOPENR_IOPHEN) + default: + panic("machine: unknown port") + } +} + +// Enable peripheral clock +func enableAltFuncClock(bus unsafe.Pointer) { + switch bus { + case unsafe.Pointer(stm32.DAC): // DAC interface clock enable + stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_DACEN) + case unsafe.Pointer(stm32.PWR): // Power interface clock enable + stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_PWREN) + case unsafe.Pointer(stm32.I2C3): // I2C3 clock enable + stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_I2C3EN) + case unsafe.Pointer(stm32.I2C2): // I2C2 clock enable + stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_I2C2EN) + case unsafe.Pointer(stm32.I2C1): // I2C1 clock enable + stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_I2C1EN) + case unsafe.Pointer(stm32.USART5): // UART5 clock enable + stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_USART5EN) + case unsafe.Pointer(stm32.USART4): // UART4 clock enable + stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_USART4EN) + case unsafe.Pointer(stm32.USART2): // USART2 clock enable + stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_USART2EN) + case unsafe.Pointer(stm32.SPI2): // SPI2 clock enable + stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_SPI2EN) + case unsafe.Pointer(stm32.LPUSART1): // LPUSART1 clock enable + stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_LPUART1EN) + case unsafe.Pointer(stm32.WWDG): // Window watchdog clock enable + stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_WWDGEN) + case unsafe.Pointer(stm32.TIM7): // TIM7 clock enable + stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM7EN) + case unsafe.Pointer(stm32.TIM6): // TIM6 clock enable + stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM6EN) + case unsafe.Pointer(stm32.TIM3): // TIM3 clock enable + stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM3EN) + case unsafe.Pointer(stm32.TIM2): // TIM2 clock enable + stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM2EN) + case unsafe.Pointer(stm32.SYSCFG_COMP): // System configuration controller clock enable + stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_SYSCFGEN) + case unsafe.Pointer(stm32.SPI1): // SPI1 clock enable + stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_SPI1EN) + case unsafe.Pointer(stm32.ADC): // ADC clock enable + stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_ADCEN) + case unsafe.Pointer(stm32.USART1): // USART1 clock enable + stm32.RCC.APB2ENR.SetBits(stm32.RCC_APB2ENR_USART1EN) + } +} + +//---------- UART related types and code + +// UART representation +type UART struct { + Buffer *RingBuffer + Bus *stm32.USART_Type + Interrupt interrupt.Interrupt + AltFuncSelector stm32.AltFunc +} + +// Configure the UART. +func (uart UART) configurePins(config UARTConfig) { + // enable the alternate functions on the TX and RX pins + config.TX.ConfigureAltFunc(PinConfig{Mode: PinModeUARTTX}, uart.AltFuncSelector) + config.RX.ConfigureAltFunc(PinConfig{Mode: PinModeUARTRX}, uart.AltFuncSelector) +} + +// UART baudrate calc based on the bus and clockspeed +func (uart UART) getBaudRateDivisor(baudRate uint32) uint32 { + var clock, rate uint32 + switch uart.Bus { + case stm32.LPUSART1: + clock = CPUFrequency() / 2 // APB1 Frequency + rate = uint32((256 * clock) / baudRate) + case stm32.USART1: + clock = CPUFrequency() / 2 // APB2 Frequency + rate = uint32(clock / baudRate) + case stm32.USART2: + clock = CPUFrequency() / 2 // APB1 Frequency + rate = uint32(clock / baudRate) + } + + return rate +} + +//---------- SPI related types and code + +// SPI on the STM32Fxxx using MODER / alternate function pins +type SPI struct { + Bus *stm32.SPI_Type + AltFuncSelector stm32.AltFunc +} + +// Set baud rate for SPI +func (spi SPI) getBaudRate(config SPIConfig) uint32 { + var conf uint32 + + localFrequency := config.Frequency + + // Default + if config.Frequency == 0 { + config.Frequency = 4e6 + } + + if spi.Bus != stm32.SPI1 { + // Assume it's SPI2 or SPI3 on APB1 at 1/2 the clock frequency of APB2, so + // we want to pretend to request 2x the baudrate asked for + localFrequency = localFrequency * 2 + } + + // set frequency dependent on PCLK prescaler. Since these are rather weird + // speeds due to the CPU freqency, pick a range up to that frquency for + // clients to use more human-understandable numbers, e.g. nearest 100KHz + + // These are based on APB2 clock frquency (84MHz on the discovery board) + // TODO: also include the MCU/APB clock setting in the equation + switch { + case localFrequency < 328125: + conf = stm32.SPI_PCLK_256 + case localFrequency < 656250: + conf = stm32.SPI_PCLK_128 + case localFrequency < 1312500: + conf = stm32.SPI_PCLK_64 + case localFrequency < 2625000: + conf = stm32.SPI_PCLK_32 + case localFrequency < 5250000: + conf = stm32.SPI_PCLK_16 + case localFrequency < 10500000: + conf = stm32.SPI_PCLK_8 + // NOTE: many SPI components won't operate reliably (or at all) above 10MHz + // Check the datasheet of the part + case localFrequency < 21000000: + conf = stm32.SPI_PCLK_4 + case localFrequency < 42000000: + conf = stm32.SPI_PCLK_2 + default: + // None of the specific baudrates were selected; choose the lowest speed + conf = stm32.SPI_PCLK_256 + } + + return conf << stm32.SPI_CR1_BR_Pos +} + +// Configure SPI pins for input output and clock +func (spi SPI) configurePins(config SPIConfig) { + config.SCK.ConfigureAltFunc(PinConfig{Mode: PinModeSPICLK}, spi.AltFuncSelector) + config.SDO.ConfigureAltFunc(PinConfig{Mode: PinModeSPISDO}, spi.AltFuncSelector) + config.SDI.ConfigureAltFunc(PinConfig{Mode: PinModeSPISDI}, spi.AltFuncSelector) +} diff --git a/src/machine/machine_stm32l0_uart.go b/src/machine/machine_stm32l0_uart.go new file mode 100644 index 00000000..80285937 --- /dev/null +++ b/src/machine/machine_stm32l0_uart.go @@ -0,0 +1,64 @@ +// +build stm32,stm32l0 + +package machine + +// Peripheral abstraction layer for UARTs on the stm32 family. + +import ( + "device/stm32" + "runtime/interrupt" + "unsafe" +) + +// Configure the UART. +func (uart UART) Configure(config UARTConfig) { + // Default baud rate to 115200. + if config.BaudRate == 0 { + config.BaudRate = 115200 + } + + // Set the GPIO pins to defaults if they're not set + if config.TX == 0 && config.RX == 0 { + config.TX = UART_TX_PIN + config.RX = UART_RX_PIN + } + + // Enable USART clock + enableAltFuncClock(unsafe.Pointer(uart.Bus)) + + uart.configurePins(config) + + // Set baud rate + uart.SetBaudRate(config.BaudRate) + + // Enable USART port, tx, rx and rx interrupts + uart.Bus.CR1.Set(stm32.USART_CR1_TE | stm32.USART_CR1_RE | stm32.USART_CR1_RXNEIE | stm32.USART_CR1_UE) + + // Enable RX IRQ + uart.Interrupt.SetPriority(0xc0) + uart.Interrupt.Enable() +} + +// handleInterrupt should be called from the appropriate interrupt handler for +// this UART instance. +func (uart *UART) handleInterrupt(interrupt.Interrupt) { + uart.Receive(byte((uart.Bus.RDR.Get() & 0xFF))) +} + +// SetBaudRate sets the communication speed for the UART. Defer to chip-specific +// routines for calculation +func (uart UART) SetBaudRate(br uint32) { + divider := uart.getBaudRateDivisor(br) + uart.Bus.BRR.Set(divider) +} + +// WriteByte writes a byte of data to the UART. +func (uart UART) WriteByte(c byte) error { + + uart.Bus.TDR.Set(uint32(c)) + + for !uart.Bus.ISR.HasBits(stm32.USART_ISR_TXE) { + } + + return nil +} diff --git a/src/runtime/runtime_stm32l0.go b/src/runtime/runtime_stm32l0.go new file mode 100644 index 00000000..daab1276 --- /dev/null +++ b/src/runtime/runtime_stm32l0.go @@ -0,0 +1,230 @@ +// +build stm32,stm32l0 + +package runtime + +import ( + "device/arm" + "device/stm32" + "machine" + "runtime/interrupt" + "runtime/volatile" +) + +const ( + // Sets PCLK1 + RCC_CFGR_PPRE1_DIV_NONE = 0x00000000 + RCC_CFGR_PPRE1_DIV_2 = 0x00000400 + RCC_CFGR_PPRE1_DIV_4 = 0x00000500 + RCC_CFGR_PPRE1_DIV_8 = 0x00000600 + RCC_CFGR_PPRE1_DIV_16 = 0x00000700 + + // Sets PCLK2 + RCC_CFGR_PPRE2_DIV_NONE = 0x00000000 + RCC_CFGR_PPRE2_DIV_2 = 0x00002000 + RCC_CFGR_PPRE2_DIV_4 = 0x00002800 + RCC_CFGR_PPRE2_DIV_8 = 0x00003000 + RCC_CFGR_PPRE2_DIV_16 = 0x00003800 +) + +func init() { + initCLK() + initRTC() + initTIM() + machine.UART0.Configure(machine.UARTConfig{}) +} + +func putchar(c byte) { + machine.UART0.WriteByte(c) +} + +// initCLK sets clock to 32MHz +// SEE: https://github.com/WRansohoff/STM32x0_timer_example/blob/master/src/main.c + +func initCLK() { + + // Set the Flash ACR to use 1 wait-state + // enable the prefetch buffer and pre-read for performance + stm32.Flash.ACR.SetBits(stm32.Flash_ACR_LATENCY | stm32.Flash_ACR_PRFTEN | stm32.Flash_ACR_PRE_READ) + + // Set presaclers so half system clock (PCLKx = HCLK/2) + stm32.RCC.CFGR.SetBits(RCC_CFGR_PPRE1_DIV_2) + stm32.RCC.CFGR.SetBits(RCC_CFGR_PPRE2_DIV_2) + + // Enable the HSI16 oscillator, since the L0 series boots to the MSI one. + stm32.RCC.CR.SetBits(stm32.RCC_CR_HSI16ON) + + // Wait for HSI16 to be ready + for !stm32.RCC.CR.HasBits(stm32.RCC_CR_HSI16RDYF) { + } + + // Configure the PLL to use HSI16 with a PLLDIV of 2 and PLLMUL of 4. + stm32.RCC.CFGR.SetBits(0x01< 625Hz, 625Hz/625 => 1Hz + + // Set initial date + //RTC->TR = RTC_TR_PM | 0; + + stm32.RTC.ISR.ClearBits(stm32.RTC_ISR_INIT) // Disable init phase + stm32.RTC.WPR.Set(0xFE) // Disable Write Access for RTC Registers + stm32.RTC.WPR.Set(0x64) // Disable Write Access for RTC Registers +} + +// Enable the TIM3 clock. +func initTIM() { + stm32.RCC.APB1ENR.SetBits(stm32.RCC_APB1ENR_TIM3EN) + + intr := interrupt.New(stm32.IRQ_TIM3, handleTIM3) + intr.SetPriority(0xc3) + intr.Enable() +} + +const asyncScheduler = false + +func ticksToNanoseconds(ticks timeUnit) int64 { + return int64(ticks) * 1000 +} + +func nanosecondsToTicks(ns int64) timeUnit { + return timeUnit(ns / 1000) +} + +// sleepTicks should sleep for specific number of microseconds. +func sleepTicks(d timeUnit) { + for d != 0 { + ticks() // update timestamp + ticks := uint32(d) // current scaling only supports 100 usec to 6553 msec + timerSleep(ticks) + d -= timeUnit(ticks) + } +} + +// number of ticks (microseconds) since start. +func ticks() timeUnit { + + // Read twice to force shadow register cache update + rSubSec := stm32.RTC.SSR.Get() & stm32.RTC_SSR_SS_Msk + rSubSec = stm32.RTC.SSR.Get() & stm32.RTC_SSR_SS_Msk + rDate := stm32.RTC.DR.Get() + rDate = stm32.RTC.DR.Get() + rDate++ + rTime := stm32.RTC.TR.Get() + rTime = stm32.RTC.TR.Get() + prediv := stm32.RTC.PRER.Get() & stm32.RTC_PRER_PREDIV_S_Msk + + var tsec uint64 + + // Timestamp in seconds + tsec = uint64(((rTime & 0x300000) >> 20) * 36000) // Hours Tens + tsec += uint64(((rTime & 0xf0000) >> 16) * 3600) // Hours Units + tsec += uint64(((rTime & 0x7000) >> 12) * 600) // Minutes Tens + tsec += uint64(((rTime & 0xf00) >> 8) * 60) // Minutes Units + tsec += uint64(((rTime & 0x70) >> 4) * 10) // Second Tens + tsec += uint64(rTime & 0xf) // Seconds Units + + //Second fraction in milliseconds + ssec := uint64((1000 * (prediv - rSubSec)) / (prediv + 1)) + + timerCounter := uint64(tsec * 1000) // Timestamp in millis + timerCounter += ssec // Add sub-seconds + timerCounter *= 1000 // Convert to micros + + // change since last measurement + offset := (timerCounter - timerLastCounter) + timerLastCounter = timerCounter + timestamp += timeUnit(offset) + return timestamp +} + +// ticks are in microseconds +func timerSleep(ticks uint32) { + timerWakeup.Set(0) + + // prescale counter down from 32mhz to 10khz aka 0.1 ms frequency. + clk := machine.CPUFrequency() / 2 + stm32.TIM3.PSC.Set(clk/10000 - 1) + + // Set duty aka duration. + // STM32 dividers use n-1, i.e. n counts from 0 to n-1. + // As a result, with these prescaler settings, + // the minimum allowed duration is 200 microseconds. + if ticks < 200 { + ticks = 200 + } + stm32.TIM3.ARR.Set(ticks/100 - 1) // convert from microseconds to 0.1 ms + + // Enable the hardware interrupt. + stm32.TIM3.DIER.SetBits(stm32.TIM_DIER_UIE) + + // Enable the timer. + stm32.TIM3.CR1.SetBits(stm32.TIM_CR1_CEN) + + // wait till timer wakes up + for timerWakeup.Get() == 0 { + arm.Asm("wfi") + } +} + +func handleTIM3(interrupt.Interrupt) { + if stm32.TIM3.SR.HasBits(stm32.TIM_SR_UIF) { + // Disable the timer. + stm32.TIM3.CR1.ClearBits(stm32.TIM_CR1_CEN) + + // clear the update flag + stm32.TIM3.SR.ClearBits(stm32.TIM_SR_UIF) + + // timer was triggered + timerWakeup.Set(1) + } +} diff --git a/targets/lgt92.json b/targets/lgt92.json new file mode 100644 index 00000000..82c603a9 --- /dev/null +++ b/targets/lgt92.json @@ -0,0 +1,12 @@ +{ + "inherits": [ + "stm32l0x2" + ], + "build-tags": [ + "lgt92" + ], + "linkerscript": "targets/stm32l072czt6.ld", + "flash-method": "openocd", + "openocd-interface": "stlink-v2", + "openocd-target": "stm32f0x" +} \ No newline at end of file diff --git a/targets/stm32l072czt6.ld b/targets/stm32l072czt6.ld new file mode 100644 index 00000000..358f87bc --- /dev/null +++ b/targets/stm32l072czt6.ld @@ -0,0 +1,10 @@ + +MEMORY +{ + FLASH_TEXT (rw) : ORIGIN = 0x08000000, LENGTH = 128K + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K +} + +_stack_size = 2K; + +INCLUDE "targets/arm.ld" diff --git a/targets/stm32l0x2.json b/targets/stm32l0x2.json new file mode 100644 index 00000000..666441fb --- /dev/null +++ b/targets/stm32l0x2.json @@ -0,0 +1,18 @@ +{ + "inherits": [ + "cortex-m" + ], + "llvm-target": "armv6m-none-eabi", + "build-tags": [ + "stm32l0", + "stm32l0x2", + "stm32" + ], + "cflags": [ + "--target=armv6m-none-eabi", + "-Qunused-arguments" + ], + "extra-files": [ + "src/device/stm32/stm32l0x2.s" + ] +} \ No newline at end of file