diff --git a/sys/arm/stm32l031x6/u8g2_rtc/Makefile b/sys/arm/stm32l031x6/u8g2_rtc/Makefile new file mode 100644 index 00000000..cfebd74d --- /dev/null +++ b/sys/arm/stm32l031x6/u8g2_rtc/Makefile @@ -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:=u8x8_test + +# 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) $(U8G2SRC:.c=.o) +# $(SYSSRC:.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 $@ + + diff --git a/sys/arm/stm32l031x6/u8g2_rtc/delay.c b/sys/arm/stm32l031x6/u8g2_rtc/delay.c new file mode 100644 index 00000000..fc08dea5 --- /dev/null +++ b/sys/arm/stm32l031x6/u8g2_rtc/delay.c @@ -0,0 +1,129 @@ +/* + delay.c + + The delay function delay_micro_seconds() will use the global variable + SystemCoreClock. A call to SystemCoreClockUpdate() is required before + using delay_micro_seconds(). + + STM32L031 Project (U8g2 Library) + + Copyright (c) 2017, olikraus@gmail.com + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list + of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or other + materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + + +*/ + +#include "stm32l031xx.h" + +/* Generic ARM delay procedure, based on the system timer (SysTick) */ + +/* + 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); +} + +/* + Delay by the provided number of micro seconds. + Limitation: "us" * System-Freq in MHz must not overflow in 32 bit. + Values between 0 and 1.000.000 (1 second) are ok. + + Important: Call SystemCoreClockUpdate() before calling this function. +*/ +void delay_micro_seconds(uint32_t us) +{ + uint32_t sys_ticks; + + sys_ticks = SystemCoreClock; + sys_ticks /=1000000UL; + sys_ticks *= us; + delay_system_ticks(sys_ticks); +} diff --git a/sys/arm/stm32l031x6/u8g2_rtc/delay.h b/sys/arm/stm32l031x6/u8g2_rtc/delay.h new file mode 100644 index 00000000..563724d4 --- /dev/null +++ b/sys/arm/stm32l031x6/u8g2_rtc/delay.h @@ -0,0 +1,55 @@ +/* + delay.h + + LPC11U3x GPS Logger (https://github.com/olikraus/lpc11u3x-gps-logger) + + Copyright (c) 2016, olikraus@gmail.com + All rights reserved. + + Redistribution and use in source and binary forms, with or without modification, + are permitted provided that the following conditions are met: + + * Redistributions of source code must retain the above copyright notice, this list + of conditions and the following disclaimer. + + * Redistributions in binary form must reproduce the above copyright notice, this + list of conditions and the following disclaimer in the documentation and/or other + materials provided with the distribution. + + THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND + CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, + INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT + NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF + ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +*/ + +#ifndef _DELAY_H +#define _DELAY_H + +#include + +/* + Delay by the provided number of system ticks. + Any values between 0 and 0x0ffffffff are allowed. +*/ +void delay_system_ticks(uint32_t sys_ticks); + +/* + Delay by the provided number of micro seconds. + Limitation: "us" * System-Freq in MHz must now overflow in 32 bit. + Values between 0 and 1.000.000 (1 second) are ok. + + Important: Call SystemCoreClockUpdate() before calling this function. +*/ +void delay_micro_seconds(uint32_t us); + +#endif /* _DELAY_H */ diff --git a/sys/arm/stm32l031x6/u8g2_rtc/main.c b/sys/arm/stm32l031x6/u8g2_rtc/main.c new file mode 100644 index 00000000..34d9fa24 --- /dev/null +++ b/sys/arm/stm32l031x6/u8g2_rtc/main.c @@ -0,0 +1,180 @@ +/* LED blink project for the STM32L031 */ + +#include "stm32l031xx.h" +#include "delay.h" +#include "u8g2.h" +#include "rtc.h" + +/*=======================================================================*/ +/* external functions */ +uint8_t u8x8_gpio_and_delay_stm32l0(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr); + + +/*=======================================================================*/ +/* global variables */ + +volatile unsigned long SysTickCount = 0; +rtc_t rtc; +u8g2_t u8g2; + +/*=======================================================================*/ + +void __attribute__ ((interrupt, used)) SysTick_Handler(void) +{ + SysTickCount++; +} + + + +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) + ; +} + +int main() +{ + setHSIClock(); + SystemCoreClockUpdate(); /* Update SystemCoreClock() */ + //SystemCoreClock = 32000000UL; + + SysTick->LOAD = (SystemCoreClock/1000)*50 - 1; /* 50ms task */ + SysTick->VAL = 0; + SysTick->CTRL = 7; /* enable, generate interrupt (SysTick_Handler), do not divide by 2 */ + + + RCC->IOPENR |= RCC_IOPENR_IOPAEN; /* Enable clock for GPIO Port A */ + __NOP(); + __NOP(); + + GPIOA->MODER &= ~GPIO_MODER_MODE13; /* clear mode for PA13 */ + GPIOA->MODER |= GPIO_MODER_MODE13_0; /* Output mode for PA13 */ + GPIOA->OTYPER &= ~GPIO_OTYPER_OT_13; /* Push/Pull for PA13 */ + GPIOA->OSPEEDR &= ~GPIO_OSPEEDER_OSPEED13; /* low speed for PA13 */ + GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD13; /* no pullup/pulldown for PA13 */ + GPIOA->BSRR = GPIO_BSRR_BR_13; /* atomic clr PA13 */ + GPIOA->BSRR = GPIO_BSRR_BS_13; /* atomic set PA13 */ + + /* setup display */ + u8g2_Setup_ssd1306_i2c_128x64_noname_f(&u8g2, U8G2_R0, u8x8_byte_sw_i2c, u8x8_gpio_and_delay_stm32l0); + u8g2_InitDisplay(&u8g2); + u8g2_SetPowerSave(&u8g2, 0); + u8g2_SetFont(&u8g2, u8g2_font_6x12_tf); + u8g2_ClearBuffer(&u8g2); + u8g2_DrawStr(&u8g2, 0,12, "STM32L031"); + u8g2_DrawStr(&u8g2, 0,24, u8x8_u8toa(SystemCoreClock/1000000, 2)); + u8g2_DrawStr(&u8g2, 20,24, "MHz"); + u8g2_SendBuffer(&u8g2); + + + + /* real time clock enable */ + + RCC->APB1ENR |= RCC_APB1ENR_PWREN; /* enable power interface */ + PWR->CR |= PWR_CR_DBP; /* activate write access to RCC->CSR */ + + /* externel 32K clock source */ + RCC->CSR |= RCC_CSR_LSEBYP; /* bypass oscillator */ + + /* externel 32K oscillator */ + //RCC->CSR &= ~RCC_CSR_LSEBYP; /* no bypass oscillator */ + //RCC->CSR &= ~RCC_CSR_LSEDRV_Msk /* lowest drive */ + //RCC->CSR |= RCC_CSR_LSEDRV_0; /* medium low drive */ + + RCC->CSR |= RCC_CSR_LSEON; /* enable low speed external clock */ + delay_micro_seconds(100000*5); /* LSE requires between 100ms to 200ms */ + /* + if ( RCC->CSR & RCC_CSR_LSERDY ) + display_Write("32K Clock Ready\n"); + else + display_Write("32K Clock Error\n"); + */ + RCC->CSR &= ~RCC_CSR_RTCSEL_Msk; /* no clock selection for RTC */ + RCC->CSR |= RCC_CSR_RTCSEL_LSE; /* select LSE */ + RCC->CSR |= RCC_CSR_RTCEN; /* enable RTC */ + + RTC->WPR = 0x0ca; /* disable RTC write protection */ + RTC->WPR = 0x053; + + RTC->ISR = RTC_ISR_INIT; /* request RTC stop */ + while((RTC->ISR & RTC_ISR_INITF)!=RTC_ISR_INITF) /* wait for stop */ + ; + RTC->PRER = 0x07f00ff; + RTC->TR = 0; + RTC->ISR =~ RTC_ISR_INIT; /* start RTC */ + + RTC->WPR = 0; /* enable RTC write protection */ + RTC->WPR = 0; + + + + //PWR->CR &= ~PWR_CR_DBP; /* disable write access to RCC->CSR */ + + + for(;;) + { + u8g2_ClearBuffer(&u8g2); + rtc_register_to_bcd(&rtc); + rtc_bcd_to_ymd_hms(&rtc); + rtc_draw_time(&rtc, &u8g2); + u8g2_SendBuffer(&u8g2); + + delay_micro_seconds(500000); + GPIOA->BSRR = GPIO_BSRR_BS_13; /* atomic set PA13 */ + delay_micro_seconds(500000); + GPIOA->BSRR = GPIO_BSRR_BR_13; /* atomic clr PA13 */ + + + //display_WriteUnsigned(RTC->TR); + //display_Write("\n"); + } +} diff --git a/sys/arm/stm32l031x6/u8g2_rtc/rtc.c b/sys/arm/stm32l031x6/u8g2_rtc/rtc.c new file mode 100644 index 00000000..d80ee593 --- /dev/null +++ b/sys/arm/stm32l031x6/u8g2_rtc/rtc.c @@ -0,0 +1,78 @@ +/* + + rtc.c + + PA0 TAMP2 Button + PA2 TAMP3 Button + +*/ + + +#include +#include "stm32l031xx.h" +#include "delay.h" +#include "u8g2.h" +#include "rtc.h" + +/* read RTC register into bcd array */ +void rtc_register_to_bcd(rtc_t *rtc) +{ + uint32_t r; + int i; + + r = RTC->TR; + i = 0; + do + { + rtc->bcd[i] = r & 15; + r >>= 4; + i++; + } while( i < 6 ); + + rtc->bcd[1] &= 7; /* seconds */ + rtc->bcd[3] &= 7; /* minutes */ + rtc->bcd[5] &= 3; /* hours */ + + r = RTC->DR; + i = 6; + do + { + rtc->bcd[i] = r & 15; + r >>= 4; + i++; + } while( i < 12 ); + + rtc->bcd[7] &= 3; /* days */ + rtc->bcd[9] &= 1; /* months */ +} + +static uint8_t rtc_bcd_to_uint8(rtc_t *rtc, int idx) U8G2_NOINLINE; +static uint8_t rtc_bcd_to_uint8(rtc_t *rtc, int idx) +{ + return rtc->bcd[idx+1]*10 + rtc->bcd[idx]; +} + +/* convert the content of the bcd array to the ymd&hms vars */ +void rtc_bcd_to_ymd_hms(rtc_t *rtc) +{ + rtc->sec = rtc_bcd_to_uint8(rtc, 0); + rtc->min = rtc_bcd_to_uint8(rtc, 2); + rtc->hour = rtc_bcd_to_uint8(rtc, 4); + rtc->day = rtc_bcd_to_uint8(rtc, 6); + rtc->month = rtc_bcd_to_uint8(rtc, 8); + rtc->year = rtc_bcd_to_uint8(rtc, 10); +} + +void rtc_draw_time(rtc_t *rtc, u8g2_t *u8g2) +{ + char s[10]; + strcpy(s, u8x8_u8toa(rtc->hour, 2)); + strcat(s, ":"); + strcat(s, u8x8_u8toa(rtc->min, 2)); + strcat(s, ":"); + strcat(s, u8x8_u8toa(rtc->sec, 2)); + + u8g2_SetFont(u8g2, u8g2_font_helvB18_tn); + u8g2_DrawStr(u8g2, 0,23, s); + +} \ No newline at end of file diff --git a/sys/arm/stm32l031x6/u8g2_rtc/rtc.h b/sys/arm/stm32l031x6/u8g2_rtc/rtc.h new file mode 100644 index 00000000..bc541905 --- /dev/null +++ b/sys/arm/stm32l031x6/u8g2_rtc/rtc.h @@ -0,0 +1,43 @@ +/* + + rtc.h + +*/ + +#ifndef _RTC_VIEW_H +#define _RTC_VIEW_H + +#include "stdint.h" + +#define BCD_SEC_UNITS 0 +#define BCD_SEC_TENS 1 +#define BCD_MIN_UNITS 2 +#define BCD_MIN_TENS 3 +#define BCD_HOUR_UNITS 4 +#define BCD_HOUR_TENS 5 +#define BCD_DAY_UNITS 6 +#define BCD_DAY_TENS 7 +#define BCD_MONTH_UNITS 8 +#define BCD_MONTH_TENS 9 +#define BCD_YEAR_UNITS 10 +#define BCD_YEAR_TENS 11 + + +struct _rtc_struct +{ + uint8_t bcd[12]; + + uint8_t sec; /* 0..59 */ + uint8_t min; /* 0..59 */ + uint8_t hour; /* 0..23 */ + uint8_t day; /* 1..31 */ + uint8_t month; /* 1..12 */ + uint8_t year; /* 0..99 */ +}; +typedef struct _rtc_struct rtc_t; + +void rtc_register_to_bcd(rtc_t *rtc); +void rtc_bcd_to_ymd_hms(rtc_t *rtc); +void rtc_draw_time(rtc_t *rtc, u8g2_t *u8g2); + +#endif \ No newline at end of file diff --git a/sys/arm/stm32l031x6/u8g2_rtc/stm32l031x6.ld b/sys/arm/stm32l031x6/u8g2_rtc/stm32l031x6.ld new file mode 100644 index 00000000..381cbf01 --- /dev/null +++ b/sys/arm/stm32l031x6/u8g2_rtc/stm32l031x6.ld @@ -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") +} diff --git a/sys/arm/stm32l031x6/u8g2_rtc/u8x8cb.c b/sys/arm/stm32l031x6/u8g2_rtc/u8x8cb.c new file mode 100644 index 00000000..7de3fa72 --- /dev/null +++ b/sys/arm/stm32l031x6/u8g2_rtc/u8x8cb.c @@ -0,0 +1,112 @@ +/* + u8x8cb.c + + STM32L031 + + PA9: Clock + PA10: Data + Both lines have a pullup resistor + +*/ + +#include "stm32l031xx.h" +#include "delay.h" +#include "u8x8.h" + + +uint8_t u8x8_gpio_and_delay_stm32l0(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr) +{ + switch(msg) + { + case U8X8_MSG_GPIO_AND_DELAY_INIT: + /* only support for software I2C*/ + + RCC->IOPENR |= RCC_IOPENR_IOPAEN; /* Enable clock for GPIO Port A */ + __NOP(); + __NOP(); + + GPIOA->MODER &= ~GPIO_MODER_MODE10; /* clear mode for PA10 */ + //GPIOA->MODER |= GPIO_MODER_MODE10_0; /* Output mode for PA10 */ + GPIOA->OTYPER &= ~GPIO_OTYPER_OT_10; /* no open drain for PA10 */ + GPIOA->OSPEEDR &= ~GPIO_OSPEEDER_OSPEED10; /* low speed for PA10 */ + GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD10; /* no pullup/pulldown for PA10 */ + //GPIOA->BSRR = GPIO_BSRR_BS_10; /* atomic set PA10 */ + + GPIOA->MODER &= ~GPIO_MODER_MODE9; /* clear mode for PA9 */ + //GPIOA->MODER |= GPIO_MODER_MODE9_0; /* Output mode for PA9 */ + GPIOA->OTYPER &= ~GPIO_OTYPER_OT_9; /* no open drain for PA9 */ + GPIOA->OSPEEDR &= ~GPIO_OSPEEDER_OSPEED9; /* low speed for PA9 */ + GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD9; /* no pullup/pulldown for PA9 */ + //GPIOA->BSRR = GPIO_BSRR_BS_9; /* atomic set PA9 */ + + break; + case U8X8_MSG_DELAY_NANO: + /* not required for SW I2C */ + break; + + case U8X8_MSG_DELAY_10MICRO: + /* not used at the moment */ + break; + + case U8X8_MSG_DELAY_100NANO: + /* not used at the moment */ + break; + + case U8X8_MSG_DELAY_MILLI: + delay_micro_seconds(arg_int*1000UL); + break; + case U8X8_MSG_DELAY_I2C: + /* arg_int is 1 or 4: 100KHz (5us) or 400KHz (1.25us) */ + delay_micro_seconds(arg_int<=2?5:1); + break; + + case U8X8_MSG_GPIO_I2C_CLOCK: + + if ( arg_int == 0 ) + { + GPIOA->MODER &= ~GPIO_MODER_MODE9; /* clear mode for PA10 */ + GPIOA->MODER |= GPIO_MODER_MODE9_0; /* Output mode for PA10 */ + GPIOA->BSRR = GPIO_BSRR_BR_9; /* atomic clr PA9 */ + } + else + { + //GPIOA->BSRR = GPIO_BSRR_BS_9; /* atomic set PA9 */ + GPIOA->MODER &= ~GPIO_MODER_MODE9; /* clear mode for PA9: input mode */ + } + break; + case U8X8_MSG_GPIO_I2C_DATA: + + if ( arg_int == 0 ) + { + GPIOA->MODER &= ~GPIO_MODER_MODE10; /* clear mode for PA10 */ + GPIOA->MODER |= GPIO_MODER_MODE10_0; /* Output mode for PA10 */ + GPIOA->BSRR = GPIO_BSRR_BR_10; /* atomic clr PA10 */ + } + else + { + //GPIOA->BSRR = GPIO_BSRR_BS_10; /* atomic set PA10 */ + // input mode + GPIOA->MODER &= ~GPIO_MODER_MODE10; /* clear mode for PA10: input mode */ + } + break; +/* + case U8X8_MSG_GPIO_MENU_SELECT: + u8x8_SetGPIOResult(u8x8, Chip_GPIO_GetPinState(LPC_GPIO, KEY_SELECT_PORT, KEY_SELECT_PIN)); + break; + case U8X8_MSG_GPIO_MENU_NEXT: + u8x8_SetGPIOResult(u8x8, Chip_GPIO_GetPinState(LPC_GPIO, KEY_NEXT_PORT, KEY_NEXT_PIN)); + break; + case U8X8_MSG_GPIO_MENU_PREV: + u8x8_SetGPIOResult(u8x8, Chip_GPIO_GetPinState(LPC_GPIO, KEY_PREV_PORT, KEY_PREV_PIN)); + break; + + case U8X8_MSG_GPIO_MENU_HOME: + u8x8_SetGPIOResult(u8x8, Chip_GPIO_GetPinState(LPC_GPIO, KEY_HOME_PORT, KEY_HOME_PIN)); + break; +*/ + default: + u8x8_SetGPIOResult(u8x8, 1); + break; + } + return 1; +}