mirror of
https://github.com/olikraus/u8g2.git
synced 2025-05-08 15:56:09 +08:00
update
This commit is contained in:
parent
9f8b9924b4
commit
a0eb1bada3
@ -64,7 +64,7 @@ void u8x8_d_helper_display_setup_memory(u8x8_t *u8x8, const u8x8_display_info_t
|
||||
void u8x8_d_helper_display_init(u8x8_t *u8x8)
|
||||
{
|
||||
/* 2) apply port directions to the GPIO lines and apply default values for the IO lines*/
|
||||
u8x8_gpio_Init(u8x8);
|
||||
u8x8_gpio_Init(u8x8); /* macro, which calls gpio_and_delay_cb with U8X8_MSG_GPIO_AND_DELAY_INIT */
|
||||
u8x8_cad_Init(u8x8); /* this will also call U8X8_MSG_BYTE_INIT, byte init will NOT call GPIO_INIT */
|
||||
|
||||
/* 3) do reset */
|
||||
@ -108,8 +108,8 @@ void u8x8_SetupMemory(u8x8_t *u8x8)
|
||||
*/
|
||||
void u8x8_InitInterface(u8x8_t *u8x8)
|
||||
{
|
||||
u8x8_gpio_Init(u8x8);
|
||||
u8x8_cad_Init(u8x8); /* this will also call U8X8_MSG_BYTE_INIT, byte init will NOT call GPIO_INIT */
|
||||
u8x8_gpio_Init(u8x8); /* macro, which calls gpio_and_delay_cb with U8X8_MSG_GPIO_AND_DELAY_INIT */
|
||||
u8x8_cad_Init(u8x8); /* this will also call U8X8_MSG_BYTE_INIT, byte init will NOT call GPIO_INIT, which alread is called in the prev step */
|
||||
}
|
||||
|
||||
/*
|
||||
|
150
sys/arm/stm32l031x4/u8g2_test/Makefile
Normal file
150
sys/arm/stm32l031x4/u8g2_test/Makefile
Normal file
@ -0,0 +1,150 @@
|
||||
#
|
||||
# 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:=u8g2_test
|
||||
|
||||
# The source files of the project
|
||||
CSRC:=$(wildcard *.c)
|
||||
SSRC:=$(wildcard ../../stm32l031x6/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:=../../stm32l031x6/stm32l0xx/inc
|
||||
SYSSRC:=$(wildcard ../../stm32l031x6/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:=stm32l031x4.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=nano.specs -L$(LDSCRIPTDIR) -T $(LDSCRIPT)
|
||||
# the ubuntu version of arm-none-eabi-ar seems to be compiled in deterministic mode which will force timestamp to zero, use undeterministic mode instead (U-modifier)
|
||||
ARFLAGS=rvU
|
||||
|
||||
# Additional Suffixes
|
||||
.SUFFIXES: .elf .hex .bin .dis
|
||||
|
||||
# Targets
|
||||
.PHONY: all
|
||||
all: $(DISNAME) $(HEXNAME)
|
||||
$(SIZE) $(ELFNAME)
|
||||
|
||||
.PHONY: upload
|
||||
upload: $(DISNAME) $(HEXNAME) $(ELFNAME)
|
||||
/home/kraus/git/stm32flash-code/stm32flash -b 115200 -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 $@
|
||||
|
||||
|
129
sys/arm/stm32l031x4/u8g2_test/delay.c
Normal file
129
sys/arm/stm32l031x4/u8g2_test/delay.c
Normal file
@ -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);
|
||||
}
|
55
sys/arm/stm32l031x4/u8g2_test/delay.h
Normal file
55
sys/arm/stm32l031x4/u8g2_test/delay.h
Normal file
@ -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 <stdint.h>
|
||||
|
||||
/*
|
||||
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 */
|
260
sys/arm/stm32l031x4/u8g2_test/main.c
Normal file
260
sys/arm/stm32l031x4/u8g2_test/main.c
Normal file
@ -0,0 +1,260 @@
|
||||
/*
|
||||
|
||||
u8x8_test
|
||||
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include "stm32l031xx.h"
|
||||
#include "delay.h"
|
||||
#include "u8g2.h"
|
||||
|
||||
/*=======================================================================*/
|
||||
/* external functions */
|
||||
uint8_t u8x8_gpio_and_delay_stm32l0_sw_i2c(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
uint8_t u8x8_gpio_and_delay_stm32l0_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
|
||||
uint8_t u8x8_byte_stm32l0_hw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr);
|
||||
|
||||
|
||||
/*=======================================================================*/
|
||||
/* global variables */
|
||||
|
||||
u8g2_t u8g2; // u8g2 object
|
||||
uint8_t u8g2_x, u8g2_y; // current position on the screen
|
||||
|
||||
volatile unsigned long SysTickCount = 0;
|
||||
|
||||
|
||||
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)
|
||||
;
|
||||
|
||||
SystemCoreClockUpdate(); /* Update SystemCoreClock global variable */
|
||||
}
|
||||
|
||||
/*
|
||||
Enable several power regions: PWR, GPIOA
|
||||
|
||||
This must be executed after each reset.
|
||||
*/
|
||||
void startUp(void)
|
||||
{
|
||||
RCC->IOPENR |= RCC_IOPENR_IOPAEN; /* Enable clock for GPIO Port A */
|
||||
RCC->IOPENR |= RCC_IOPENR_IOPBEN; /* Enable clock for GPIO Port B */
|
||||
|
||||
RCC->APB1ENR |= RCC_APB1ENR_PWREN; /* enable power interface (PWR) */
|
||||
PWR->CR |= PWR_CR_DBP; /* activate write access to RCC->CSR and RTC */
|
||||
|
||||
SysTick->LOAD = (SystemCoreClock/1000)*50 - 1; /* 50ms task */
|
||||
SysTick->VAL = 0;
|
||||
SysTick->CTRL = 7; /* enable, generate interrupt (SysTick_Handler), do not divide by 2 */
|
||||
}
|
||||
|
||||
/*=======================================================================*/
|
||||
/* u8x8 display procedures */
|
||||
|
||||
void initDisplay(void)
|
||||
{
|
||||
|
||||
/* setup display */
|
||||
//u8g2_Setup_ssd1306_i2c_128x64_noname_f(&u8g2, U8G2_R2, u8x8_byte_sw_i2c, u8x8_gpio_and_delay_stm32l0_sw_i2c);
|
||||
|
||||
//u8g2_Setup_uc1609_slg19264_f(&u8g2, U8G2_R2, u8x8_byte_4wire_sw_spi, u8x8_gpio_and_delay_stm32l0_spi);
|
||||
|
||||
u8g2_Setup_uc1609_slg19264_f(&u8g2, U8G2_R2, u8x8_byte_stm32l0_hw_spi, u8x8_gpio_and_delay_stm32l0_spi);
|
||||
|
||||
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
void outChar(uint8_t c)
|
||||
{
|
||||
u8g2_x+=u8g2_DrawGlyph(&u8g2, u8g2_x, u8g2_y, c);
|
||||
}
|
||||
|
||||
void outStr(const char *s)
|
||||
{
|
||||
while( *s )
|
||||
outChar(*s++);
|
||||
}
|
||||
|
||||
void outHexHalfByte(uint8_t b)
|
||||
{
|
||||
b &= 0x0f;
|
||||
if ( b < 10 )
|
||||
outChar(b+'0');
|
||||
else
|
||||
outChar(b+'a'-10);
|
||||
}
|
||||
|
||||
void outHex8(uint8_t b)
|
||||
{
|
||||
outHexHalfByte(b >> 4);
|
||||
outHexHalfByte(b);
|
||||
}
|
||||
|
||||
void outHex16(uint16_t v)
|
||||
{
|
||||
outHex8(v>>8);
|
||||
outHex8(v);
|
||||
}
|
||||
|
||||
void outHex32(uint32_t v)
|
||||
{
|
||||
outHex16(v>>16);
|
||||
outHex16(v);
|
||||
}
|
||||
|
||||
void setRow(uint8_t r)
|
||||
{
|
||||
u8g2_x = 0;
|
||||
u8g2_y = r;
|
||||
}
|
||||
|
||||
void notused(void *ptr, uint16_t cnt)
|
||||
{
|
||||
/* disable and reset to defaults */
|
||||
DMA1_Channel1->CCR = 0;
|
||||
|
||||
/* defaults:
|
||||
- 8 Bit access --> will be changed below
|
||||
- read from peripheral --> ok
|
||||
- none-circular mode --> ok
|
||||
- no increment mode --> will be changed below
|
||||
*/
|
||||
|
||||
|
||||
DMA1_Channel1->CNDTR = cnt; /* buffer size */
|
||||
DMA1_Channel1->CPAR = (uint32_t)&(ADC1->DR); /* source value */
|
||||
// DMA1_Channel1->CPAR = (uint32_t)&(GPIOA->ODR); /* source value */
|
||||
DMA1_Channel1->CMAR = (uint32_t)ptr; /* destination memory */
|
||||
|
||||
DMA1_CSELR->CSELR &= ~DMA_CSELR_C1S; /* 0000: select ADC for DMA CH 1 (this is reset default) */
|
||||
DMA1_CSELR->CSELR &= ~DMA_CSELR_C2S; /* 0000: select ADC for DMA CH 2 (this is reset default) */
|
||||
|
||||
DMA1_Channel1->CCR |= DMA_CCR_MINC; /* increment memory */
|
||||
DMA1_Channel1->CCR |= DMA_CCR_MSIZE_0; /* 01: 16 Bit access */
|
||||
DMA1_Channel1->CCR |= DMA_CCR_PSIZE_0; /* 01: 16 Bit access */
|
||||
|
||||
DMA1_Channel1->CCR |= DMA_CCR_EN; /* enable */
|
||||
|
||||
|
||||
/*
|
||||
detect rising edge on external trigger (ADC_CFGR1_EXTEN_0)
|
||||
recive trigger from TIM2 (ADC_CFGR1_EXTSEL_1)
|
||||
8 Bit resolution (ADC_CFGR1_RES_1)
|
||||
|
||||
Use DMA one shot mode and enable DMA (ADC_CFGR1_DMAEN)
|
||||
Once DMA is finished, it will disable continues mode (ADC_CFGR1_CONT)
|
||||
*/
|
||||
|
||||
|
||||
}
|
||||
|
||||
/*=======================================================================*/
|
||||
|
||||
|
||||
int main()
|
||||
{
|
||||
uint8_t v = 0;
|
||||
//setHSIClock(); /* enable 32 MHz Clock */
|
||||
SystemCoreClockUpdate();
|
||||
startUp(); /* enable systick irq and several power regions */
|
||||
initDisplay(); /* aktivate display */
|
||||
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE9; /* clear mode */
|
||||
GPIOA->MODER |= GPIO_MODER_MODE9_0; /* Output mode */
|
||||
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_9; /* no open drain */
|
||||
GPIOA->OSPEEDR &= ~GPIO_OSPEEDER_OSPEED9; /* low speed */
|
||||
GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEED9_1; /* 10 MHz */
|
||||
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD9; /* no pullup/pulldown */
|
||||
GPIOA->BSRR = GPIO_BSRR_BR_9; /* atomic clear */
|
||||
|
||||
|
||||
|
||||
for(;;)
|
||||
{
|
||||
GPIOA->BSRR = GPIO_BSRR_BR_9; /* atomic clear */
|
||||
|
||||
u8g2_SetFont(&u8g2, u8g2_font_6x12_tf);
|
||||
//u8g2_SetContrast(&u8g2, v);
|
||||
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_SetFont(&u8g2, u8g2_font_9x15B_tf);
|
||||
u8g2_DrawStr(&u8g2, 0,50, u8x8_u8toa(v, 3));
|
||||
|
||||
GPIOA->BSRR = GPIO_BSRR_BS_9; /* atomic clear */
|
||||
|
||||
u8g2_SendBuffer(&u8g2);
|
||||
v++;
|
||||
}
|
||||
return 0;
|
||||
}
|
BIN
sys/arm/stm32l031x4/u8g2_test/stm32l031.jpg
Normal file
BIN
sys/arm/stm32l031x4/u8g2_test/stm32l031.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 249 KiB |
245
sys/arm/stm32l031x4/u8g2_test/stm32l031x4.ld
Normal file
245
sys/arm/stm32l031x4/u8g2_test/stm32l031x4.ld
Normal file
@ -0,0 +1,245 @@
|
||||
/*
|
||||
|
||||
stm32l031x4.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 = 16K
|
||||
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")
|
||||
}
|
317
sys/arm/stm32l031x4/u8g2_test/u8x8cb.c
Normal file
317
sys/arm/stm32l031x4/u8g2_test/u8x8cb.c
Normal file
@ -0,0 +1,317 @@
|
||||
/*
|
||||
u8x8cb.c
|
||||
|
||||
STM32L031
|
||||
|
||||
|
||||
*/
|
||||
|
||||
#include "stm32l031xx.h"
|
||||
#include "delay.h"
|
||||
#include "u8x8.h"
|
||||
|
||||
/*
|
||||
I2C:
|
||||
PA9: Clock
|
||||
PA10: Data
|
||||
*/
|
||||
|
||||
uint8_t u8x8_gpio_and_delay_stm32l0_sw_i2c(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;
|
||||
}
|
||||
|
||||
/*
|
||||
SPI:
|
||||
PA14: CD
|
||||
PA13: CS
|
||||
PA7: MOSI
|
||||
PA6: Reset
|
||||
PA5: SCK
|
||||
*/
|
||||
|
||||
uint8_t u8x8_gpio_and_delay_stm32l0_spi(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();
|
||||
|
||||
/* setup PA14, PA13, PA7, PA6, PA5 */
|
||||
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE14; /* clear mode */
|
||||
GPIOA->MODER |= GPIO_MODER_MODE14_0; /* Output mode */
|
||||
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_14; /* no open drain */
|
||||
GPIOA->OSPEEDR &= ~GPIO_OSPEEDER_OSPEED14; /* low speed */
|
||||
GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEED14_1; /* 10 MHz */
|
||||
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD14; /* no pullup/pulldown */
|
||||
GPIOA->BSRR = GPIO_BSRR_BR_14; /* atomic clear */
|
||||
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE13; /* clear mode */
|
||||
GPIOA->MODER |= GPIO_MODER_MODE13_0; /* Output mode */
|
||||
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_13; /* no open drain */
|
||||
GPIOA->OSPEEDR &= ~GPIO_OSPEEDER_OSPEED13; /* low speed */
|
||||
GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEED13_1; /* 10 MHz */
|
||||
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD13; /* no pullup/pulldown */
|
||||
GPIOA->BSRR = GPIO_BSRR_BR_13; /* atomic clear */
|
||||
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE7; /* clear mode */
|
||||
GPIOA->MODER |= GPIO_MODER_MODE7_0; /* Output mode */
|
||||
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_7; /* no open drain */
|
||||
GPIOA->OSPEEDR &= ~GPIO_OSPEEDER_OSPEED7; /* low speed */
|
||||
GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEED7_1; /* 10 MHz */
|
||||
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD7; /* no pullup/pulldown */
|
||||
GPIOA->BSRR = GPIO_BSRR_BR_7; /* atomic clear */
|
||||
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE6; /* clear mode */
|
||||
GPIOA->MODER |= GPIO_MODER_MODE6_0; /* Output mode */
|
||||
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_6; /* no open drain */
|
||||
GPIOA->OSPEEDR &= ~GPIO_OSPEEDER_OSPEED6; /* low speed */
|
||||
GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEED6_1; /* 10 MHz */
|
||||
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD6; /* no pullup/pulldown */
|
||||
GPIOA->BSRR = GPIO_BSRR_BR_6; /* atomic clear */
|
||||
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE5; /* clear mode */
|
||||
GPIOA->MODER |= GPIO_MODER_MODE5_0; /* Output mode */
|
||||
GPIOA->OTYPER &= ~GPIO_OTYPER_OT_5; /* no open drain */
|
||||
GPIOA->OSPEEDR &= ~GPIO_OSPEEDER_OSPEED5; /* low speed */
|
||||
GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEED5_1; /* 10 MHz */
|
||||
GPIOA->PUPDR &= ~GPIO_PUPDR_PUPD5; /* no pullup/pulldown */
|
||||
GPIOA->BSRR = GPIO_BSRR_BR_5; /* atomic clear */
|
||||
|
||||
break;
|
||||
case U8X8_MSG_DELAY_NANO:
|
||||
/* required for SPI, but seems to work without any delay (at least with 2MHz system clock) */
|
||||
//delay_micro_seconds(1);
|
||||
break;
|
||||
|
||||
case U8X8_MSG_DELAY_10MICRO:
|
||||
delay_micro_seconds(arg_int*10UL);
|
||||
break;
|
||||
|
||||
case U8X8_MSG_DELAY_100NANO:
|
||||
/* not used at the moment */
|
||||
delay_micro_seconds((arg_int+9)/10);
|
||||
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_SPI_CLOCK:
|
||||
if ( arg_int == 0 )
|
||||
GPIOA->BSRR = GPIO_BSRR_BR_5; /* atomic clr */
|
||||
else
|
||||
GPIOA->BSRR = GPIO_BSRR_BS_5; /* atomic set */
|
||||
break;
|
||||
|
||||
case U8X8_MSG_GPIO_SPI_DATA:
|
||||
if ( arg_int == 0 )
|
||||
GPIOA->BSRR = GPIO_BSRR_BR_7; /* atomic clr */
|
||||
else
|
||||
GPIOA->BSRR = GPIO_BSRR_BS_7; /* atomic set */
|
||||
break;
|
||||
|
||||
case U8X8_MSG_GPIO_CS: // CS (chip select) pin: Output level in arg_int
|
||||
if ( arg_int == 0 )
|
||||
GPIOA->BSRR = GPIO_BSRR_BR_13; /* atomic clr */
|
||||
else
|
||||
GPIOA->BSRR = GPIO_BSRR_BS_13; /* atomic set */
|
||||
break;
|
||||
|
||||
case U8X8_MSG_GPIO_DC: // DC (data/cmd, A0, register select) pin: Output level in arg_int
|
||||
if ( arg_int == 0 )
|
||||
GPIOA->BSRR = GPIO_BSRR_BR_14; /* atomic clr */
|
||||
else
|
||||
GPIOA->BSRR = GPIO_BSRR_BS_14; /* atomic set */
|
||||
break;
|
||||
|
||||
case U8X8_MSG_GPIO_RESET: // Reset pin: Output level in arg_int/*
|
||||
if ( arg_int == 0 )
|
||||
GPIOA->BSRR = GPIO_BSRR_BR_6; /* atomic clr */
|
||||
else
|
||||
GPIOA->BSRR = GPIO_BSRR_BS_6; /* atomic set */
|
||||
break;
|
||||
|
||||
default:
|
||||
u8x8_SetGPIOResult(u8x8, 1);
|
||||
break;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
uint8_t u8x8_byte_stm32l0_hw_spi(u8x8_t *u8x8, uint8_t msg, uint8_t arg_int, void *arg_ptr)
|
||||
{
|
||||
uint8_t *data;
|
||||
switch(msg) {
|
||||
case U8X8_MSG_BYTE_SEND:
|
||||
data = (uint8_t *)arg_ptr;
|
||||
while( arg_int > 0 )
|
||||
{
|
||||
while( ( SPI1->SR & SPI_SR_TXE ) == 0 )
|
||||
;
|
||||
*(uint8_t *)&(SPI1->DR) = *data;
|
||||
data++;
|
||||
arg_int--;
|
||||
}
|
||||
break;
|
||||
case U8X8_MSG_BYTE_INIT:
|
||||
/* enable clock for SPI */
|
||||
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN; /* enable SPI1 */
|
||||
/* set a predivision if the system clock is too high, not required for 2MHz */
|
||||
RCC->CFGR &= ~RCC_CFGR_PPRE2_Msk;
|
||||
//RCC->CFGR |= RCC_CFGR_PPRE2_DIV4;
|
||||
|
||||
/* output setup is already done, just enable the alternate mode here */
|
||||
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE7; /* clear mode */
|
||||
GPIOA->MODER |= GPIO_MODER_MODE7_1; /* Alternate function mode */
|
||||
GPIOA->AFR[0] &= ~GPIO_AFRL_AFRL7_Msk; /* clear af mode */
|
||||
GPIOA->AFR[0] |= 0 << GPIO_AFRL_AFRL7_Pos; /* assign af mode (which is 0 for SPI) */
|
||||
|
||||
GPIOA->MODER &= ~GPIO_MODER_MODE5; /* clear mode */
|
||||
GPIOA->MODER |= GPIO_MODER_MODE5_1; /* Alternate function mode */
|
||||
GPIOA->AFR[0] &= ~GPIO_AFRL_AFRL5_Msk; /* clear af mode */
|
||||
GPIOA->AFR[0] |= 0 << GPIO_AFRL_AFRL5_Pos; /* assign af mode (which is 0 for SPI) */
|
||||
|
||||
/* setup and enable SPI subsystem */
|
||||
/* Note: We assume SPI mode 0 for the displays (true for the most modern displays), so CPHA and CPOL are forced to 0 here. SPI mode is here: u8x8->display_info->spi_mode */
|
||||
|
||||
SPI1->CR1 = SPI_CR1_MSTR // master
|
||||
//| SPI_CR1_BIDIMODE
|
||||
//| SPI_CR1_BIDIOE
|
||||
| SPI_CR1_SSM
|
||||
| SPI_CR1_SSI
|
||||
//| SPI_CR1_BR_0
|
||||
//| SPI_CR1_BR_1
|
||||
//| SPI_CR1_BR_2 // speed
|
||||
//| SPI_CR1_CPHA
|
||||
//| SPI_CR1_CPOL
|
||||
;
|
||||
SPI1->CR2 = 0; // SPI_CR2_TXDMAEN = transmit DMA enable
|
||||
SPI1->CR1 |= SPI_CR1_SPE; // SPI enable
|
||||
|
||||
u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
|
||||
break;
|
||||
case U8X8_MSG_BYTE_SET_DC:
|
||||
while ( SPI1->SR & SPI_SR_BSY ) // wait for transfer completion
|
||||
;
|
||||
u8x8_gpio_SetDC(u8x8, arg_int);
|
||||
break;
|
||||
case U8X8_MSG_BYTE_START_TRANSFER:
|
||||
u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_enable_level);
|
||||
u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->post_chip_enable_wait_ns, NULL);
|
||||
break;
|
||||
case U8X8_MSG_BYTE_END_TRANSFER:
|
||||
while ( SPI1->SR & SPI_SR_BSY ) // wait for transfer completion
|
||||
;
|
||||
u8x8->gpio_and_delay_cb(u8x8, U8X8_MSG_DELAY_NANO, u8x8->display_info->pre_chip_disable_wait_ns, NULL);
|
||||
u8x8_gpio_SetCS(u8x8, u8x8->display_info->chip_disable_level);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user