first commit

This commit is contained in:
valeh
2020-12-22 14:30:09 +02:00
commit 26b0ba5954
1832 changed files with 17777948 additions and 0 deletions

View File

@@ -0,0 +1,148 @@
#
# Generic and Simple GNU ARM Makefile
#
# Desinged for the gnu-arm-none-eabi tool chain
#
# Features
# - create hex file
# - create assembler listing (.dis)
#
# Limitations
# - only C-files supported
# - no automatic dependency checking (call 'make clean' if any .h files are changed)
#
# Targets:
# make
# create hex file, no upload
# make upload
# create and upload hex file
# make clean
# delete all generated files
#
# Note:
# Display list make database: make -p -f/dev/null | less
#
#================================================
# External tools
# The base directory of gcc-arm-none-eabi
# Can be empty on Ubuntu and installed gcc-arm-none-eabi
# If set, GCCBINPATH must contain a "/" at the end.
GCCBINPATH:=/usr/bin/
#================================================
# Project Information
# The name for the project
TARGETNAME:=gpio_pulse
# The source files of the project
CSRC:=$(wildcard *.c)
SSRC:=$(wildcard ../stm32l0xx/src/*.s)
# The CPU architecture (will be used for -mcpu)
# for the LPC824, can we use "cortex-m0plus"?
MCPU:=cortex-m0plus
# Include directory for the system include files
SYSINC:=../stm32l0xx/inc
SYSSRC:=$(wildcard ../stm32l0xx/src/*.c)
# Include directory for the u8g2 include files
#U8G2INC:=../../../../csrc/
#U8G2SRC:=$(wildcard ../../../../csrc/*.c)
# directory for FatFS
#FFINC:=../fatfs
#FFSRC:=$(wildcard ../fatfs/*.c)
# Directory for the linker script
LDSCRIPTDIR:=.
# Name of the linker script (must be the "keep" script, because the other script is not always working)
LDSCRIPT:=stm32l031x6.ld
#================================================
# Main part of the Makefile starts here. Usually no changes are needed.
# Internal Variable Names
LIBNAME:=$(TARGETNAME).a
ELFNAME:=$(TARGETNAME).elf
HEXNAME:=$(TARGETNAME).hex
DISNAME:=$(TARGETNAME).dis
MAPNAME:=$(TARGETNAME).map
OBJ:=$(CSRC:.c=.o) $(SSRC:.s=.o) $(SYSSRC:.c=.o)
# $(SYSSRC:.c=.o) $(U8G2SRC:.c=.o) $(FFSRC:.c=.o)
# Replace standard build tools by arm tools
AS:=$(GCCBINPATH)arm-none-eabi-as
CC:=$(GCCBINPATH)arm-none-eabi-gcc
AR:=$(GCCBINPATH)arm-none-eabi-ar
OBJCOPY:=$(GCCBINPATH)arm-none-eabi-objcopy
OBJDUMP:=$(GCCBINPATH)arm-none-eabi-objdump
SIZE:=$(GCCBINPATH)arm-none-eabi-size
# Common flags
COMMON_FLAGS = -mthumb -mcpu=$(MCPU)
COMMON_FLAGS += -DSTM32L031xx
COMMON_FLAGS += -Wall -I. -I$(SYSINC) -I$(U8G2INC)
# define stack size (defaults to 0x0100)
# COMMON_FLAGS += -D__STACK_SIZE=0x0100
# COMMON_FLAGS += -Os -flto
COMMON_FLAGS += -Os
# COMMON_FLAGS += -fstack-protector
# COMMON_FLAGS += -finstrument-functions
# Do not use stand libs startup code. Uncomment this for gcclib procedures
# memcpy still works, but might be required for __aeabi_uidiv
# COMMON_FLAGS += -nostdlib
# remove unused data and function
#COMMON_FLAGS += -ffunction-sections -fdata-sections -fshort-wchar
COMMON_FLAGS += -ffunction-sections -fdata-sections
# C flags
CFLAGS:=$(COMMON_FLAGS) -std=gnu99
# LD flags
# remove unreferenced procedures and variables, but __isr_vector
GC:=-Wl,--gc-sections -Wl,--undefined=__isr_vector
MAP:=-Wl,-Map=$(MAPNAME)
LFLAGS:=$(COMMON_FLAGS) $(GC) $(MAP)
#LDLIBS:=--specs=nosys.specs -lc -lc -lnosys -L$(LDSCRIPTDIR) -T $(LDSCRIPT)
LDLIBS:=--specs=nosys.specs -L$(LDSCRIPTDIR) -T $(LDSCRIPT)
# Additional Suffixes
.SUFFIXES: .elf .hex .bin .dis
# Targets
.PHONY: all
all: $(DISNAME) $(HEXNAME)
$(SIZE) $(ELFNAME)
.PHONY: upload
upload: $(DISNAME) $(HEXNAME) $(ELFNAME)
stm32flash -e 255 -g 0 -w $(HEXNAME) -v /dev/ttyUSB0
$(SIZE) $(ELFNAME)
.PHONY: clean
clean:
$(RM) $(OBJ) $(HEXNAME) $(ELFNAME) $(LIBNAME) $(DISNAME) $(MAPNAME) libssp.a libssp_nonshared.a
# implicit rules
.elf.hex:
$(OBJCOPY) -O ihex $< $@
# explicit rules
$(ELFNAME): $(LIBNAME)($(OBJ)) libssp.a libssp_nonshared.a
$(LINK.o) $(LFLAGS) $(LIBNAME) $(LDLIBS) -o $@
$(DISNAME): $(ELFNAME)
$(OBJDUMP) -D -S $< > $@
# create empty ssp libs for -fstack-protector-all -fstack-protector
libssp.a:
$(AR) rcs $@
libssp_nonshared.a:
$(AR) rcs $@

View File

@@ -0,0 +1,642 @@
/*
GPIO pulse generator project for the STM32L031
I2C:
Write 0, <gpio cmd>
*/
#include "stm32l031xx.h"
#include "core_cm0plus.h"
/*================================================*/
/* forward declaration */
void setGPIO( uint8_t n );
void clearGPIO(void);
/*================================================*/
/* queue */
#define GPIO_QUEUE_MAX 128
uint8_t gpio_queue_mem[GPIO_QUEUE_MAX];
uint8_t gpio_queue_start = 0;
uint8_t gpio_queue_end = 0;
/* this is called from the I2C interrupt procedures */
void addCmdToGPIOQueue(uint8_t n)
{
uint8_t pos;
pos = gpio_queue_end ;
pos++;
if ( pos >= GPIO_QUEUE_MAX )
pos = 0;
if ( pos == gpio_queue_start )
return; // queue overflow
gpio_queue_mem[gpio_queue_end] = n;
gpio_queue_end = pos;
}
uint8_t isGPIOQueueEmpty(void)
{
if ( gpio_queue_start == gpio_queue_end )
return 1;
return 0;
}
/* get the next command in the queue, return 255 if the queue is empty */
uint8_t getCmdFromGPIOQueue(void)
{
uint8_t r = gpio_queue_mem[gpio_queue_start];
if ( isGPIOQueueEmpty() )
return 255;
return r;
}
void removeCmdFromGPIOQueue(void)
{
if ( isGPIOQueueEmpty() )
return;
__disable_irq();
gpio_queue_start++;
if ( gpio_queue_start >= GPIO_QUEUE_MAX )
gpio_queue_start = 0;
__enable_irq();
}
/*================================================*/
/* GPIO output state machine */
#define GPIO_STATE_IDLE 0
#define GPIO_STATE_TURN_ON 1
#define GPIO_STATE_WAIT_ON 2
#define GPIO_STATE_OFF 3
/* time is in ticks + 1 */
#define GPIO_STATE_ON_TICKS 0
#define GPIO_STATE_OFF_TICKS 4
volatile uint8_t gpio_state = GPIO_STATE_IDLE;
volatile uint8_t gpio_state_machine_output_number = 0;
volatile uint8_t gpio_state_machine_counter = 0;
void gpioNextState(void)
{
switch(gpio_state)
{
case GPIO_STATE_IDLE:
break;
case GPIO_STATE_TURN_ON:
setGPIO(gpio_state_machine_output_number);
gpio_state_machine_counter = GPIO_STATE_ON_TICKS;
gpio_state = GPIO_STATE_WAIT_ON;
break;
case GPIO_STATE_WAIT_ON:
if ( gpio_state_machine_counter == 0 )
{
clearGPIO();
gpio_state_machine_counter = GPIO_STATE_OFF_TICKS;
gpio_state = GPIO_STATE_OFF;
}
else
{
gpio_state_machine_counter--;
}
break;
case GPIO_STATE_OFF:
if ( gpio_state_machine_counter == 0 )
{
gpio_state = GPIO_STATE_IDLE;
}
else
{
gpio_state_machine_counter--;
}
break;
default:
gpio_state = GPIO_STATE_IDLE;
break;
}
}
uint8_t gpioStartStateMachine(uint8_t gpio_number)
{
/* can we enable the state machine? */
if ( gpio_state != GPIO_STATE_IDLE )
return 0; /* not idle, can not start */
/* set the gpio number */
__disable_irq();
gpio_state_machine_output_number = gpio_number;
gpio_state = GPIO_STATE_TURN_ON;
__enable_irq();
return 1;
}
/*================================================*/
/* Queue & State Machine Connector */
void processQueue(void)
{
uint8_t cmd;
cmd = getCmdFromGPIOQueue();
if ( cmd < 255 )
{
/* try to start the state machine */
if ( gpioStartStateMachine(cmd) != 0 )
{
/* success, remove the cmd from the queue */
removeCmdFromGPIOQueue();
}
}
}
/*==============================================*/
/* I2C */
volatile unsigned char i2c_mem[256]; /* contains data, which read or written */
volatile unsigned char i2c_idx; /* the current index into i2c_mem */
volatile unsigned char i2c_is_write_idx; /* write state */
volatile uint16_t i2c_total_irq_cnt;
volatile uint16_t i2c_TXIS_cnt;
volatile uint16_t i2c_RXNE_cnt;
void i2c_mem_reset_write(void)
{
i2c_is_write_idx = 1;
}
void i2c_mem_init(void)
{
i2c_idx = 0;
i2c_mem_reset_write();
}
void i2c_mem_set_index(unsigned char value)
{
i2c_idx = value;
i2c_is_write_idx = 0;
}
void i2c_mem_write_via_index(unsigned char value)
{
if ( i2c_idx == 0 )
{
/* additionall put this byte into the queue */
addCmdToGPIOQueue(value);
}
i2c_mem[i2c_idx++] = value;
}
unsigned char i2c_mem_read(void)
{
i2c_mem_reset_write();
i2c_idx++;
return i2c_mem[i2c_idx];
}
void i2c_mem_write(unsigned char value)
{
if ( i2c_is_write_idx != 0 )
{
i2c_mem_set_index(value);
}
else
{
i2c_is_write_idx = 0;
i2c_mem_write_via_index(value);
}
}
/* address: I2C address multiplied by 2 */
/* Pins PA9 (SCL) and PA10 (SDA) */
void i2c_hw_init(unsigned char address)
{
RCC->APB1ENR |= RCC_APB1ENR_I2C1EN; /* Enable clock for I2C */
RCC->IOPENR |= RCC_IOPENR_IOPAEN; /* Enable clock for GPIO Port A */
__NOP(); /* extra delay for clock stabilization required? */
__NOP();
/* configure io */
GPIOA->MODER &= ~GPIO_MODER_MODE9; /* clear mode for PA9 */
GPIOA->MODER |= GPIO_MODER_MODE9_1; /* alt fn */
GPIOA->OTYPER |= GPIO_OTYPER_OT_9; /* open drain */
GPIOA->AFR[1] &= ~(15<<4); /* Clear Alternate Function PA9 */
GPIOA->AFR[1] |= 1<<4; /* I2C Alternate Function PA9 */
GPIOA->MODER &= ~GPIO_MODER_MODE10; /* clear mode for PA10 */
GPIOA->MODER |= GPIO_MODER_MODE10_1; /* alt fn */
GPIOA->OTYPER |= GPIO_OTYPER_OT_10; /* open drain */
GPIOA->AFR[1] &= ~(15<<8); /* Clear Alternate Function PA10 */
GPIOA->AFR[1] |= 1<<8; /* I2C Alternate Function PA10 */
RCC->CCIPR &= ~RCC_CCIPR_I2C1SEL; /* write 00 to the I2C clk selection register */
RCC->CCIPR |= RCC_CCIPR_I2C1SEL_0; /* select system clock (01) */
/* I2C init flow chart: Clear PE bit */
I2C1->CR1 &= ~I2C_CR1_PE;
/* I2C init flow chart: Configure filter */
/* leave at defaults */
/* I2C init flow chart: Configure timing */
/*
standard mode 100kHz configuration
SYSCLK = I2CCLK = 32 MHz
PRESC = 6 bits 28..31
SCLL = 0x13 bits 0..7
SCLH = 0x0f bits 8..15
SDADEL = 0x02 bits 16..19
SCLDEL = 0x04 bits 20..23
*/
I2C1->TIMINGR = 0x60420f13;
/* I2C init flow chart: Configure NOSTRECH */
I2C1->CR1 |= I2C_CR1_NOSTRETCH;
/* I2C init flow chart: Enable I2C */
I2C1->CR1 |= I2C_CR1_PE;
/* disable OAR1 for reconfiguration */
I2C1->OAR1 &= ~I2C_OAR1_OA1EN;
I2C1->OAR1 = address;
I2C1->OAR1 |= I2C_OAR1_OA1EN;
/* enable interrupts */
I2C1->CR1 |= I2C_CR1_STOPIE;
I2C1->CR1 |= I2C_CR1_NACKIE;
//I2C1->CR1 |= I2C_CR1_ADDRIE;
I2C1->CR1 |= I2C_CR1_RXIE;
I2C1->CR1 |= I2C_CR1_TXIE;
/* load first value into TXDR register */
I2C1->TXDR = i2c_mem[i2c_idx];
/* enable IRQ in NVIC */
NVIC_SetPriority(I2C1_IRQn, 0);
NVIC_EnableIRQ(I2C1_IRQn);
}
void i2c_init(unsigned char address)
{
i2c_mem_init();
i2c_hw_init(address);
}
void __attribute__ ((interrupt, used)) I2C1_IRQHandler(void)
{
unsigned long isr = I2C1->ISR;
i2c_total_irq_cnt ++;
if ( isr & I2C_ISR_TXIS )
{
i2c_TXIS_cnt++;
I2C1->TXDR = i2c_mem_read();
}
else if ( isr & I2C_ISR_RXNE )
{
i2c_RXNE_cnt++;
i2c_mem_write(I2C1->RXDR);
I2C1->ISR |= I2C_ISR_TXE; // allow overwriting the TCDR with new data
I2C1->TXDR = i2c_mem[i2c_idx];
}
else if ( isr & I2C_ISR_STOPF )
{
I2C1->ICR = I2C_ICR_STOPCF;
I2C1->ISR |= I2C_ISR_TXE; // allow overwriting the TCDR with new data
I2C1->TXDR = i2c_mem[i2c_idx];
i2c_mem_reset_write();
}
else if ( isr & I2C_ISR_NACKF )
{
I2C1->ICR = I2C_ICR_NACKCF;
I2C1->ISR |= I2C_ISR_TXE; // allow overwriting the TCDR with new data
I2C1->TXDR = i2c_mem[i2c_idx];
i2c_mem_reset_write();
}
else if ( isr & I2C_ISR_ADDR )
{
/* not required, the addr match interrupt is not enabled */
I2C1->ICR = I2C_ICR_ADDRCF;
I2C1->ISR |= I2C_ISR_TXE; // allow overwriting the TCDR with new data
I2C1->TXDR = i2c_mem[i2c_idx];
i2c_mem_reset_write();
}
/* if at any time the addr match is set, clear the flag */
/* not sure, whether this is required */
if ( isr & I2C_ISR_ADDR )
{
I2C1->ICR = I2C_ICR_ADDRCF;
}
}
/*================================================*/
volatile unsigned long SysTickCount = 0;
void __attribute__ ((interrupt, used)) SysTick_Handler(void)
{
SysTickCount++;
gpioNextState();
}
/*
Delay by the provided number of system ticks.
The delay must be smaller than the RELOAD value.
This delay has an imprecision of about +/- 20 system ticks.
*/
static void _delay_system_ticks_sub(uint32_t sys_ticks)
{
uint32_t start_val, end_val, curr_val;
uint32_t load;
start_val = SysTick->VAL;
start_val &= 0x0ffffffUL;
end_val = start_val;
if ( end_val < sys_ticks )
{
/* check, if the operation after this if clause would lead to a negative result */
/* if this would be the case, then add the reload value first */
load = SysTick->LOAD;
load &= 0x0ffffffUL;
end_val += load;
}
/* counter goes towards zero, so end_val is below start value */
end_val -= sys_ticks;
/* wait until interval is left */
if ( start_val >= end_val )
{
for(;;)
{
curr_val = SysTick->VAL;
curr_val &= 0x0ffffffUL;
if ( curr_val <= end_val )
break;
if ( curr_val > start_val )
break;
}
}
else
{
for(;;)
{
curr_val = SysTick->VAL;
curr_val &= 0x0ffffffUL;
if ( curr_val <= end_val && curr_val > start_val )
break;
}
}
}
/*
Delay by the provided number of system ticks.
Any values between 0 and 0x0ffffffff are allowed.
*/
void delay_system_ticks(uint32_t sys_ticks)
{
uint32_t load4;
load4 = SysTick->LOAD;
load4 &= 0x0ffffffUL;
load4 >>= 2;
while ( sys_ticks > load4 )
{
sys_ticks -= load4;
_delay_system_ticks_sub(load4);
}
_delay_system_ticks_sub(sys_ticks);
}
void setHSIClock()
{
/* test if the current clock source is something else than HSI */
if ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI)
{
/* enable HSI */
RCC->CR |= RCC_CR_HSION;
/* wait until HSI becomes ready */
while ( (RCC->CR & RCC_CR_HSIRDY) == 0 )
;
/* enable the HSI "divide by 4" bit */
RCC->CR |= (uint32_t)(RCC_CR_HSIDIVEN);
/* wait until the "divide by 4" flag is enabled */
while((RCC->CR & RCC_CR_HSIDIVF) == 0)
;
/* then use the HSI clock */
RCC->CFGR = (RCC->CFGR & (uint32_t) (~RCC_CFGR_SW)) | RCC_CFGR_SW_HSI;
/* wait until HSI clock is used */
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_HSI)
;
}
/* disable PLL */
RCC->CR &= (uint32_t)(~RCC_CR_PLLON);
/* wait until PLL is inactive */
while((RCC->CR & RCC_CR_PLLRDY) != 0)
;
/* set latency to 1 wait state */
FLASH->ACR |= FLASH_ACR_LATENCY;
/* At this point the HSI runs with 4 MHz */
/* Multiply by 16 device by 2 --> 32 MHz */
RCC->CFGR = (RCC->CFGR & (~(RCC_CFGR_PLLMUL| RCC_CFGR_PLLDIV ))) | (RCC_CFGR_PLLMUL16 | RCC_CFGR_PLLDIV2);
/* enable PLL */
RCC->CR |= RCC_CR_PLLON;
/* wait until the PLL is ready */
while ((RCC->CR & RCC_CR_PLLRDY) == 0)
;
/* use the PLL has clock source */
RCC->CFGR |= (uint32_t) (RCC_CFGR_SW_PLL);
/* wait until the PLL source is active */
while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL)
;
}
void initGPIO(void)
{
RCC->IOPENR |= RCC_IOPENR_IOPAEN; /* Enable clock for GPIO Port A */
__NOP();
__NOP();
GPIOA->MODER &= ~GPIO_MODER_MODE14; /* clear mode */
GPIOA->MODER |= GPIO_MODER_MODE14_0; /* Output mode */
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_14; /* no Push/Pull */
GPIOA->OSPEEDR &= ~GPIO_OSPEEDER_OSPEED14; /* low speed */
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD14; /* no pullup/pulldown */
GPIOA->BSRR = GPIO_BSRR_BR_14; /* atomic clr */
GPIOA->MODER &= ~GPIO_MODER_MODE13; /* clear mode */
GPIOA->MODER |= GPIO_MODER_MODE13_0; /* Output mode */
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_13; /* no Push/Pull */
GPIOA->OSPEEDR &= ~GPIO_OSPEEDER_OSPEED13; /* low speed */
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD13; /* no pullup/pulldown */
GPIOA->BSRR = GPIO_BSRR_BR_13; /* atomic clr */
GPIOA->MODER &= ~GPIO_MODER_MODE7; /* clear mode */
GPIOA->MODER |= GPIO_MODER_MODE7_0; /* Output mode */
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_7; /* no Push/Pull */
GPIOA->OSPEEDR &= ~GPIO_OSPEEDER_OSPEED7; /* low speed */
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD7; /* no pullup/pulldown */
GPIOA->BSRR = GPIO_BSRR_BR_7; /* atomic clr */
GPIOA->MODER &= ~GPIO_MODER_MODE6; /* clear mode */
GPIOA->MODER |= GPIO_MODER_MODE6_0; /* Output mode */
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_6; /* no Push/Pull */
GPIOA->OSPEEDR &= ~GPIO_OSPEEDER_OSPEED6; /* low speed */
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD6; /* no pullup/pulldown */
GPIOA->BSRR = GPIO_BSRR_BR_6; /* atomic clr */
GPIOA->MODER &= ~GPIO_MODER_MODE5; /* clear mode */
GPIOA->MODER |= GPIO_MODER_MODE5_0; /* Output mode */
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_5; /* no Push/Pull */
GPIOA->OSPEEDR &= ~GPIO_OSPEEDER_OSPEED5; /* low speed */
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD5; /* no pullup/pulldown */
GPIOA->BSRR = GPIO_BSRR_BR_5; /* atomic clr */
GPIOA->MODER &= ~GPIO_MODER_MODE4; /* clear mode */
GPIOA->MODER |= GPIO_MODER_MODE4_0; /* Output mode */
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_4; /* no Push/Pull */
GPIOA->OSPEEDR &= ~GPIO_OSPEEDER_OSPEED4; /* low speed */
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD4; /* no pullup/pulldown */
GPIOA->BSRR = GPIO_BSRR_BR_4; /* atomic clr */
GPIOA->MODER &= ~GPIO_MODER_MODE1; /* clear mode */
GPIOA->MODER |= GPIO_MODER_MODE1_0; /* Output mode */
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_1; /* no Push/Pull */
GPIOA->OSPEEDR &= ~GPIO_OSPEEDER_OSPEED1; /* low speed */
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD1; /* no pullup/pulldown */
GPIOA->BSRR = GPIO_BSRR_BR_1; /* atomic clr */
GPIOA->MODER &= ~GPIO_MODER_MODE0; /* clear mode */
GPIOA->MODER |= GPIO_MODER_MODE0_0; /* Output mode */
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_0; /* no Push/Pull */
GPIOA->OSPEEDR &= ~GPIO_OSPEEDER_OSPEED0; /* low speed */
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD0; /* no pullup/pulldown */
GPIOA->BSRR = GPIO_BSRR_BR_0; /* atomic clr */
}
void clearGPIO(void)
{
GPIOA->BSRR = GPIO_BSRR_BR_14
| GPIO_BSRR_BR_13
| GPIO_BSRR_BR_7
| GPIO_BSRR_BR_6
| GPIO_BSRR_BR_5
| GPIO_BSRR_BR_4
| GPIO_BSRR_BR_1
| GPIO_BSRR_BR_0;
}
/*
0: PA14
1: PA13
2: PA7
3: PA6
4: PA5
5: PA4
6: PA1
7: PA0
*/
void setGPIO( uint8_t n )
{
clearGPIO();
switch(n)
{
case 0: GPIOA->BSRR = GPIO_BSRR_BS_14; break;
case 1: GPIOA->BSRR = GPIO_BSRR_BS_13; break;
case 2: GPIOA->BSRR = GPIO_BSRR_BS_7; break;
case 3: GPIOA->BSRR = GPIO_BSRR_BS_6; break;
case 4: GPIOA->BSRR = GPIO_BSRR_BS_5; break;
case 5: GPIOA->BSRR = GPIO_BSRR_BS_4; break;
case 6: GPIOA->BSRR = GPIO_BSRR_BS_1; break;
case 7: GPIOA->BSRR = GPIO_BSRR_BS_0; break;
}
}
void setAllGPIO(void)
{
GPIOA->BSRR = GPIO_BSRR_BS_14
| GPIO_BSRR_BS_13
| GPIO_BSRR_BS_7
| GPIO_BSRR_BS_6
| GPIO_BSRR_BS_5
| GPIO_BSRR_BS_4
| GPIO_BSRR_BS_1
| GPIO_BSRR_BS_0;
}
int main()
{
uint8_t i;
initGPIO();
setHSIClock();
i2c_init(2*17);
SysTick->LOAD = 32000*100 - 1; // 100 ms
SysTick->VAL = 0;
SysTick->CTRL = 7; /* enable, generate interrupt (SysTick_Handler), do not divide by 2 */
/*
for(;;)
{
delay_system_ticks(32000*200);
setGPIO(7);
delay_system_ticks(32000*200);
clearGPIO();
}
*/
for( i = 0; i < 8; i++ )
addCmdToGPIOQueue(i);
for(;;)
{
processQueue();
}
}

View File

@@ -0,0 +1,245 @@
/*
stm32l031x6.ld
Modified for stm32l0 from the original nokeep.ld script from the
arm-none-eabi examples by olikraus@gmail.com
Assuming, that the original nokeep.ld file is available under
the GNU General Public License, this file is available under the
same license.
There are three modifications:
1. Provide symbols for the stm32l0 startup code
The following symbols are required for the stm32l0 startup
code (e.g. startup_stm32l031xx.s)
_sidata start address for the initialization values of the .data section
_sdata start address for the .data section. defined in linker script
_edata end address for the .data section. defined in linker script
_sbss start address for the .bss section. defined in linker script
_ebss end address for the .bss section. defined in linker script
_estack top address of the stack
2. Stack size estimation / calculation
_Stack_Size has been added to allow better stack size calculation
3. KEEP keywords
Additionall KEEPs added for .init and .fini. Without this KEEP the
generated code will not work, because of the missing _init function.
4. Bugfix: Allign the end of the flash area
*/
_Stack_Size = 0x400; /* stm32l0: estimated amount of stack */
/* Linker script to configure memory regions.
* Need modifying for a specific board.
* FLASH.ORIGIN: starting address of flash
* FLASH.LENGTH: length of flash
* RAM.ORIGIN: starting address of RAM bank 0
* RAM.LENGTH: length of RAM bank 0
*/
MEMORY
{
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 32K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 8K
}
/* Linker script to place sections and symbol values. Should be used together
* with other linker script that defines memory regions FLASH and RAM.
* It references following symbols, which must be defined in code:
* Reset_Handler : Entry of reset handler
*
* It defines following symbols, which code can use without definition:
* __exidx_start
* __exidx_end
* __copy_table_start__
* __copy_table_end__
* __zero_table_start__
* __zero_table_end__
* __etext
* __data_start__
* __preinit_array_start
* __preinit_array_end
* __init_array_start
* __init_array_end
* __fini_array_start
* __fini_array_end
* __data_end__
* __bss_start__
* __bss_end__
* __end__
* end
* __HeapLimit
* __StackLimit
* __StackTop
* __stack
*/
ENTRY(Reset_Handler)
SECTIONS
{
.text :
{
KEEP(*(.isr_vector))
*(.text*)
/* the st32l0 startup code calls __libc_init_array, which calls the _init */
/* ... sooo.... better keep the init and fini sections */
KEEP ( *(.init) )
KEEP ( *(.fini) )
/* .ctors */
*crtbegin.o(.ctors)
*crtbegin?.o(.ctors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
*(SORT(.ctors.*))
*(.ctors)
/* .dtors */
*crtbegin.o(.dtors)
*crtbegin?.o(.dtors)
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
*(SORT(.dtors.*))
*(.dtors)
*(.rodata*)
*(.eh_frame*)
/* allign the end of the flash area */
. = ALIGN(4);
} > FLASH
.ARM.extab :
{
*(.ARM.extab* .gnu.linkonce.armextab.*)
} > FLASH
__exidx_start = .;
.ARM.exidx :
{
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
} > FLASH
__exidx_end = .;
/* To copy multiple ROM to RAM sections,
* uncomment .copy.table section and,
* define __STARTUP_COPY_MULTIPLE in startup_ARMCMx.S */
/*
.copy.table :
{
. = ALIGN(4);
__copy_table_start__ = .;
LONG (__etext)
LONG (__data_start__)
LONG (__data_end__ - __data_start__)
LONG (__etext2)
LONG (__data2_start__)
LONG (__data2_end__ - __data2_start__)
__copy_table_end__ = .;
} > FLASH
*/
/* To clear multiple BSS sections,
* uncomment .zero.table section and,
* define __STARTUP_CLEAR_BSS_MULTIPLE in startup_ARMCMx.S */
/*
.zero.table :
{
. = ALIGN(4);
__zero_table_start__ = .;
LONG (__bss_start__)
LONG (__bss_end__ - __bss_start__)
LONG (__bss2_start__)
LONG (__bss2_end__ - __bss2_start__)
__zero_table_end__ = .;
} > FLASH
*/
__etext = .;
_sidata = .; /* for stm32l0 startup code */
.data : AT (__etext)
{
__data_start__ = .;
_sdata = .; /* for stm32l0 startup code */
*(vtable)
*(.data*)
. = ALIGN(4);
/* preinit data */
PROVIDE_HIDDEN (__preinit_array_start = .);
*(.preinit_array)
PROVIDE_HIDDEN (__preinit_array_end = .);
. = ALIGN(4);
/* init data */
PROVIDE_HIDDEN (__init_array_start = .);
*(SORT(.init_array.*))
*(.init_array)
PROVIDE_HIDDEN (__init_array_end = .);
. = ALIGN(4);
/* finit data */
PROVIDE_HIDDEN (__fini_array_start = .);
*(SORT(.fini_array.*))
*(.fini_array)
PROVIDE_HIDDEN (__fini_array_end = .);
*(.jcr)
. = ALIGN(4);
/* All data end */
__data_end__ = .;
_edata = .; /* for stm32l0 startup code */
} > RAM
.bss :
{
. = ALIGN(4);
__bss_start__ = .;
_sbss = .; /* for stm32l0 startup code */
*(.bss*)
*(COMMON)
. = ALIGN(4);
__bss_end__ = .;
_ebss = .; /* for stm32l0 startup code */
} > RAM
.heap (COPY):
{
__end__ = .;
PROVIDE(end = .);
*(.heap*)
__HeapLimit = .;
} > RAM
/* .stack_dummy section doesn't contains any symbols. It is only
* used for linker to calculate size of stack sections, and assign
* values to stack symbols later */
.stack_dummy (COPY):
{
*(.stack*)
. = . + _Stack_Size; /* estimated stack size */
} > RAM
/* Set stack top to end of RAM, and stack limit move down by
* size of stack_dummy section */
__StackTop = ORIGIN(RAM) + LENGTH(RAM);
_estack = __StackTop; /* for stm32l0 startup code */
__StackLimit = __StackTop - SIZEOF(.stack_dummy);
PROVIDE(__stack = __StackTop);
/* Check if data + heap + stack exceeds RAM limit */
ASSERT(__StackLimit >= __HeapLimit, "region RAM overflowed with stack")
}