mirror of
https://github.com/eddyem/stm32samples.git
synced 2026-03-22 01:31:21 +03:00
rename G0:G070
This commit is contained in:
8
G0:G070,G0B1/RTC/Makefile
Normal file
8
G0:G070,G0B1/RTC/Makefile
Normal file
@@ -0,0 +1,8 @@
|
||||
BINARY := rtc
|
||||
# MCU code
|
||||
MCU := G070xx
|
||||
# change this linking script depending on particular MCU model,
|
||||
LDSCRIPT := stm32g070xb.ld
|
||||
|
||||
include ../makefile.g0
|
||||
include ../../makefile.stm32
|
||||
164
G0:G070,G0B1/RTC/Makefile.old
Normal file
164
G0:G070,G0B1/RTC/Makefile.old
Normal file
@@ -0,0 +1,164 @@
|
||||
BINARY = rtc
|
||||
BOOTPORT ?= /dev/ttyUSB0
|
||||
BOOTSPEED ?= 115200
|
||||
# MCU FAMILY
|
||||
FAMILY = G0
|
||||
# MCU code
|
||||
MCU = G070xx
|
||||
#DEFS = -DEBUG -g3
|
||||
# change this linking script depending on particular MCU model,
|
||||
# for example, if you have STM32F103VBT6, you should write:
|
||||
LDSCRIPT = stm32g070xb.ld
|
||||
|
||||
INDEPENDENT_HEADERS=
|
||||
|
||||
FP_FLAGS ?= -msoft-float
|
||||
ASM_FLAGS = -mthumb -mcpu=cortex-m0plus -march=armv6-m -mtune=cortex-m0plus
|
||||
ARCH_FLAGS = $(ASM_FLAGS) $(FP_FLAGS)
|
||||
|
||||
# autoincremental version & build date
|
||||
VERSION_FILE = version.inc
|
||||
ifeq ($(shell test -e $(VERSION_FILE) && echo -n yes), yes)
|
||||
NEXTVER := $(shell expr $$(awk '/#define BUILD_NUMBER/' $(VERSION_FILE) | tr -cd "[0-9]") + 1)
|
||||
else
|
||||
NEXTVER := "1"
|
||||
endif
|
||||
|
||||
BUILDDATE := $(shell date +%Y-%m-%d)
|
||||
|
||||
###############################################################################
|
||||
# Executables
|
||||
PREFIX ?= /opt/bin/arm-none-eabi
|
||||
|
||||
RM := rm -f
|
||||
RMDIR := rmdir
|
||||
SIZE := $(PREFIX)-size
|
||||
CC := $(PREFIX)-gcc
|
||||
LD := $(PREFIX)-gcc
|
||||
AR := $(PREFIX)-ar
|
||||
AS := $(PREFIX)-as
|
||||
OBJCOPY := $(PREFIX)-objcopy
|
||||
OBJDUMP := $(PREFIX)-objdump
|
||||
GDB := $(PREFIX)-gdb
|
||||
STFLASH := $(shell which st-flash)
|
||||
STBOOT := $(shell which stm32flash)
|
||||
|
||||
###############################################################################
|
||||
# Source files
|
||||
OBJDIR = mk
|
||||
LDSCRIPT ?= $(BINARY).ld
|
||||
SRC := $(wildcard *.c)
|
||||
OBJS := $(addprefix $(OBJDIR)/, $(SRC:%.c=%.o))
|
||||
STARTUP = $(OBJDIR)/startup.o
|
||||
OBJS += $(STARTUP)
|
||||
DEPS := $(OBJS:.o=.d)
|
||||
|
||||
INC_DIR ?= ../inc
|
||||
|
||||
INCLUDE := -I$(INC_DIR)/Fx -I$(INC_DIR)/cm
|
||||
LIB_DIR := $(INC_DIR)/ld
|
||||
|
||||
###############################################################################
|
||||
# C flags
|
||||
CFLAGS += -O2 -MD -D__thumb2__=1
|
||||
CFLAGS += -Wall -Werror -Wextra -Wshadow -Wimplicit-function-declaration
|
||||
CFLAGS += -Wredundant-decls $(INCLUDE)
|
||||
# -Wmissing-prototypes -Wstrict-prototypes
|
||||
CFLAGS += -fno-common -ffunction-sections -fdata-sections -flto
|
||||
|
||||
###############################################################################
|
||||
# Linker flags
|
||||
LDFLAGS += --static -nostartfiles --specs=nano.specs -flto
|
||||
LDFLAGS += -L$(LIB_DIR)
|
||||
LDFLAGS += -T$(LDSCRIPT)
|
||||
LDFLAGS += -Wl,-Map=$(OBJDIR)/$(BINARY).map
|
||||
LDFLAGS += -Wl,--gc-sections
|
||||
|
||||
###############################################################################
|
||||
# Used libraries
|
||||
LDLIBS += -Wl,--start-group -lc -lgcc -Wl,--end-group
|
||||
LDLIBS += $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
|
||||
|
||||
DEFS += -DSTM32$(FAMILY) -DSTM32$(MCU)
|
||||
|
||||
#.SUFFIXES: .elf .bin .hex .srec .list .map .images
|
||||
#.SECONDEXPANSION:
|
||||
#.SECONDARY:
|
||||
|
||||
ELF := $(OBJDIR)/$(BINARY).elf
|
||||
LIST := $(OBJDIR)/$(BINARY).list
|
||||
BIN := $(BINARY).bin
|
||||
HEX := $(BINARY).hex
|
||||
|
||||
all: bin list size
|
||||
|
||||
elf: $(ELF)
|
||||
bin: $(BIN)
|
||||
hex: $(HEX)
|
||||
list: $(LIST)
|
||||
|
||||
ifneq ($(MAKECMDGOALS),clean)
|
||||
-include $(DEPS)
|
||||
endif
|
||||
|
||||
$(OBJDIR):
|
||||
mkdir $(OBJDIR)
|
||||
|
||||
$(STARTUP): $(INC_DIR)/startup/vector.c
|
||||
$(CC) $(CFLAGS) $(DEFS) $(INCLUDE) $(ARCH_FLAGS) -o $@ -c $<
|
||||
|
||||
$(VERSION_FILE): *.[ch]
|
||||
[ -f $(VERSION_FILE) ] || echo -e "#define BUILD_NUMBER \"0\"\n#define BUILD_DATE \"none\"" > $(VERSION_FILE)
|
||||
@echo " Generate version: $(NEXTVER) for date $(BUILDDATE)"
|
||||
@sed -i "s/#define BUILD_NUMBER.*/#define BUILD_NUMBER \"$(NEXTVER)\"/" $(VERSION_FILE)
|
||||
@sed -i "s/#define BUILD_DATE.*/#define BUILD_DATE \"$(BUILDDATE)\"/" $(VERSION_FILE)
|
||||
|
||||
# Uncomment and rename file, which includes version.inc
|
||||
#$(OBJDIR)/proto.o: proto.c $(VERSION_FILE)
|
||||
|
||||
$(OBJDIR)/%.o: %.c
|
||||
@echo " CC $<"
|
||||
$(CC) $(CFLAGS) $(DEFS) $(INCLUDE) $(ARCH_FLAGS) -o $@ -c $<
|
||||
|
||||
#$(OBJDIR)/%.d: %.c $(OBJDIR)
|
||||
# $(CC) -MM -MG $< | sed -e 's,^\([^:]*\)\.o[ ]*:,$(@D)/\1.o $(@D)/\1.d:,' >$@
|
||||
|
||||
$(BIN): $(ELF)
|
||||
@echo " OBJCOPY $(BIN)"
|
||||
$(OBJCOPY) -Obinary $(ELF) $(BIN)
|
||||
|
||||
$(HEX): $(ELF)
|
||||
@echo " OBJCOPY $(HEX)"
|
||||
$(OBJCOPY) -Oihex $(ELF) $(HEX)
|
||||
|
||||
$(LIST): $(ELF)
|
||||
@echo " OBJDUMP $(LIST)"
|
||||
$(OBJDUMP) -S $(ELF) > $(LIST)
|
||||
|
||||
$(ELF): $(OBJDIR) $(OBJS)
|
||||
@echo " LD $(ELF)"
|
||||
$(LD) $(LDFLAGS) $(ARCH_FLAGS) $(OBJS) $(LDLIBS) -o $(ELF)
|
||||
|
||||
clean:
|
||||
@echo " CLEAN"
|
||||
$(RM) $(OBJS) $(DEPS) $(ELF) $(HEX) $(LIST) $(OBJDIR)/*.map
|
||||
@rmdir $(OBJDIR) 2>/dev/null || true
|
||||
|
||||
size: $(ELF)
|
||||
$(SIZE) -Ax $(ELF)
|
||||
|
||||
flash: $(BIN)
|
||||
@echo " FLASH $(BIN)"
|
||||
$(STFLASH) write $(BIN) 0x8000000
|
||||
|
||||
boot: $(BIN)
|
||||
@echo " LOAD $(BIN) through bootloader"
|
||||
$(STBOOT) -b$(BOOTSPEED) $(BOOTPORT) -w $(BIN)
|
||||
|
||||
openocd:
|
||||
openocd -f openocd.cfg
|
||||
dbg:
|
||||
arm-none-eabi-gdb $(ELF) -ex 'target extended-remote localhost:3333' -ex 'monitor reset halt'
|
||||
|
||||
|
||||
.PHONY: clean flash boot size openocd dbg
|
||||
12
G0:G070,G0B1/RTC/README
Normal file
12
G0:G070,G0B1/RTC/README
Normal file
@@ -0,0 +1,12 @@
|
||||
Simplest work with RTC
|
||||
|
||||
Proto:
|
||||
|
||||
C - set/print calibration ticks (-511..+512) to each 2^20 ticks
|
||||
Sd - set date (YY MM DD Weekday)
|
||||
St - set time (HH MM SS)
|
||||
t - print current Tms
|
||||
T - print current Time
|
||||
|
||||
Button press - print current time @ usart3
|
||||
|
||||
71
G0:G070,G0B1/RTC/main.c
Normal file
71
G0:G070,G0B1/RTC/main.c
Normal file
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* This file is part of the rtc project.
|
||||
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stm32g0.h>
|
||||
|
||||
#include "proto.h"
|
||||
#include "rtc.h"
|
||||
#include "strfunc.h"
|
||||
#include "usart.h"
|
||||
|
||||
// KEY (intpullup->0) - PC0
|
||||
// LED - PC8
|
||||
|
||||
volatile uint32_t Tms = 0;
|
||||
|
||||
/* Called when systick fires */
|
||||
void sys_tick_handler(void){
|
||||
++Tms;
|
||||
}
|
||||
|
||||
static void gpio_setup(void){
|
||||
RCC->IOPENR |= RCC_IOPENR_GPIOCEN; // enable PC
|
||||
// set PC8 as opendrain output, PC0 is pullup input, other as default (AIN)
|
||||
GPIOC->MODER = (0xffffffff & ~(GPIO_MODER_MODE8 | GPIO_MODER_MODE0)) | GPIO_MODER_MODER8_O;
|
||||
GPIOC->PUPDR = GPIO_PUPDR0_PU; // pullup
|
||||
GPIOC->OTYPER = GPIO_OTYPER_OT8; // open drain
|
||||
}
|
||||
|
||||
int main(void){
|
||||
StartHSE();
|
||||
rtc_setup();
|
||||
SysTick_Config(8000); // 1ms counter
|
||||
gpio_setup();
|
||||
usart3_setup();
|
||||
uint32_t T = 0;
|
||||
int sent = 0;
|
||||
/* Do nothing in main loop */
|
||||
while (1){
|
||||
if(Tms - T > 499){ // blink LED
|
||||
T = Tms;
|
||||
pin_toggle(GPIOC, 1<<8);
|
||||
usart3_sendbuf();
|
||||
}
|
||||
if(pin_read(GPIOC, 1<<0) == 0){ // key pressed - send time over USART
|
||||
if(!sent){
|
||||
print_curtime();
|
||||
sent = 1;
|
||||
}
|
||||
}else sent = 0;
|
||||
int wasbo = 0;
|
||||
char *rcv = usart3_getline(&wasbo);
|
||||
if(wasbo) usart3_sendstr("Buffer overflow occured @ last message\n");
|
||||
if(rcv) rcv = (char*)parse_cmd(rcv);
|
||||
if(rcv) usart3_sendstr(rcv);
|
||||
}
|
||||
}
|
||||
89
G0:G070,G0B1/RTC/openocd.cfg
Normal file
89
G0:G070,G0B1/RTC/openocd.cfg
Normal file
@@ -0,0 +1,89 @@
|
||||
# script for stm32g0x family
|
||||
|
||||
#
|
||||
# stm32g0 devices support SWD transports only.
|
||||
#
|
||||
source [find interface/stlink.cfg]
|
||||
source [find target/swj-dp.tcl]
|
||||
source [find mem_helper.tcl]
|
||||
|
||||
if { [info exists CHIPNAME] } {
|
||||
set _CHIPNAME $CHIPNAME
|
||||
} else {
|
||||
set _CHIPNAME stm32g0x
|
||||
}
|
||||
|
||||
set _ENDIAN little
|
||||
|
||||
# Work-area is a space in RAM used for flash programming
|
||||
# Smallest proposed target has 8kB ram, use 4kB by default to avoid surprises
|
||||
if { [info exists WORKAREASIZE] } {
|
||||
set _WORKAREASIZE $WORKAREASIZE
|
||||
} else {
|
||||
set _WORKAREASIZE 0x1000
|
||||
}
|
||||
|
||||
#jtag scan chain
|
||||
if { [info exists CPUTAPID] } {
|
||||
set _CPUTAPID $CPUTAPID
|
||||
} else {
|
||||
# Section 37.5.5 - corresponds to Cortex-M0+
|
||||
set _CPUTAPID 0x0bc11477
|
||||
}
|
||||
|
||||
swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID
|
||||
dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu
|
||||
|
||||
set _TARGETNAME $_CHIPNAME.cpu
|
||||
target create $_TARGETNAME cortex_m -endian $_ENDIAN -dap $_CHIPNAME.dap
|
||||
|
||||
$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0
|
||||
|
||||
set _FLASHNAME $_CHIPNAME.flash
|
||||
flash bank $_FLASHNAME stm32l4x 0 0 0 0 $_TARGETNAME
|
||||
|
||||
# reasonable default
|
||||
adapter speed 2000
|
||||
|
||||
adapter srst delay 100
|
||||
if {[using_jtag]} {
|
||||
jtag_ntrst_delay 100
|
||||
}
|
||||
|
||||
reset_config srst_nogate
|
||||
|
||||
if {![using_hla]} {
|
||||
# if srst is not fitted use SYSRESETREQ to
|
||||
# perform a soft reset
|
||||
cortex_m reset_config sysresetreq
|
||||
}
|
||||
|
||||
proc stm32g0x_default_reset_start {} {
|
||||
# Reset clock is HSI16 (16 MHz)
|
||||
adapter speed 2000
|
||||
}
|
||||
|
||||
proc stm32g0x_default_examine_end {} {
|
||||
# DBGMCU_CR |= DBG_STANDBY | DBG_STOP
|
||||
mmw 0x40015804 0x00000006 0
|
||||
|
||||
# Stop watchdog counters during halt
|
||||
# DBGMCU_APB1_FZ |= DBG_IWDG_STOP | DBG_WWDG_STOP
|
||||
mmw 0x40015808 0x00001800 0
|
||||
}
|
||||
|
||||
proc stm32g0x_default_reset_init {} {
|
||||
# Increase clock to 64 Mhz
|
||||
mmw 0x40022000 0x00000002 0x00000005 ;# FLASH_ACR: Latency = 2
|
||||
mww 0x4002100C 0x30000802 ;# RCC_PLLCFGR = PLLR=/2, PLLN=8, PLLM=/1, PLLSRC=0x2
|
||||
mmw 0x40021000 0x01000000 0x00000000 ;# RCC_CR |= PLLON
|
||||
mmw 0x40021008 0x00000002 0x00000005 ;# RCC_CFGR: SW=PLLRCLK
|
||||
|
||||
# Boost JTAG frequency
|
||||
adapter speed 4000
|
||||
}
|
||||
|
||||
# Default hooks
|
||||
$_TARGETNAME configure -event examine-end { stm32g0x_default_examine_end }
|
||||
$_TARGETNAME configure -event reset-start { stm32g0x_default_reset_start }
|
||||
$_TARGETNAME configure -event reset-init { stm32g0x_default_reset_init }
|
||||
149
G0:G070,G0B1/RTC/proto.c
Normal file
149
G0:G070,G0B1/RTC/proto.c
Normal file
@@ -0,0 +1,149 @@
|
||||
/*
|
||||
* This file is part of the rtc project.
|
||||
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stm32g0.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "rtc.h"
|
||||
#include "strfunc.h"
|
||||
#include "usart.h"
|
||||
|
||||
extern volatile uint32_t Tms;
|
||||
|
||||
const char *helpstring =
|
||||
"C - set/print calibration ticks (-511..+512) to each 2^20 ticks\n"
|
||||
"Sd - set date (YY MM DD Weekday)\n"
|
||||
"St - set time (HH MM SS)\n"
|
||||
"t - print current Tms\n"
|
||||
"T - print current Time\n"
|
||||
;
|
||||
|
||||
TRUE_INLINE void putch(char x){
|
||||
usart3_send(&x, 1);
|
||||
}
|
||||
|
||||
static const char *weekdays[] = {"Mon", "Tue", "Wed", "Thur", "Fri", "Sat", "Sun"};
|
||||
static const char *months[] = {"Jan", "Feb", "Mar", "Apr", "May", "June", "July", "Aug", "Sept", "Oct", "Nov", "Dec"};
|
||||
static const char *OK = "OK\n";
|
||||
|
||||
static void prezero(uint8_t x){
|
||||
if(x < 10){ putch('0'); putch('0' + x);}
|
||||
else USND(u2str(x));
|
||||
}
|
||||
|
||||
void print_curtime(){
|
||||
rtc_t t;
|
||||
get_curtime(&t);
|
||||
USND(weekdays[t.weekday - 1]);
|
||||
putch(' ');
|
||||
USND(months[t.month - 1]);
|
||||
putch(' ');
|
||||
USND(u2str(t.day));
|
||||
putch(' ');
|
||||
prezero(t.hour);
|
||||
putch(':');
|
||||
prezero(t.minute);
|
||||
putch(':');
|
||||
prezero(t.second);
|
||||
USND(" 20"); prezero(t.year);
|
||||
putch('\n');
|
||||
}
|
||||
|
||||
static int readNu8(const char *buf, uint8_t *arr, int maxlen){
|
||||
uint32_t D;
|
||||
const char *nxt;
|
||||
int N = 0;
|
||||
while((nxt = getnum(buf, &D)) && nxt != buf && N < maxlen){
|
||||
buf = nxt;
|
||||
if(D > 0xff){
|
||||
USND("Value too large\n");
|
||||
return N;
|
||||
}
|
||||
arr[N++] = (uint8_t) D&0xff;
|
||||
}
|
||||
return N;
|
||||
}
|
||||
|
||||
TRUE_INLINE const char* setdatetime(const char *buf){
|
||||
buf = omit_spaces(buf);
|
||||
uint8_t array[4];
|
||||
rtc_t r;
|
||||
switch(*buf){
|
||||
case 'd': // set date
|
||||
if(4 != readNu8(buf+1, array, 4))
|
||||
return "Format: YY MM DD Weekday (monday is 1)\n";
|
||||
r.year = array[0];
|
||||
r.month = array[1];
|
||||
r.day = array[2];
|
||||
r.weekday = array[3];
|
||||
if(!rtc_setdate(&r)) return "Wrong date format\n";
|
||||
break;
|
||||
case 't': // set time
|
||||
if(3 != readNu8(buf+1, array, 3))
|
||||
return "Format: HH MM SS\n";
|
||||
r.hour = array[0];
|
||||
r.minute = array[1];
|
||||
r.second = array[2];
|
||||
if(!rtc_settime(&r)) return "Wrong time format\n";
|
||||
break;
|
||||
default:
|
||||
return "Sd -> set date; St -> set time\n";
|
||||
}
|
||||
return OK;
|
||||
}
|
||||
|
||||
TRUE_INLINE const char *setcal(const char *buf){
|
||||
int32_t v;
|
||||
if(buf == getint(buf, &v)){
|
||||
USND("Calibration value: ");
|
||||
USND(i2str(rtc_getcalib()));
|
||||
putch('\n');
|
||||
return NULL;
|
||||
}
|
||||
if(!rtc_setcalib(v)) return "Enter value: -511..+512\n";
|
||||
return OK;
|
||||
}
|
||||
|
||||
const char *parse_cmd(char *buf){
|
||||
const char *x = omit_spaces(buf);
|
||||
// "long" commands
|
||||
switch(*x){
|
||||
case 'S':
|
||||
return setdatetime(x + 1);
|
||||
break;
|
||||
case 'C':
|
||||
return setcal(x + 1);
|
||||
break;
|
||||
}
|
||||
// "short" commands
|
||||
if(x[1]) return x; // echo wrong data
|
||||
switch(*x){
|
||||
case 't':
|
||||
USND("T=");
|
||||
USND(u2str(Tms));
|
||||
putch('\n');
|
||||
break;
|
||||
case 'T':
|
||||
print_curtime();
|
||||
break;
|
||||
default: // help
|
||||
USND(helpstring);
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
22
G0:G070,G0B1/RTC/proto.h
Normal file
22
G0:G070,G0B1/RTC/proto.h
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* This file is part of the rtc project.
|
||||
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
const char *parse_cmd(char *buf);
|
||||
void print_curtime();
|
||||
BIN
G0:G070,G0B1/RTC/rtc.bin
Executable file
BIN
G0:G070,G0B1/RTC/rtc.bin
Executable file
Binary file not shown.
136
G0:G070,G0B1/RTC/rtc.c
Normal file
136
G0:G070,G0B1/RTC/rtc.c
Normal file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* This file is part of the rtc project.
|
||||
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stm32g0.h>
|
||||
|
||||
#include "rtc.h"
|
||||
|
||||
#ifndef WAITWHILE
|
||||
#define WAITWHILE(x) do{register uint32_t StartUpCounter = 0; while((x) && (++StartUpCounter < 0xffffff)){nop();}}while(0)
|
||||
#endif
|
||||
|
||||
static const uint8_t maxdays[12] = {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
|
||||
|
||||
// i - in, r - rest of divide
|
||||
#if 0
|
||||
static uint16_t div10s(uint16_t i, uint16_t *r){ // divide by 10
|
||||
uint32_t u = i;
|
||||
u *= 52429;
|
||||
u >>= 19;
|
||||
if(r) *r = i - 10*u;
|
||||
return (uint16_t)u;
|
||||
}
|
||||
#endif
|
||||
static uint8_t div10b(uint8_t i, uint8_t *r){ // divide by 10
|
||||
uint32_t u = i;
|
||||
u *= 52429;
|
||||
u >>= 19;
|
||||
if(r) *r = i - 10*u;
|
||||
return (uint8_t)u;
|
||||
}
|
||||
|
||||
static uint8_t DEC2BCD(uint8_t x){
|
||||
uint8_t d, r;
|
||||
d = div10b(x, &r);
|
||||
return (d << 4 | r);
|
||||
}
|
||||
|
||||
int rtc_setdate(rtc_t *d){
|
||||
if(d->year > 99) return FALSE;
|
||||
if(d->month > 12 || d->month == 0) return FALSE;
|
||||
if(d->day > maxdays[d->month - 1] || d->day == 0) return FALSE;
|
||||
if(d->month == 2 && d->day == 29){
|
||||
uint8_t test = (d->year >> 2) << 2;
|
||||
if(d->year != test) return FALSE; // not leap year
|
||||
}
|
||||
if(d->weekday > 7 || d->weekday == 0) return FALSE;
|
||||
RTC->ICSR |= RTC_ICSR_INIT;
|
||||
WAITWHILE(!(RTC->ICSR & RTC_ICSR_INITF));
|
||||
RTC->DR = DEC2BCD(d->year) << RTC_DR_YU_Pos | d->weekday << RTC_DR_WDU_Pos | DEC2BCD(d->month) << RTC_DR_MU_Pos | DEC2BCD(d->day) << RTC_DR_DU_Pos;
|
||||
RTC->ICSR &= ~RTC_ICSR_INIT;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
int rtc_settime(rtc_t *t){
|
||||
if(t->hour > 23) return FALSE;
|
||||
if(t->minute > 59) return FALSE;
|
||||
if(t->second > 59) return FALSE;
|
||||
RTC->ICSR |= RTC_ICSR_INIT;
|
||||
WAITWHILE(!(RTC->ICSR & RTC_ICSR_INITF));
|
||||
RTC->TR = DEC2BCD(t->hour) << RTC_TR_HU_Pos | DEC2BCD(t->minute) << RTC_TR_MNU_Pos | DEC2BCD(t->second) << RTC_TR_SU_Pos;
|
||||
RTC->ICSR &= ~RTC_ICSR_INIT;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void rtc_setup(){
|
||||
PWR->CR1 |= PWR_CR1_DBP; // disable RTC write protection
|
||||
// turn on LSE and switch RTC to it
|
||||
RCC->APBENR1 |= RCC_APBENR1_RTCAPBEN;
|
||||
RCC->BDCR = RCC_BDCR_LSEON;
|
||||
WAITWHILE(!(RCC->BDCR & RCC_BDCR_LSERDY));
|
||||
RCC->BDCR |= RCC_BDCR_RTCEN | RCC_BDCR_RTCSEL_0;
|
||||
// unlock RCC
|
||||
RTC->WPR = 0xCA;
|
||||
RTC->WPR = 0x53;
|
||||
RTC->ICSR |= RTC_ICSR_INIT;
|
||||
WAITWHILE(!(RTC->ICSR & RTC_ICSR_INITF));
|
||||
RTC->PRER = (0x7f << RTC_PRER_PREDIV_A_Pos) | 0xff; // prediv_a = 127, prediv_s = 255
|
||||
// here we can init starting time: monday of 1 jan 2001, 00:00:00
|
||||
// RTC->DR = 1 << RTC_DR_YU_Pos | 1 << RTC_DR_WDU_Pos | 1 << RTC_DR_MU_Pos | 1 << RTC_DR_DU_Pos;
|
||||
// RTC->TR = 0;
|
||||
// RTC->CR is default - 0
|
||||
// now turn off INIT bit, RTC will go on
|
||||
RTC->ICSR &= ~RTC_ICSR_INIT;
|
||||
}
|
||||
|
||||
void get_curtime(rtc_t *t){
|
||||
WAITWHILE(!(RTC->ICSR & RTC_ICSR_RSF));
|
||||
register uint32_t r = RTC->TR;
|
||||
#define BCDu(shift) ((r >> shift) & 0xf)
|
||||
t->second = BCDu(RTC_TR_SU_Pos) + 10 * BCDu(RTC_TR_ST_Pos);
|
||||
t->minute = BCDu(RTC_TR_MNU_Pos) + 10 * BCDu(RTC_TR_MNT_Pos);
|
||||
t->hour = BCDu(RTC_TR_HU_Pos) + 10 * BCDu(RTC_TR_HT_Pos);
|
||||
r = RTC->DR;
|
||||
t->day = BCDu(RTC_DR_DU_Pos) + 10 * BCDu(RTC_DR_DT_Pos);
|
||||
t->month = BCDu(RTC_DR_MU_Pos);
|
||||
if(r & RTC_DR_MT) t->month += 10;
|
||||
t->weekday = (r >> RTC_DR_WDU_Pos) & 0x7;
|
||||
t->year = BCDu(RTC_DR_YU_Pos) + 10 * BCDu(RTC_DR_YT_Pos);
|
||||
}
|
||||
|
||||
// set calibration value
|
||||
int rtc_setcalib(int calval){
|
||||
if(calval < -511 || calval > 512) return FALSE;
|
||||
uint32_t calp = 0, calm = 0;
|
||||
if(calval < 0) calm = -calval;
|
||||
else if(calval > 0){
|
||||
calp = RTC_CALR_CALP;
|
||||
calm = 512 - calval;
|
||||
}
|
||||
// unlock RCC
|
||||
RTC->WPR = 0xCA;
|
||||
RTC->WPR = 0x53;
|
||||
RTC->CALR = calp | calm;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int rtc_getcalib(){
|
||||
int calval = (RTC->CALR & RTC_CALR_CALP) ? 512 : 0;
|
||||
calval -= RTC->CALR & 0x1ff;
|
||||
return calval;
|
||||
}
|
||||
1
G0:G070,G0B1/RTC/rtc.cflags
Normal file
1
G0:G070,G0B1/RTC/rtc.cflags
Normal file
@@ -0,0 +1 @@
|
||||
-std=c17
|
||||
3
G0:G070,G0B1/RTC/rtc.config
Normal file
3
G0:G070,G0B1/RTC/rtc.config
Normal file
@@ -0,0 +1,3 @@
|
||||
#define EBUG
|
||||
#define STM32G0
|
||||
#define STM32G070xx
|
||||
1
G0:G070,G0B1/RTC/rtc.creator
Normal file
1
G0:G070,G0B1/RTC/rtc.creator
Normal file
@@ -0,0 +1 @@
|
||||
[General]
|
||||
171
G0:G070,G0B1/RTC/rtc.creator.user
Normal file
171
G0:G070,G0B1/RTC/rtc.creator.user
Normal file
@@ -0,0 +1,171 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE QtCreatorProject>
|
||||
<!-- Written by QtCreator 8.0.2, 2022-12-22T21:13:47. -->
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>EnvironmentId</variable>
|
||||
<value type="QByteArray">{7bd84e39-ca37-46d3-be9d-99ebea85bc0d}</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.ActiveTarget</variable>
|
||||
<value type="int">0</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.EditorSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
|
||||
<value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
|
||||
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
|
||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
|
||||
<value type="QString" key="language">Cpp</value>
|
||||
<valuemap type="QVariantMap" key="value">
|
||||
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
|
||||
<value type="QString" key="language">QmlJS</value>
|
||||
<valuemap type="QVariantMap" key="value">
|
||||
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
<value type="int" key="EditorConfiguration.CodeStyle.Count">2</value>
|
||||
<value type="QByteArray" key="EditorConfiguration.Codec">KOI8-R</value>
|
||||
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
|
||||
<value type="int" key="EditorConfiguration.IndentSize">4</value>
|
||||
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
|
||||
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
|
||||
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
|
||||
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
|
||||
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
|
||||
<value type="bool" key="EditorConfiguration.PreferSingleLineComments">false</value>
|
||||
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
|
||||
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
|
||||
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
|
||||
<value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
|
||||
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
|
||||
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
|
||||
<value type="int" key="EditorConfiguration.TabSize">8</value>
|
||||
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
|
||||
<value type="bool" key="EditorConfiguration.UseIndenter">false</value>
|
||||
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
|
||||
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanIndentation">false</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
|
||||
<value type="QString" key="EditorConfiguration.ignoreFileTypes">*.md, *.MD, Makefile</value>
|
||||
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
|
||||
<value type="bool" key="EditorConfiguration.skipTrailingWhitespace">true</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.PluginSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<valuemap type="QVariantMap" key="AutoTest.ActiveFrameworks">
|
||||
<value type="bool" key="AutoTest.Framework.Boost">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.CTest">false</value>
|
||||
<value type="bool" key="AutoTest.Framework.Catch">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.GTest">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.QtQuickTest">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.QtTest">true</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="AutoTest.CheckStates"/>
|
||||
<value type="int" key="AutoTest.RunAfterBuild">0</value>
|
||||
<value type="bool" key="AutoTest.UseGlobal">true</value>
|
||||
<valuemap type="QVariantMap" key="ClangTools">
|
||||
<value type="bool" key="ClangTools.AnalyzeOpenFiles">true</value>
|
||||
<value type="bool" key="ClangTools.BuildBeforeAnalysis">true</value>
|
||||
<value type="QString" key="ClangTools.DiagnosticConfig">Builtin.DefaultTidyAndClazy</value>
|
||||
<value type="int" key="ClangTools.ParallelJobs">2</value>
|
||||
<valuelist type="QVariantList" key="ClangTools.SelectedDirs"/>
|
||||
<valuelist type="QVariantList" key="ClangTools.SelectedFiles"/>
|
||||
<valuelist type="QVariantList" key="ClangTools.SuppressedDiagnostics"/>
|
||||
<value type="bool" key="ClangTools.UseGlobalSettings">true</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Target.0</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="QString" key="DeviceType">Desktop</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{65a14f9e-e008-4c1b-89df-4eaa4774b6e3}</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/Big/Data/00__Electronics/STM32/G0-nolib/rtc</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<valuelist type="QVariantList" key="GenericProjectManager.GenericMakeStep.BuildTargets">
|
||||
<value type="QString">all</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">GenericProjectManager.GenericMakeStep</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Сборка</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Сборка</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<valuelist type="QVariantList" key="GenericProjectManager.GenericMakeStep.BuildTargets">
|
||||
<value type="QString">clean</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">GenericProjectManager.GenericMakeStep</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Очистка</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Очистка</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">По умолчанию</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">GenericProjectManager.GenericBuildConfiguration</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Развёртывание</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Развёртывание</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.CustomExecutableRunConfiguration</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey"></value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.TargetCount</variable>
|
||||
<value type="int">1</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
|
||||
<value type="int">22</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>Version</variable>
|
||||
<value type="int">22</value>
|
||||
</data>
|
||||
</qtcreator>
|
||||
1
G0:G070,G0B1/RTC/rtc.cxxflags
Normal file
1
G0:G070,G0B1/RTC/rtc.cxxflags
Normal file
@@ -0,0 +1 @@
|
||||
-std=c++17
|
||||
11
G0:G070,G0B1/RTC/rtc.files
Normal file
11
G0:G070,G0B1/RTC/rtc.files
Normal file
@@ -0,0 +1,11 @@
|
||||
main.c
|
||||
rtc.c
|
||||
rtc.h
|
||||
usart.c
|
||||
usart.h
|
||||
strfunc.c
|
||||
strfunc.h
|
||||
proto.c
|
||||
proto.h
|
||||
i2c.c
|
||||
i2c.h
|
||||
40
G0:G070,G0B1/RTC/rtc.h
Normal file
40
G0:G070,G0B1/RTC/rtc.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* This file is part of the rtc project.
|
||||
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
// time, day of week (1 - monday), and date (1 - january)
|
||||
typedef struct{
|
||||
uint8_t second;
|
||||
uint8_t minute;
|
||||
uint8_t hour;
|
||||
uint8_t weekday;
|
||||
uint8_t day;
|
||||
uint8_t month;
|
||||
uint8_t year;
|
||||
} rtc_t;
|
||||
|
||||
void rtc_setup();
|
||||
|
||||
void get_curtime(rtc_t *t);
|
||||
int rtc_setdate(rtc_t *d);
|
||||
int rtc_settime(rtc_t *t);
|
||||
int rtc_setcalib(int calval);
|
||||
int rtc_getcalib();
|
||||
4
G0:G070,G0B1/RTC/rtc.includes
Normal file
4
G0:G070,G0B1/RTC/rtc.includes
Normal file
@@ -0,0 +1,4 @@
|
||||
.
|
||||
../inc
|
||||
../inc/Fx
|
||||
../inc/cm
|
||||
274
G0:G070,G0B1/RTC/strfunc.c
Normal file
274
G0:G070,G0B1/RTC/strfunc.c
Normal file
@@ -0,0 +1,274 @@
|
||||
/*
|
||||
* This file is part of the rtc project.
|
||||
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stm32g0.h>
|
||||
|
||||
/**
|
||||
* @brief hexdump - dump hex array by 16 bytes in string
|
||||
* @param sendfun - function to send data
|
||||
* @param arr - array to dump
|
||||
* @param len - length of `arr`
|
||||
*/
|
||||
void hexdump(int (*sendfun)(const char *s), uint8_t *arr, uint16_t len){
|
||||
char buf[52], *bptr = buf;
|
||||
for(uint16_t l = 0; l < len; ++l, ++arr){
|
||||
for(int16_t j = 1; j > -1; --j){
|
||||
register uint8_t half = (*arr >> (4*j)) & 0x0f;
|
||||
if(half < 10) *bptr++ = half + '0';
|
||||
else *bptr++ = half - 10 + 'a';
|
||||
}
|
||||
if(l % 16 == 15){
|
||||
*bptr++ = '\n';
|
||||
*bptr = 0;
|
||||
sendfun(buf);
|
||||
bptr = buf;
|
||||
}else *bptr++ = ' ';
|
||||
}
|
||||
if(bptr != buf){
|
||||
*bptr++ = '\n';
|
||||
*bptr = 0;
|
||||
sendfun(buf);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief _2str - convert value into string buffer
|
||||
* @param val - |value|
|
||||
* @param minus - ==0 if value > 0
|
||||
* @return buffer with number
|
||||
*/
|
||||
static char *_2str(uint32_t val, uint8_t minus){
|
||||
static char strbuf[12];
|
||||
char *bufptr = &strbuf[11];
|
||||
*bufptr = 0;
|
||||
if(!val){
|
||||
*(--bufptr) = '0';
|
||||
}else{
|
||||
while(val){
|
||||
uint32_t x = val / 10;
|
||||
*(--bufptr) = (val - 10*x) + '0';
|
||||
val = x;
|
||||
//*(--bufptr) = val % 10 + '0';
|
||||
//val /= 10;
|
||||
}
|
||||
}
|
||||
if(minus) *(--bufptr) = '-';
|
||||
return bufptr;
|
||||
}
|
||||
|
||||
// return string with number `val`
|
||||
char *u2str(uint32_t val){
|
||||
return _2str(val, 0);
|
||||
}
|
||||
char *i2str(int32_t i){
|
||||
uint8_t minus = 0;
|
||||
uint32_t val;
|
||||
if(i < 0){
|
||||
minus = 1;
|
||||
val = -i;
|
||||
}else val = i;
|
||||
return _2str(val, minus);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief uhex2str - print 32bit unsigned int as hex
|
||||
* @param val - value
|
||||
* @return string with number
|
||||
*/
|
||||
char *uhex2str(uint32_t val){
|
||||
static char buf[12] = "0x";
|
||||
int npos = 2;
|
||||
uint8_t *ptr = (uint8_t*)&val + 3;
|
||||
int8_t i, j, z=1;
|
||||
for(i = 0; i < 4; ++i, --ptr){
|
||||
if(*ptr == 0){ // omit leading zeros
|
||||
if(i == 3) z = 0;
|
||||
if(z) continue;
|
||||
}
|
||||
else z = 0;
|
||||
for(j = 1; j > -1; --j){
|
||||
uint8_t half = (*ptr >> (4*j)) & 0x0f;
|
||||
if(half < 10) buf[npos++] = half + '0';
|
||||
else buf[npos++] = half - 10 + 'a';
|
||||
}
|
||||
}
|
||||
buf[npos] = 0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief omit_spaces - eliminate leading spaces and other trash in string
|
||||
* @param buf - string
|
||||
* @return - pointer to first character in `buf` > ' '
|
||||
*/
|
||||
const char *omit_spaces(const char *buf){
|
||||
while(*buf){
|
||||
if(*buf > ' ') break;
|
||||
++buf;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief getdec - read decimal number & return pointer to next non-number symbol
|
||||
* @param buf - string
|
||||
* @param N - number read
|
||||
* @return Next non-number symbol. In case of overflow return `buf` and N==0xffffffff
|
||||
*/
|
||||
static const char *getdec(const char *buf, uint32_t *N){
|
||||
char *start = (char*)buf;
|
||||
uint32_t num = 0;
|
||||
while(*buf){
|
||||
char c = *buf;
|
||||
if(c < '0' || c > '9'){
|
||||
break;
|
||||
}
|
||||
if(num > 429496729 || (num == 429496729 && c > '5')){ // overflow
|
||||
*N = 0xffffff;
|
||||
return start;
|
||||
}
|
||||
num *= 10;
|
||||
num += c - '0';
|
||||
++buf;
|
||||
}
|
||||
*N = num;
|
||||
return buf;
|
||||
}
|
||||
// read hexadecimal number (without 0x prefix!)
|
||||
static const char *gethex(const char *buf, uint32_t *N){
|
||||
const char *start = buf;
|
||||
uint32_t num = 0;
|
||||
while(*buf){
|
||||
char c = *buf;
|
||||
uint8_t M = 0;
|
||||
if(c >= '0' && c <= '9'){
|
||||
M = '0';
|
||||
}else if(c >= 'A' && c <= 'F'){
|
||||
M = 'A' - 10;
|
||||
}else if(c >= 'a' && c <= 'f'){
|
||||
M = 'a' - 10;
|
||||
}
|
||||
if(M){
|
||||
if(num & 0xf0000000){ // overflow
|
||||
*N = 0xffffff;
|
||||
return start;
|
||||
}
|
||||
num <<= 4;
|
||||
num += c - M;
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
++buf;
|
||||
}
|
||||
*N = num;
|
||||
return buf;
|
||||
}
|
||||
// read octal number (without 0 prefix!)
|
||||
static const char *getoct(const char *buf, uint32_t *N){
|
||||
const char *start = (char*)buf;
|
||||
uint32_t num = 0;
|
||||
while(*buf){
|
||||
char c = *buf;
|
||||
if(c < '0' || c > '7'){
|
||||
break;
|
||||
}
|
||||
if(num & 0xe0000000){ // overflow
|
||||
*N = 0xffffff;
|
||||
return start;
|
||||
}
|
||||
num <<= 3;
|
||||
num += c - '0';
|
||||
++buf;
|
||||
}
|
||||
*N = num;
|
||||
return buf;
|
||||
}
|
||||
// read binary number (without b prefix!)
|
||||
static const char *getbin(const char *buf, uint32_t *N){
|
||||
const char *start = (char*)buf;
|
||||
uint32_t num = 0;
|
||||
while(*buf){
|
||||
char c = *buf;
|
||||
if(c < '0' || c > '1'){
|
||||
break;
|
||||
}
|
||||
if(num & 0x80000000){ // overflow
|
||||
*N = 0xffffff;
|
||||
return start;
|
||||
}
|
||||
num <<= 1;
|
||||
if(c == '1') num |= 1;
|
||||
++buf;
|
||||
}
|
||||
*N = num;
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief getnum - read uint32_t from string (dec, hex or bin: 127, 0x7f, 0b1111111)
|
||||
* @param buf - buffer with number and so on
|
||||
* @param N - the number read
|
||||
* @return pointer to first non-number symbol in buf
|
||||
* (if it is == buf, there's no number or if *N==0xffffffff there was overflow)
|
||||
*/
|
||||
const char *getnum(const char *txt, uint32_t *N){
|
||||
const char *nxt = NULL;
|
||||
const char *s = omit_spaces(txt);
|
||||
if(*s == '0'){ // hex, oct or 0
|
||||
if(s[1] == 'x' || s[1] == 'X'){ // hex
|
||||
nxt = gethex(s+2, N);
|
||||
if(nxt == s+2) nxt = (char*)txt;
|
||||
}else if(s[1] > '0'-1 && s[1] < '8'){ // oct
|
||||
nxt = getoct(s+1, N);
|
||||
if(nxt == s+1) nxt = (char*)txt;
|
||||
}else{ // 0
|
||||
nxt = s+1;
|
||||
*N = 0;
|
||||
}
|
||||
}else if(*s == 'b' || *s == 'B'){
|
||||
nxt = getbin(s+1, N);
|
||||
if(nxt == s+1) nxt = (char*)txt;
|
||||
}else{
|
||||
nxt = getdec(s, N);
|
||||
if(nxt == s) nxt = (char*)txt;
|
||||
}
|
||||
return nxt;
|
||||
}
|
||||
|
||||
// get signed integer
|
||||
const char *getint(const char *txt, int32_t *I){
|
||||
const char *s = omit_spaces(txt);
|
||||
int32_t sign = 1;
|
||||
uint32_t U;
|
||||
if(*s == '-'){
|
||||
sign = -1;
|
||||
++s;
|
||||
}
|
||||
const char *nxt = getnum(s, &U);
|
||||
if(nxt == s) return txt;
|
||||
if(U & 0x80000000) return txt; // overfull
|
||||
*I = sign * (int32_t)U;
|
||||
return nxt;
|
||||
}
|
||||
|
||||
/*
|
||||
void mymemcpy(char *dest, const char *src, int len){
|
||||
if(len < 1) return;
|
||||
while(len--) *dest++ = *src++;
|
||||
}
|
||||
*/
|
||||
30
G0:G070,G0B1/RTC/strfunc.h
Normal file
30
G0:G070,G0B1/RTC/strfunc.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* This file is part of the rtc project.
|
||||
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string.h>
|
||||
|
||||
void hexdump(int (*sendfun)(const char *s), uint8_t *arr, uint16_t len);
|
||||
const char *u2str(uint32_t val);
|
||||
const char *i2str(int32_t i);
|
||||
const char *uhex2str(uint32_t val);
|
||||
const char *getnum(const char *txt, uint32_t *N);
|
||||
const char *omit_spaces(const char *buf);
|
||||
const char *getint(const char *txt, int32_t *I);
|
||||
//void mymemcpy(char *dest, const char *src, int len);
|
||||
177
G0:G070,G0B1/RTC/usart.c
Normal file
177
G0:G070,G0B1/RTC/usart.c
Normal file
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* This file is part of the rtc project.
|
||||
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stm32g0.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "usart.h"
|
||||
|
||||
// RX/TX DMA->CCR without EN flag
|
||||
#define DMARXCCR (DMA_CCR_MINC | DMA_CCR_TCIE | DMA_CCR_TEIE)
|
||||
#define DMATXCCR (DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_TCIE | DMA_CCR_TEIE)
|
||||
|
||||
volatile int u3txrdy = 1, u3rxrdy = 0; // transmission done, next line received
|
||||
static volatile int bufovr = 0, wasbufovr = 0; // Rx buffer overflow or error flag -> delete next line
|
||||
static volatile int rbufno = 0, tbufno = 0; // current buf number
|
||||
static volatile char rbuf[2][UARTBUFSZ], tbuf[2][UARTBUFSZ]; // receive & transmit buffers
|
||||
static volatile int rxlen[2] = {0}, txlen[2] = {0};
|
||||
|
||||
char *usart3_getline(int *wasbo){
|
||||
if(wasbo) *wasbo = wasbufovr;
|
||||
wasbufovr = 0;
|
||||
if(!u3rxrdy) return NULL;
|
||||
u3rxrdy = 0; // clear ready flag
|
||||
return (char*)rbuf[!rbufno]; // current buffer is in filling stage, return old - filled - buffer
|
||||
}
|
||||
|
||||
#define USART_BRR(speed) ((64000000 + speed/2) / speed)
|
||||
|
||||
// USART3 @ PD8 (Tx) and PD9 (Rx) - both AF0
|
||||
void usart3_setup(){
|
||||
RCC->IOPENR |= RCC_IOPENR_GPIODEN; // enable PD
|
||||
RCC->AHBENR |= RCC_AHBENR_DMA1EN; // enable DMA1
|
||||
// set PD8 and PD9 as AF
|
||||
GPIOD->MODER = (GPIOD->MODER & ~(GPIO_MODER_MODE8 | GPIO_MODER_MODE9))
|
||||
| GPIO_MODER_MODER8_AF | GPIO_MODER_MODER9_AF;
|
||||
// AF0 for USART3 @ PD8/PD9
|
||||
GPIOD->AFR[1] = GPIOD->AFR[1] & ~(GPIO_AFRH_AFSEL8 | GPIO_AFRH_AFSEL9);
|
||||
// enable USART3 clocking
|
||||
RCC->APBENR1 |= RCC_APBENR1_USART3EN;
|
||||
// baudrate 115200
|
||||
USART3->BRR = USART_BRR(115200);
|
||||
// eol character: '/n'
|
||||
USART3->CR2 = USART_CR2_ADD_VAL('\n');
|
||||
// enable DMA transmission
|
||||
USART3->CR3 = USART_CR3_DMAT | USART_CR3_DMAR;
|
||||
// set up DMA channels: 2 - Tx, 3 - Rx
|
||||
// Tx channel: mem++, mem->periph, 8bit, compl.&err. irq
|
||||
DMA1_Channel2->CCR = DMATXCCR;
|
||||
DMA1_Channel2->CPAR = (uint32_t) &USART3->TDR; // peripherial address
|
||||
// Rx channel: mem++, periph->mem, 8bit, compl.&err. irq
|
||||
DMA1_Channel3->CCR = DMARXCCR;
|
||||
DMA1_Channel3->CPAR = (uint32_t) &USART3->RDR; // peripherial address
|
||||
DMA1_Channel3->CNDTR = UARTBUFSZ;
|
||||
DMA1_Channel3->CMAR = (uint32_t)&rbuf[rbufno];
|
||||
// set up DMAMUX channels: 55 - USART3_TX, 54 - USART3_RX
|
||||
// enumeration of DMAMUX starts from 0 (DMA - from 1)!
|
||||
DMAMUX1_Channel1->CCR = 55;
|
||||
DMAMUX1_Channel2->CCR = 54;
|
||||
// charmatch interrupt, enable transmitter and receiver, enable usart
|
||||
USART3->CR1 = USART_CR1_CMIE | USART_CR1_TE | USART_CR1_RE | USART_CR1_UE;
|
||||
USART3->ICR = 0xffffffff; // clear all flags
|
||||
DMA1_Channel3->CCR = DMARXCCR | DMA_CCR_EN; // start receiving right now
|
||||
NVIC_EnableIRQ(USART3_4_IRQn);
|
||||
NVIC_EnableIRQ(DMA1_Channel2_3_IRQn);
|
||||
}
|
||||
|
||||
static int usart3_sendN(const char *str, int len){
|
||||
int rest = UARTBUFSZ - txlen[tbufno];
|
||||
if(rest == 0 && !u3txrdy) return 0; // buffer is full while transmission in process
|
||||
if(len < rest) rest = len;
|
||||
memcpy((char*)(tbuf[tbufno] + txlen[tbufno]), str, rest);
|
||||
txlen[tbufno] += rest;
|
||||
if(!u3txrdy) return rest;
|
||||
if(txlen[tbufno] == UARTBUFSZ) usart3_sendbuf();
|
||||
if(rest == len) return len;
|
||||
len -= rest;
|
||||
// now fill another - empty - buffer
|
||||
if(len > UARTBUFSZ) len = UARTBUFSZ;
|
||||
memcpy((char*)tbuf[tbufno], str + rest, len);
|
||||
txlen[tbufno] = len;
|
||||
return rest + len;
|
||||
}
|
||||
|
||||
void usart3_send(const char *str, int len){
|
||||
while(len){
|
||||
int sent = usart3_sendN(str, len);
|
||||
str += sent;
|
||||
len -= sent;
|
||||
}
|
||||
}
|
||||
|
||||
void usart3_sendstr(const char *str){
|
||||
int l = strlen(str);
|
||||
usart3_send(str, l);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usart3_sendbuf - send current buffer
|
||||
*/
|
||||
void usart3_sendbuf(){
|
||||
if(!u3txrdy || txlen[tbufno] == 0) return;
|
||||
// set up DMA
|
||||
DMA1_Channel2->CCR = DMATXCCR;
|
||||
DMA1_Channel2->CMAR = (uint32_t)&tbuf[tbufno];
|
||||
DMA1_Channel2->CNDTR = txlen[tbufno];
|
||||
USART3->ICR = USART_ICR_TCCF; // clear TC flag
|
||||
u3txrdy = 0;
|
||||
// activate DMA
|
||||
DMA1_Channel2->CCR = DMATXCCR | DMA_CCR_EN;
|
||||
tbufno = !tbufno; // swap buffers
|
||||
txlen[tbufno] = 0;
|
||||
}
|
||||
|
||||
// return amount of bytes sents
|
||||
int usart3_send_blocking(const char *str, int len){
|
||||
if(!u3txrdy) return 0;
|
||||
USART3->CR1 |= USART_CR1_TE;
|
||||
for(int i = 0; i < len; ++i){
|
||||
while(!(USART3->ISR & USART_ISR_TXE_TXFNF));
|
||||
USART3->TDR = *str++;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
// interrupt by '\n'
|
||||
void usart3_4_isr(){
|
||||
if(USART3->ISR & USART_ISR_CMF){ // got '\n' @ USART3
|
||||
DMA1_Channel3->CCR = DMARXCCR;
|
||||
if(!bufovr){ // forget about broken line @ buffer overflow
|
||||
u3rxrdy = 1;
|
||||
int l = UARTBUFSZ - DMA1_Channel3->CNDTR - 1; // strlen
|
||||
rxlen[rbufno] = l;
|
||||
rbuf[rbufno][l] = 0;
|
||||
rbufno = !rbufno;
|
||||
}else{
|
||||
bufovr = 0;
|
||||
wasbufovr = 1;
|
||||
}
|
||||
// reload DMA Rx with next buffer
|
||||
DMA1_Channel3->CMAR = (uint32_t)&rbuf[rbufno];
|
||||
DMA1_Channel3->CNDTR = UARTBUFSZ;
|
||||
DMA1_Channel3->CCR = DMARXCCR | DMA_CCR_EN;
|
||||
}
|
||||
USART3->ICR = 0xffffffff; // clear all flags
|
||||
}
|
||||
|
||||
// ch2 - Tx, ch3 - Rx
|
||||
void dma1_channel2_3_isr(){
|
||||
uint32_t isr = DMA1->ISR;
|
||||
if(isr & (DMA_ISR_TCIF2 | DMA_ISR_TEIF2)){ // transfer complete or error
|
||||
u3txrdy = 1;
|
||||
}
|
||||
if(isr & (DMA_ISR_TCIF3 | DMA_ISR_TEIF3)){ // receive complete or error -> buffer overflow
|
||||
if(rbuf[rbufno][UARTBUFSZ-1] != '\n'){ // last symbol is not a newline
|
||||
bufovr = 1;
|
||||
DMA1_Channel3->CCR = DMARXCCR;
|
||||
DMA1_Channel3->CNDTR = UARTBUFSZ;
|
||||
DMA1_Channel3->CCR = DMARXCCR | DMA_CCR_EN;
|
||||
}
|
||||
}
|
||||
DMA1->IFCR = 0xff0; // clear all flags for 2&3
|
||||
}
|
||||
32
G0:G070,G0B1/RTC/usart.h
Normal file
32
G0:G070,G0B1/RTC/usart.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* This file is part of the rtc project.
|
||||
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define UARTBUFSZ (64)
|
||||
|
||||
#define USND(t) do{usart3_sendstr(t);}while(0)
|
||||
|
||||
extern volatile int u3txrdy, u3rxrdy;
|
||||
|
||||
void usart3_setup();
|
||||
int usart3_send_blocking(const char *str, int len);
|
||||
void usart3_send(const char *str, int len);
|
||||
void usart3_sendbuf();
|
||||
char *usart3_getline(int *wasbo);
|
||||
void usart3_sendstr(const char *str);
|
||||
2
G0:G070,G0B1/RTC/version.inc
Normal file
2
G0:G070,G0B1/RTC/version.inc
Normal file
@@ -0,0 +1,2 @@
|
||||
#define BUILD_NUMBER "1"
|
||||
#define BUILD_DATE "2023-01-18"
|
||||
9
G0:G070,G0B1/blink/Makefile
Normal file
9
G0:G070,G0B1/blink/Makefile
Normal file
@@ -0,0 +1,9 @@
|
||||
BINARY := blink
|
||||
# MCU code
|
||||
MCU := G070xx
|
||||
# change this linking script depending on particular MCU model,
|
||||
LDSCRIPT := stm32g070xb.ld
|
||||
|
||||
include ../makefile.g0
|
||||
include ../../makefile.stm32
|
||||
|
||||
145
G0:G070,G0B1/blink/Makefile.old
Normal file
145
G0:G070,G0B1/blink/Makefile.old
Normal file
@@ -0,0 +1,145 @@
|
||||
BINARY = blink
|
||||
BOOTPORT ?= /dev/ttyUSB0
|
||||
BOOTSPEED ?= 115200
|
||||
# MCU FAMILY
|
||||
FAMILY = G0
|
||||
# MCU code
|
||||
MCU = G070xx
|
||||
#DEFS = -DEBUG -g3
|
||||
# change this linking script depending on particular MCU model,
|
||||
# for example, if you have STM32F103VBT6, you should write:
|
||||
LDSCRIPT = stm32g070xb.ld
|
||||
|
||||
INDEPENDENT_HEADERS=
|
||||
|
||||
FP_FLAGS ?= -msoft-float
|
||||
ASM_FLAGS = -mthumb -mcpu=cortex-m0plus -march=armv6-m -mtune=cortex-m0plus
|
||||
ARCH_FLAGS = $(ASM_FLAGS) $(FP_FLAGS)
|
||||
|
||||
###############################################################################
|
||||
# Executables
|
||||
PREFIX ?= /opt/bin/arm-none-eabi
|
||||
|
||||
RM := rm -f
|
||||
RMDIR := rmdir
|
||||
SIZE := $(PREFIX)-size
|
||||
CC := $(PREFIX)-gcc
|
||||
LD := $(PREFIX)-gcc
|
||||
AR := $(PREFIX)-ar
|
||||
AS := $(PREFIX)-as
|
||||
OBJCOPY := $(PREFIX)-objcopy
|
||||
OBJDUMP := $(PREFIX)-objdump
|
||||
GDB := $(PREFIX)-gdb
|
||||
STFLASH := $(shell which st-flash)
|
||||
STBOOT := $(shell which stm32flash)
|
||||
|
||||
###############################################################################
|
||||
# Source files
|
||||
OBJDIR = mk
|
||||
LDSCRIPT ?= $(BINARY).ld
|
||||
SRC := $(wildcard *.c)
|
||||
OBJS := $(addprefix $(OBJDIR)/, $(SRC:%.c=%.o))
|
||||
STARTUP = $(OBJDIR)/startup.o
|
||||
OBJS += $(STARTUP)
|
||||
DEPS := $(OBJS:.o=.d)
|
||||
|
||||
INC_DIR ?= ../inc
|
||||
|
||||
INCLUDE := -I$(INC_DIR)/Fx -I$(INC_DIR)/cm
|
||||
LIB_DIR := $(INC_DIR)/ld
|
||||
|
||||
###############################################################################
|
||||
# C flags
|
||||
CFLAGS += -O2 -MD -D__thumb2__=1
|
||||
CFLAGS += -Wall -Werror -Wextra -Wshadow -Wimplicit-function-declaration
|
||||
CFLAGS += -Wredundant-decls $(INCLUDE)
|
||||
# -Wmissing-prototypes -Wstrict-prototypes
|
||||
CFLAGS += -fno-common -ffunction-sections -fdata-sections -flto
|
||||
|
||||
###############################################################################
|
||||
# Linker flags
|
||||
LDFLAGS += --static -nostartfiles --specs=nano.specs -flto
|
||||
LDFLAGS += -L$(LIB_DIR)
|
||||
LDFLAGS += -T$(LDSCRIPT)
|
||||
LDFLAGS += -Wl,-Map=$(OBJDIR)/$(BINARY).map
|
||||
LDFLAGS += -Wl,--gc-sections
|
||||
|
||||
###############################################################################
|
||||
# Used libraries
|
||||
LDLIBS += -Wl,--start-group -lc -lgcc -Wl,--end-group
|
||||
LDLIBS += $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
|
||||
|
||||
DEFS += -DSTM32$(FAMILY) -DSTM32$(MCU)
|
||||
|
||||
#.SUFFIXES: .elf .bin .hex .srec .list .map .images
|
||||
#.SECONDEXPANSION:
|
||||
#.SECONDARY:
|
||||
|
||||
ELF := $(OBJDIR)/$(BINARY).elf
|
||||
LIST := $(OBJDIR)/$(BINARY).list
|
||||
BIN := $(BINARY).bin
|
||||
HEX := $(BINARY).hex
|
||||
|
||||
all: bin list size
|
||||
|
||||
elf: $(ELF)
|
||||
bin: $(BIN)
|
||||
hex: $(HEX)
|
||||
list: $(LIST)
|
||||
|
||||
ifneq ($(MAKECMDGOALS),clean)
|
||||
-include $(DEPS)
|
||||
endif
|
||||
|
||||
$(OBJDIR):
|
||||
mkdir $(OBJDIR)
|
||||
|
||||
$(STARTUP): $(INC_DIR)/startup/vector.c
|
||||
$(CC) $(CFLAGS) $(DEFS) $(INCLUDE) $(ARCH_FLAGS) -o $@ -c $<
|
||||
|
||||
$(OBJDIR)/%.o: %.c
|
||||
@echo " CC $<"
|
||||
$(CC) $(CFLAGS) $(DEFS) $(INCLUDE) $(ARCH_FLAGS) -o $@ -c $<
|
||||
|
||||
#$(OBJDIR)/%.d: %.c $(OBJDIR)
|
||||
# $(CC) -MM -MG $< | sed -e 's,^\([^:]*\)\.o[ ]*:,$(@D)/\1.o $(@D)/\1.d:,' >$@
|
||||
|
||||
$(BIN): $(ELF)
|
||||
@echo " OBJCOPY $(BIN)"
|
||||
$(OBJCOPY) -Obinary $(ELF) $(BIN)
|
||||
|
||||
$(HEX): $(ELF)
|
||||
@echo " OBJCOPY $(HEX)"
|
||||
$(OBJCOPY) -Oihex $(ELF) $(HEX)
|
||||
|
||||
$(LIST): $(ELF)
|
||||
@echo " OBJDUMP $(LIST)"
|
||||
$(OBJDUMP) -S $(ELF) > $(LIST)
|
||||
|
||||
$(ELF): $(OBJDIR) $(OBJS)
|
||||
@echo " LD $(ELF)"
|
||||
$(LD) $(LDFLAGS) $(ARCH_FLAGS) $(OBJS) $(LDLIBS) -o $(ELF)
|
||||
|
||||
clean:
|
||||
@echo " CLEAN"
|
||||
$(RM) $(OBJS) $(DEPS) $(ELF) $(HEX) $(LIST) $(OBJDIR)/*.map
|
||||
@rmdir $(OBJDIR) 2>/dev/null || true
|
||||
|
||||
size: $(ELF)
|
||||
$(SIZE) -Ax $(ELF)
|
||||
|
||||
flash: $(BIN)
|
||||
@echo " FLASH $(BIN)"
|
||||
$(STFLASH) write $(BIN) 0x8000000
|
||||
|
||||
boot: $(BIN)
|
||||
@echo " LOAD $(BIN) through bootloader"
|
||||
$(STBOOT) -b$(BOOTSPEED) $(BOOTPORT) -w $(BIN)
|
||||
|
||||
openocd:
|
||||
openocd -f openocd.cfg
|
||||
dbg:
|
||||
arm-none-eabi-gdb $(ELF) -ex 'target remote localhost:3333' -ex 'monitor reset halt'
|
||||
|
||||
|
||||
.PHONY: clean flash boot size openocd dbg
|
||||
3
G0:G070,G0B1/blink/README
Normal file
3
G0:G070,G0B1/blink/README
Normal file
@@ -0,0 +1,3 @@
|
||||
Toggle LED on STM32G070-pill depending on user button:
|
||||
- pressed - 'SOS' in Morze
|
||||
- not pressed - blink with period of 1 second
|
||||
BIN
G0:G070,G0B1/blink/blink.bin
Executable file
BIN
G0:G070,G0B1/blink/blink.bin
Executable file
Binary file not shown.
1
G0:G070,G0B1/blink/blink.cflags
Normal file
1
G0:G070,G0B1/blink/blink.cflags
Normal file
@@ -0,0 +1 @@
|
||||
-std=c17
|
||||
3
G0:G070,G0B1/blink/blink.config
Normal file
3
G0:G070,G0B1/blink/blink.config
Normal file
@@ -0,0 +1,3 @@
|
||||
#define EBUG
|
||||
#define STM32G0
|
||||
#define STM32G070xx
|
||||
1
G0:G070,G0B1/blink/blink.creator
Normal file
1
G0:G070,G0B1/blink/blink.creator
Normal file
@@ -0,0 +1 @@
|
||||
[General]
|
||||
171
G0:G070,G0B1/blink/blink.creator.user
Normal file
171
G0:G070,G0B1/blink/blink.creator.user
Normal file
@@ -0,0 +1,171 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE QtCreatorProject>
|
||||
<!-- Written by QtCreator 8.0.2, 2022-12-22T21:13:47. -->
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>EnvironmentId</variable>
|
||||
<value type="QByteArray">{7bd84e39-ca37-46d3-be9d-99ebea85bc0d}</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.ActiveTarget</variable>
|
||||
<value type="int">0</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.EditorSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
|
||||
<value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
|
||||
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
|
||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
|
||||
<value type="QString" key="language">Cpp</value>
|
||||
<valuemap type="QVariantMap" key="value">
|
||||
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
|
||||
<value type="QString" key="language">QmlJS</value>
|
||||
<valuemap type="QVariantMap" key="value">
|
||||
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
<value type="int" key="EditorConfiguration.CodeStyle.Count">2</value>
|
||||
<value type="QByteArray" key="EditorConfiguration.Codec">KOI8-R</value>
|
||||
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
|
||||
<value type="int" key="EditorConfiguration.IndentSize">4</value>
|
||||
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
|
||||
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
|
||||
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
|
||||
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
|
||||
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
|
||||
<value type="bool" key="EditorConfiguration.PreferSingleLineComments">false</value>
|
||||
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
|
||||
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
|
||||
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
|
||||
<value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
|
||||
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
|
||||
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
|
||||
<value type="int" key="EditorConfiguration.TabSize">8</value>
|
||||
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
|
||||
<value type="bool" key="EditorConfiguration.UseIndenter">false</value>
|
||||
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
|
||||
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanIndentation">false</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
|
||||
<value type="QString" key="EditorConfiguration.ignoreFileTypes">*.md, *.MD, Makefile</value>
|
||||
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
|
||||
<value type="bool" key="EditorConfiguration.skipTrailingWhitespace">true</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.PluginSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<valuemap type="QVariantMap" key="AutoTest.ActiveFrameworks">
|
||||
<value type="bool" key="AutoTest.Framework.Boost">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.CTest">false</value>
|
||||
<value type="bool" key="AutoTest.Framework.Catch">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.GTest">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.QtQuickTest">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.QtTest">true</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="AutoTest.CheckStates"/>
|
||||
<value type="int" key="AutoTest.RunAfterBuild">0</value>
|
||||
<value type="bool" key="AutoTest.UseGlobal">true</value>
|
||||
<valuemap type="QVariantMap" key="ClangTools">
|
||||
<value type="bool" key="ClangTools.AnalyzeOpenFiles">true</value>
|
||||
<value type="bool" key="ClangTools.BuildBeforeAnalysis">true</value>
|
||||
<value type="QString" key="ClangTools.DiagnosticConfig">Builtin.DefaultTidyAndClazy</value>
|
||||
<value type="int" key="ClangTools.ParallelJobs">2</value>
|
||||
<valuelist type="QVariantList" key="ClangTools.SelectedDirs"/>
|
||||
<valuelist type="QVariantList" key="ClangTools.SelectedFiles"/>
|
||||
<valuelist type="QVariantList" key="ClangTools.SuppressedDiagnostics"/>
|
||||
<value type="bool" key="ClangTools.UseGlobalSettings">true</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Target.0</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="QString" key="DeviceType">Desktop</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{65a14f9e-e008-4c1b-89df-4eaa4774b6e3}</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/Big/Data/00__Electronics/STM32/G0-nolib/blink</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<valuelist type="QVariantList" key="GenericProjectManager.GenericMakeStep.BuildTargets">
|
||||
<value type="QString">all</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">GenericProjectManager.GenericMakeStep</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Сборка</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Сборка</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<valuelist type="QVariantList" key="GenericProjectManager.GenericMakeStep.BuildTargets">
|
||||
<value type="QString">clean</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">GenericProjectManager.GenericMakeStep</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Очистка</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Очистка</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">По умолчанию</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">GenericProjectManager.GenericBuildConfiguration</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Развёртывание</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Развёртывание</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.CustomExecutableRunConfiguration</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey"></value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.TargetCount</variable>
|
||||
<value type="int">1</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
|
||||
<value type="int">22</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>Version</variable>
|
||||
<value type="int">22</value>
|
||||
</data>
|
||||
</qtcreator>
|
||||
1
G0:G070,G0B1/blink/blink.cxxflags
Normal file
1
G0:G070,G0B1/blink/blink.cxxflags
Normal file
@@ -0,0 +1 @@
|
||||
-std=c++17
|
||||
1
G0:G070,G0B1/blink/blink.files
Normal file
1
G0:G070,G0B1/blink/blink.files
Normal file
@@ -0,0 +1 @@
|
||||
systick_blink.c
|
||||
4
G0:G070,G0B1/blink/blink.includes
Normal file
4
G0:G070,G0B1/blink/blink.includes
Normal file
@@ -0,0 +1,4 @@
|
||||
.
|
||||
../inc
|
||||
../inc/Fx
|
||||
../inc/cm
|
||||
89
G0:G070,G0B1/blink/openocd.cfg
Normal file
89
G0:G070,G0B1/blink/openocd.cfg
Normal file
@@ -0,0 +1,89 @@
|
||||
# script for stm32g0x family
|
||||
|
||||
#
|
||||
# stm32g0 devices support SWD transports only.
|
||||
#
|
||||
source [find interface/stlink.cfg]
|
||||
source [find target/swj-dp.tcl]
|
||||
source [find mem_helper.tcl]
|
||||
|
||||
if { [info exists CHIPNAME] } {
|
||||
set _CHIPNAME $CHIPNAME
|
||||
} else {
|
||||
set _CHIPNAME stm32g0x
|
||||
}
|
||||
|
||||
set _ENDIAN little
|
||||
|
||||
# Work-area is a space in RAM used for flash programming
|
||||
# Smallest proposed target has 8kB ram, use 4kB by default to avoid surprises
|
||||
if { [info exists WORKAREASIZE] } {
|
||||
set _WORKAREASIZE $WORKAREASIZE
|
||||
} else {
|
||||
set _WORKAREASIZE 0x1000
|
||||
}
|
||||
|
||||
#jtag scan chain
|
||||
if { [info exists CPUTAPID] } {
|
||||
set _CPUTAPID $CPUTAPID
|
||||
} else {
|
||||
# Section 37.5.5 - corresponds to Cortex-M0+
|
||||
set _CPUTAPID 0x0bc11477
|
||||
}
|
||||
|
||||
swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID
|
||||
dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu
|
||||
|
||||
set _TARGETNAME $_CHIPNAME.cpu
|
||||
target create $_TARGETNAME cortex_m -endian $_ENDIAN -dap $_CHIPNAME.dap
|
||||
|
||||
$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0
|
||||
|
||||
set _FLASHNAME $_CHIPNAME.flash
|
||||
flash bank $_FLASHNAME stm32l4x 0 0 0 0 $_TARGETNAME
|
||||
|
||||
# reasonable default
|
||||
adapter speed 2000
|
||||
|
||||
adapter srst delay 100
|
||||
if {[using_jtag]} {
|
||||
jtag_ntrst_delay 100
|
||||
}
|
||||
|
||||
reset_config srst_nogate
|
||||
|
||||
if {![using_hla]} {
|
||||
# if srst is not fitted use SYSRESETREQ to
|
||||
# perform a soft reset
|
||||
cortex_m reset_config sysresetreq
|
||||
}
|
||||
|
||||
proc stm32g0x_default_reset_start {} {
|
||||
# Reset clock is HSI16 (16 MHz)
|
||||
adapter speed 2000
|
||||
}
|
||||
|
||||
proc stm32g0x_default_examine_end {} {
|
||||
# DBGMCU_CR |= DBG_STANDBY | DBG_STOP
|
||||
mmw 0x40015804 0x00000006 0
|
||||
|
||||
# Stop watchdog counters during halt
|
||||
# DBGMCU_APB1_FZ |= DBG_IWDG_STOP | DBG_WWDG_STOP
|
||||
mmw 0x40015808 0x00001800 0
|
||||
}
|
||||
|
||||
proc stm32g0x_default_reset_init {} {
|
||||
# Increase clock to 64 Mhz
|
||||
mmw 0x40022000 0x00000002 0x00000005 ;# FLASH_ACR: Latency = 2
|
||||
mww 0x4002100C 0x30000802 ;# RCC_PLLCFGR = PLLR=/2, PLLN=8, PLLM=/1, PLLSRC=0x2
|
||||
mmw 0x40021000 0x01000000 0x00000000 ;# RCC_CR |= PLLON
|
||||
mmw 0x40021008 0x00000002 0x00000005 ;# RCC_CFGR: SW=PLLRCLK
|
||||
|
||||
# Boost JTAG frequency
|
||||
adapter speed 4000
|
||||
}
|
||||
|
||||
# Default hooks
|
||||
$_TARGETNAME configure -event examine-end { stm32g0x_default_examine_end }
|
||||
$_TARGETNAME configure -event reset-start { stm32g0x_default_reset_start }
|
||||
$_TARGETNAME configure -event reset-init { stm32g0x_default_reset_init }
|
||||
78
G0:G070,G0B1/blink/systick_blink.c
Normal file
78
G0:G070,G0B1/blink/systick_blink.c
Normal file
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* This file is part of the blink project.
|
||||
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "stm32g0.h"
|
||||
|
||||
// KEY (intpullup->0) - PC0
|
||||
// LED - PC8
|
||||
|
||||
static volatile uint32_t blink_ctr = 0;
|
||||
|
||||
/* Called when systick fires */
|
||||
void sys_tick_handler(void){
|
||||
++blink_ctr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up timer to fire every x milliseconds
|
||||
*/
|
||||
static void systick_setup(uint32_t xms){ // xms < 2098!!!
|
||||
static uint32_t curms = 0;
|
||||
if(curms == xms) return;
|
||||
// 8MHz - HCLK/8
|
||||
// this function also clears counter so it starts right away
|
||||
SysTick_Config(8000 * xms); // arg should be < 0xffffff, so ms should be < 2098
|
||||
curms = xms;
|
||||
}
|
||||
|
||||
|
||||
static void gpio_setup(void){
|
||||
RCC->IOPENR = RCC_IOPENR_GPIOCEN; // enable PC
|
||||
// set PC8 as opendrain output, PC0 is pullup input, other as default (AIN)
|
||||
GPIOC->MODER = (0xffffffff & ~(GPIO_MODER_MODE8 | GPIO_MODER_MODE0)) | GPIO_MODER_MODER8_O;
|
||||
GPIOC->PUPDR = GPIO_PUPDR0_PU; // pullup
|
||||
GPIOC->OTYPER = GPIO_OTYPER_OT8; // open drain
|
||||
}
|
||||
|
||||
static const uint32_t L[] = {125,100,125,100,125,200, 350,100,350,100,350,200, 125,100,125,100,125, 1000};
|
||||
|
||||
int main(void){
|
||||
StartHSE();
|
||||
gpio_setup();
|
||||
systick_setup(500);
|
||||
uint32_t M = 0;
|
||||
int pressed = 0;
|
||||
/* Do nothing in main loop */
|
||||
while (1){
|
||||
if(pin_read(GPIOC, 1<<0) == 0){ // key not pressed - 'sos'
|
||||
pressed = 1;
|
||||
systick_setup(L[M]);
|
||||
if(M & 1) pin_set(GPIOC, 1<<8);
|
||||
else pin_clear(GPIOC, 1<<8);
|
||||
if(++M == 18) M = 0;
|
||||
}else{ // key pressed - blink with period of 1s
|
||||
if(pressed){
|
||||
M = 0;
|
||||
pressed = 0;
|
||||
systick_setup(500);
|
||||
}
|
||||
if(blink_ctr & 1) pin_set(GPIOC, 1<<8);
|
||||
else pin_clear(GPIOC, 1<<8);
|
||||
}
|
||||
}
|
||||
}
|
||||
9
G0:G070,G0B1/flash/Makefile
Normal file
9
G0:G070,G0B1/flash/Makefile
Normal file
@@ -0,0 +1,9 @@
|
||||
BINARY := flash
|
||||
# MCU code
|
||||
MCU := G070xx
|
||||
# change this linking script depending on particular MCU model,
|
||||
LDSCRIPT := stm32g070xb.ld
|
||||
|
||||
include ../makefile.g0
|
||||
include ../../makefile.stm32
|
||||
|
||||
2
G0:G070,G0B1/flash/README
Normal file
2
G0:G070,G0B1/flash/README
Normal file
@@ -0,0 +1,2 @@
|
||||
USART3 @ PD8/PD9 (115200, 8N1)
|
||||
EEPROM in Flash emulation
|
||||
BIN
G0:G070,G0B1/flash/flash.bin
Executable file
BIN
G0:G070,G0B1/flash/flash.bin
Executable file
Binary file not shown.
198
G0:G070,G0B1/flash/flash.c
Normal file
198
G0:G070,G0B1/flash/flash.c
Normal file
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
* This file is part of the flash project.
|
||||
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stm32g0.h>
|
||||
#include <string.h> // memcpy
|
||||
#include "flash.h"
|
||||
#include "strfunc.h"
|
||||
#include "usart.h"
|
||||
|
||||
extern const uint32_t __varsstart, _BLOCKSIZE;
|
||||
|
||||
static const uint32_t blocksize = (uint32_t)&_BLOCKSIZE;
|
||||
|
||||
// max amount of Config records stored (will be recalculate in flashstorage_init()
|
||||
static uint32_t maxCnum = 1024 / sizeof(user_conf); // can't use blocksize here
|
||||
|
||||
#define DEFMF {.haveencoder = 1, .donthold = 1, .eswinv = 1, .keeppos = 1}
|
||||
|
||||
#define USERCONF_INITIALIZER { \
|
||||
.userconf_sz = sizeof(user_conf) \
|
||||
,.flagU16 = 0xabcd \
|
||||
,.flagU32 = 0xdeadbeef \
|
||||
,.str = "test string" \
|
||||
}
|
||||
|
||||
static int erase_flash(const void*, const void*);
|
||||
static int write2flash(const void*, const void*, uint32_t);
|
||||
// don't write `static` here, or get error:
|
||||
// 'memcpy' forming offset 8 is out of the bounds [0, 4] of object '__varsstart' with type 'uint32_t'
|
||||
const user_conf *Flash_Data = (const user_conf *)(&__varsstart);
|
||||
|
||||
user_conf the_conf = USERCONF_INITIALIZER;
|
||||
|
||||
static int currentconfidx = -1; // index of current configuration
|
||||
|
||||
/**
|
||||
* @brief binarySearch - binary search in flash for last non-empty cell
|
||||
* any struct searched should have its sizeof() @ the first field!!!
|
||||
* @param l - left index
|
||||
* @param r - right index (should be @1 less than last index!)
|
||||
* @param start - starting address
|
||||
* @param stor_size - size of structure to search
|
||||
* @return index of non-empty cell or -1
|
||||
*/
|
||||
static int binarySearch(int r, const uint8_t *start, int stor_size){
|
||||
int l = 0;
|
||||
while(r >= l){
|
||||
int mid = l + (r - l) / 2;
|
||||
const uint8_t *s = start + mid * stor_size;
|
||||
if(*((const uint16_t*)s) == stor_size){
|
||||
if(*((const uint16_t*)(s + stor_size)) == 0xffff){ // next is free
|
||||
return mid;
|
||||
}else{ // element is to the right
|
||||
l = mid + 1;
|
||||
}
|
||||
}else{ // element is to the left
|
||||
r = mid - 1;
|
||||
}
|
||||
}
|
||||
return -1; // not found
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief flashstorage_init - initialization of user conf storage
|
||||
* run in once @ start
|
||||
*/
|
||||
void flashstorage_init(){
|
||||
if(FLASH_SIZE > 0 && FLASH_SIZE < 20000){
|
||||
uint32_t flsz = FLASH_SIZE * blocksize; // size in bytes
|
||||
flsz -= (uint32_t)(&__varsstart) - FLASH_BASE;
|
||||
maxCnum = flsz / sizeof(user_conf);
|
||||
}
|
||||
// -1 if there's no data at all & flash is clear; maxnum-1 if flash is full
|
||||
currentconfidx = binarySearch((int)maxCnum-2, (const uint8_t*)Flash_Data, sizeof(user_conf));
|
||||
if(currentconfidx > -1){
|
||||
memcpy(&the_conf, &Flash_Data[currentconfidx], sizeof(user_conf));
|
||||
}
|
||||
}
|
||||
|
||||
// store new configuration
|
||||
// @return 0 if all OK
|
||||
int store_userconf(){
|
||||
// maxnum - 3 means that there always should be at least one empty record after last data
|
||||
// for binarySearch() checking that there's nothing more after it!
|
||||
if(currentconfidx > (int)maxCnum - 3){ // there's no more place
|
||||
currentconfidx = 0;
|
||||
if(erase_flash(Flash_Data, NULL)) return 1;
|
||||
}else ++currentconfidx; // take next data position (0 - within first run after firmware flashing)
|
||||
return write2flash((const void*)&Flash_Data[currentconfidx], &the_conf, sizeof(the_conf));
|
||||
}
|
||||
|
||||
static int write2flash(const void *start, const void *wrdata, uint32_t stor_size){
|
||||
int ret = 0;
|
||||
if (FLASH->CR & FLASH_CR_LOCK){ // unloch flash
|
||||
FLASH->KEYR = FLASH_KEY1;
|
||||
FLASH->KEYR = FLASH_KEY2;
|
||||
}
|
||||
// FLASH_SR_BSY2 for some
|
||||
uint32_t count = (stor_size + 7) / 8;
|
||||
volatile uint32_t *address = (volatile uint32_t*) start;
|
||||
const uint32_t *data = (const uint32_t*) wrdata;
|
||||
for(uint32_t i = 0; i < count; ++i){
|
||||
while (FLASH->SR & (FLASH_SR_BSY1)); // 1: check BSY1
|
||||
if(FLASH->SR & FLASH_SR_WRPERR){ // 2: check errors
|
||||
return 1; // write protection
|
||||
}
|
||||
FLASH->SR = 0xffff; // clear all flags
|
||||
FLASH->CR |= FLASH_CR_PG; // 3: set PG bit
|
||||
IWDG->KR = IWDG_REFRESH;
|
||||
*address++ = *data++; // 4: write both 32 bit words
|
||||
*address++ = *data++;
|
||||
while(FLASH->SR & FLASH_SR_BSY1);
|
||||
if(FLASH->SR & FLASH_SR_PGSERR){
|
||||
ret = 1; // program error - meet not 0xffff
|
||||
break;
|
||||
}/*else{
|
||||
for(int _ = 0; _ < 9999 && (!(FLASH->SR & FLASH_SR_EOP)); ++_);
|
||||
}*/
|
||||
FLASH->SR = 0xffff;
|
||||
}
|
||||
FLASH->CR &= ~(FLASH_CR_PG); // 7: clear PG bit at end of process
|
||||
FLASH->CR |= FLASH_CR_LOCK; // lock it back
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief erase_flash - erase N pages of flash memory
|
||||
* @param start - first address
|
||||
* @param end - last address (or NULL if need to erase all flash remaining)
|
||||
* @return 0 if succeed
|
||||
*/
|
||||
static int erase_flash(const void *start, const void *end){
|
||||
int ret = 0;
|
||||
if(!start) return 1;
|
||||
uint32_t startb = (((uint32_t)start - FLASH_BASE) + blocksize - 1) / blocksize, endb;
|
||||
if(!end){ // erase all remaining
|
||||
endb = FLASH_SIZE / blocksize;
|
||||
}else{ // erase a part
|
||||
endb = (((uint32_t)end - FLASH_BASE) + blocksize - 1) / blocksize;
|
||||
}
|
||||
if ((FLASH->CR & FLASH_CR_LOCK) != 0){
|
||||
FLASH->KEYR = FLASH_KEY1;
|
||||
FLASH->KEYR = FLASH_KEY2;
|
||||
}
|
||||
for(uint32_t i = startb; i < endb; ++i){
|
||||
IWDG->KR = IWDG_REFRESH;
|
||||
/* (1) Wait till no operation is on going */
|
||||
/* (2) Clear error & EOP bits */
|
||||
while ((FLASH->SR & FLASH_SR_BSY1) != 0){} /* (1) */
|
||||
FLASH->SR = 0xffff; /* (2) */
|
||||
/* (1) Set the PER bit in the FLASH_CR register to enable page erasing */
|
||||
/* (2) Select the page to erase (PNB) */
|
||||
/* (3) Set the STRT bit in the FLASH_CR register to start the erasing */
|
||||
/* (4) Wait until BSY1 cleared */
|
||||
FLASH->CR |= FLASH_CR_PER | i << FLASH_CR_PNB_Pos; /* (1) (2) */
|
||||
FLASH->CR |= FLASH_CR_STRT; /* (3) */
|
||||
while ((FLASH->SR & FLASH_SR_BSY1) != 0){} /* (4) */
|
||||
FLASH->SR = FLASH_SR_EOP;
|
||||
if(FLASH->SR & FLASH_SR_WRPERR){ /* Check Write protection error */
|
||||
ret = 1;
|
||||
FLASH->SR = FLASH_SR_WRPERR; /* Clear the flag by software by writing it at 1*/
|
||||
break;
|
||||
}
|
||||
FLASH->CR &= ~FLASH_CR_PER; // clear PER
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
void dump_userconf(){
|
||||
SEND("flashsize="); printu(FLASH_SIZE);
|
||||
SEND("\nuserconf_addr="); printuhex((uint32_t)Flash_Data);
|
||||
SEND("\nuserconf_idx="); usart3_sendstr(i2str(currentconfidx));
|
||||
SEND("\nuserconf_sz="); printu(the_conf.userconf_sz);
|
||||
SEND("\nflagU16="); printuhex(the_conf.flagU16);
|
||||
SEND("\nflagU32="); printuhex(the_conf.flagU32);
|
||||
SEND("\nstr="); SEND(the_conf.str);
|
||||
newline();
|
||||
usart3_sendbuf();
|
||||
}
|
||||
|
||||
int erase_storage(){
|
||||
return erase_flash(Flash_Data, NULL);
|
||||
}
|
||||
1
G0:G070,G0B1/flash/flash.cflags
Normal file
1
G0:G070,G0B1/flash/flash.cflags
Normal file
@@ -0,0 +1 @@
|
||||
-std=c17
|
||||
3
G0:G070,G0B1/flash/flash.config
Normal file
3
G0:G070,G0B1/flash/flash.config
Normal file
@@ -0,0 +1,3 @@
|
||||
#define EBUG
|
||||
#define STM32G0
|
||||
#define STM32G070xx
|
||||
1
G0:G070,G0B1/flash/flash.creator
Normal file
1
G0:G070,G0B1/flash/flash.creator
Normal file
@@ -0,0 +1 @@
|
||||
[General]
|
||||
171
G0:G070,G0B1/flash/flash.creator.user
Normal file
171
G0:G070,G0B1/flash/flash.creator.user
Normal file
@@ -0,0 +1,171 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE QtCreatorProject>
|
||||
<!-- Written by QtCreator 8.0.2, 2022-12-22T21:13:47. -->
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>EnvironmentId</variable>
|
||||
<value type="QByteArray">{7bd84e39-ca37-46d3-be9d-99ebea85bc0d}</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.ActiveTarget</variable>
|
||||
<value type="int">0</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.EditorSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
|
||||
<value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
|
||||
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
|
||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
|
||||
<value type="QString" key="language">Cpp</value>
|
||||
<valuemap type="QVariantMap" key="value">
|
||||
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
|
||||
<value type="QString" key="language">QmlJS</value>
|
||||
<valuemap type="QVariantMap" key="value">
|
||||
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
<value type="int" key="EditorConfiguration.CodeStyle.Count">2</value>
|
||||
<value type="QByteArray" key="EditorConfiguration.Codec">KOI8-R</value>
|
||||
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
|
||||
<value type="int" key="EditorConfiguration.IndentSize">4</value>
|
||||
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
|
||||
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
|
||||
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
|
||||
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
|
||||
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
|
||||
<value type="bool" key="EditorConfiguration.PreferSingleLineComments">false</value>
|
||||
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
|
||||
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
|
||||
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
|
||||
<value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
|
||||
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
|
||||
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
|
||||
<value type="int" key="EditorConfiguration.TabSize">8</value>
|
||||
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
|
||||
<value type="bool" key="EditorConfiguration.UseIndenter">false</value>
|
||||
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
|
||||
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanIndentation">false</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
|
||||
<value type="QString" key="EditorConfiguration.ignoreFileTypes">*.md, *.MD, Makefile</value>
|
||||
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
|
||||
<value type="bool" key="EditorConfiguration.skipTrailingWhitespace">true</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.PluginSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<valuemap type="QVariantMap" key="AutoTest.ActiveFrameworks">
|
||||
<value type="bool" key="AutoTest.Framework.Boost">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.CTest">false</value>
|
||||
<value type="bool" key="AutoTest.Framework.Catch">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.GTest">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.QtQuickTest">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.QtTest">true</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="AutoTest.CheckStates"/>
|
||||
<value type="int" key="AutoTest.RunAfterBuild">0</value>
|
||||
<value type="bool" key="AutoTest.UseGlobal">true</value>
|
||||
<valuemap type="QVariantMap" key="ClangTools">
|
||||
<value type="bool" key="ClangTools.AnalyzeOpenFiles">true</value>
|
||||
<value type="bool" key="ClangTools.BuildBeforeAnalysis">true</value>
|
||||
<value type="QString" key="ClangTools.DiagnosticConfig">Builtin.DefaultTidyAndClazy</value>
|
||||
<value type="int" key="ClangTools.ParallelJobs">2</value>
|
||||
<valuelist type="QVariantList" key="ClangTools.SelectedDirs"/>
|
||||
<valuelist type="QVariantList" key="ClangTools.SelectedFiles"/>
|
||||
<valuelist type="QVariantList" key="ClangTools.SuppressedDiagnostics"/>
|
||||
<value type="bool" key="ClangTools.UseGlobalSettings">true</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Target.0</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="QString" key="DeviceType">Desktop</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{65a14f9e-e008-4c1b-89df-4eaa4774b6e3}</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/Big/Data/00__Electronics/STM32/G0-nolib/usart</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<valuelist type="QVariantList" key="GenericProjectManager.GenericMakeStep.BuildTargets">
|
||||
<value type="QString">all</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">GenericProjectManager.GenericMakeStep</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Сборка</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Сборка</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<valuelist type="QVariantList" key="GenericProjectManager.GenericMakeStep.BuildTargets">
|
||||
<value type="QString">clean</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">GenericProjectManager.GenericMakeStep</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Очистка</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Очистка</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">По умолчанию</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">GenericProjectManager.GenericBuildConfiguration</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Развёртывание</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Развёртывание</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.CustomExecutableRunConfiguration</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey"></value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.TargetCount</variable>
|
||||
<value type="int">1</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
|
||||
<value type="int">22</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>Version</variable>
|
||||
<value type="int">22</value>
|
||||
</data>
|
||||
</qtcreator>
|
||||
1
G0:G070,G0B1/flash/flash.cxxflags
Normal file
1
G0:G070,G0B1/flash/flash.cxxflags
Normal file
@@ -0,0 +1 @@
|
||||
-std=c++17
|
||||
8
G0:G070,G0B1/flash/flash.files
Normal file
8
G0:G070,G0B1/flash/flash.files
Normal file
@@ -0,0 +1,8 @@
|
||||
main.c
|
||||
usart.c
|
||||
|
||||
flash.c
|
||||
flash.h
|
||||
strfunc.c
|
||||
strfunc.h
|
||||
usart.h
|
||||
38
G0:G070,G0B1/flash/flash.h
Normal file
38
G0:G070,G0B1/flash/flash.h
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* This file is part of the flash project.
|
||||
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
/*
|
||||
* struct to save user configurations
|
||||
*/
|
||||
typedef struct __attribute__((packed, aligned(8))){
|
||||
uint16_t userconf_sz; // "magick number"
|
||||
uint16_t flagU16;
|
||||
uint32_t flagU32;
|
||||
char str[32];
|
||||
} user_conf;
|
||||
|
||||
extern user_conf the_conf; // global user config (read from FLASH to RAM)
|
||||
// data from ld-file: start address of storage
|
||||
|
||||
void flashstorage_init();
|
||||
int store_userconf();
|
||||
void dump_userconf();
|
||||
int erase_storage();
|
||||
|
||||
4
G0:G070,G0B1/flash/flash.includes
Normal file
4
G0:G070,G0B1/flash/flash.includes
Normal file
@@ -0,0 +1,4 @@
|
||||
.
|
||||
../inc
|
||||
../inc/Fx
|
||||
../inc/cm
|
||||
122
G0:G070,G0B1/flash/main.c
Normal file
122
G0:G070,G0B1/flash/main.c
Normal file
@@ -0,0 +1,122 @@
|
||||
/*
|
||||
* This file is part of the usart project.
|
||||
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stm32g0.h>
|
||||
#include "flash.h"
|
||||
#include "strfunc.h"
|
||||
#include "usart.h"
|
||||
|
||||
// KEY (intpullup->0) - PC0
|
||||
// LED - PC8
|
||||
|
||||
volatile uint32_t Tms = 0;
|
||||
|
||||
/* Called when systick fires */
|
||||
void sys_tick_handler(void){
|
||||
++Tms;
|
||||
}
|
||||
|
||||
static void gpio_setup(void){
|
||||
RCC->IOPENR |= RCC_IOPENR_GPIOCEN; // enable PC
|
||||
// set PC8 as opendrain output, PC0 is pullup input, other as default (AIN)
|
||||
GPIOC->MODER = (0xffffffff & ~(GPIO_MODER_MODE8 | GPIO_MODER_MODE0)) | GPIO_MODER_MODER8_O;
|
||||
GPIOC->PUPDR = GPIO_PUPDR0_PU; // pullup
|
||||
GPIOC->OTYPER = GPIO_OTYPER_OT8; // open drain
|
||||
}
|
||||
|
||||
static const char *helpmsg =
|
||||
"'1' - change U16 value\n"
|
||||
"'2' - change U32 value\n"
|
||||
"'d' - dumpconf\n"
|
||||
"'e' - erase flash\n"
|
||||
"'f' - save conf to flash\n"
|
||||
"'s' - change string (up to 31 symbol)\n"
|
||||
"'t' - print Tms\n"
|
||||
;
|
||||
|
||||
static void chstr(const char *s){
|
||||
int i = 0;
|
||||
for(; i < 31 && *s; ++i){
|
||||
the_conf.str[i] = *s++;
|
||||
}
|
||||
the_conf.str[i] = 0;
|
||||
}
|
||||
|
||||
int main(void){
|
||||
StartHSE();
|
||||
SysTick_Config(8000); // 1ms counter
|
||||
flashstorage_init();
|
||||
gpio_setup();
|
||||
usart3_setup();
|
||||
uint32_t T = 0;
|
||||
int sent = 0;
|
||||
/* Do nothing in main loop */
|
||||
while (1){
|
||||
if(Tms - T > 499){ // blink LED
|
||||
T = Tms;
|
||||
pin_toggle(GPIOC, 1<<8);
|
||||
usart3_sendbuf();
|
||||
}
|
||||
if(pin_read(GPIOC, 1<<0) == 0){ // key pressed - send data over USART
|
||||
if(!sent){
|
||||
usart3_sendstr("Button pressed\n");
|
||||
sent = 1;
|
||||
}
|
||||
}else sent = 0;
|
||||
int wasbo = 0;
|
||||
char *rcv = usart3_getline(&wasbo);
|
||||
if(wasbo) usart3_sendstr("Buffer overflow occured @ last message\n");
|
||||
if(rcv){
|
||||
char cmd = *rcv++;
|
||||
uint32_t U, got = 0;
|
||||
const char *n = getnum(rcv, &U);
|
||||
if(n != rcv) got = 1;
|
||||
switch(cmd){
|
||||
case '1':
|
||||
if(!got || U > 0xffff) SEND("Need an uint16_t number\n");
|
||||
else the_conf.flagU16 = (uint16_t)U;
|
||||
SEND("Changed to "); printuhex(the_conf.flagU16); newline();
|
||||
break;
|
||||
case '2':
|
||||
if(!got) SEND("Need an uint32_t number\n");
|
||||
else the_conf.flagU32 = U;
|
||||
SEND("Changed to "); printuhex(the_conf.flagU32); newline();
|
||||
break;
|
||||
case 'd':
|
||||
dump_userconf();
|
||||
break;
|
||||
case 'e':
|
||||
if(erase_storage()) SEND("Error erasing\n");
|
||||
else SEND("Erased OK\n");
|
||||
break;
|
||||
case 'f':
|
||||
if(store_userconf()) SEND("Error: can't save\n");
|
||||
else SEND("OK, stored\n");
|
||||
break;
|
||||
case 's':
|
||||
chstr(omit_spaces(rcv));
|
||||
SEND("Changed to: "); SEND(the_conf.str); newline();
|
||||
break;
|
||||
case 't':
|
||||
SEND("Tms="); printu(Tms); newline();
|
||||
break;
|
||||
default: SEND(helpmsg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
89
G0:G070,G0B1/flash/openocd.cfg
Normal file
89
G0:G070,G0B1/flash/openocd.cfg
Normal file
@@ -0,0 +1,89 @@
|
||||
# script for stm32g0x family
|
||||
|
||||
#
|
||||
# stm32g0 devices support SWD transports only.
|
||||
#
|
||||
source [find interface/stlink.cfg]
|
||||
source [find target/swj-dp.tcl]
|
||||
source [find mem_helper.tcl]
|
||||
|
||||
if { [info exists CHIPNAME] } {
|
||||
set _CHIPNAME $CHIPNAME
|
||||
} else {
|
||||
set _CHIPNAME stm32g0x
|
||||
}
|
||||
|
||||
set _ENDIAN little
|
||||
|
||||
# Work-area is a space in RAM used for flash programming
|
||||
# Smallest proposed target has 8kB ram, use 4kB by default to avoid surprises
|
||||
if { [info exists WORKAREASIZE] } {
|
||||
set _WORKAREASIZE $WORKAREASIZE
|
||||
} else {
|
||||
set _WORKAREASIZE 0x1000
|
||||
}
|
||||
|
||||
#jtag scan chain
|
||||
if { [info exists CPUTAPID] } {
|
||||
set _CPUTAPID $CPUTAPID
|
||||
} else {
|
||||
# Section 37.5.5 - corresponds to Cortex-M0+
|
||||
set _CPUTAPID 0x0bc11477
|
||||
}
|
||||
|
||||
swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID
|
||||
dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu
|
||||
|
||||
set _TARGETNAME $_CHIPNAME.cpu
|
||||
target create $_TARGETNAME cortex_m -endian $_ENDIAN -dap $_CHIPNAME.dap
|
||||
|
||||
$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0
|
||||
|
||||
set _FLASHNAME $_CHIPNAME.flash
|
||||
flash bank $_FLASHNAME stm32l4x 0 0 0 0 $_TARGETNAME
|
||||
|
||||
# reasonable default
|
||||
adapter speed 2000
|
||||
|
||||
adapter srst delay 100
|
||||
if {[using_jtag]} {
|
||||
jtag_ntrst_delay 100
|
||||
}
|
||||
|
||||
reset_config srst_nogate
|
||||
|
||||
if {![using_hla]} {
|
||||
# if srst is not fitted use SYSRESETREQ to
|
||||
# perform a soft reset
|
||||
cortex_m reset_config sysresetreq
|
||||
}
|
||||
|
||||
proc stm32g0x_default_reset_start {} {
|
||||
# Reset clock is HSI16 (16 MHz)
|
||||
adapter speed 2000
|
||||
}
|
||||
|
||||
proc stm32g0x_default_examine_end {} {
|
||||
# DBGMCU_CR |= DBG_STANDBY | DBG_STOP
|
||||
mmw 0x40015804 0x00000006 0
|
||||
|
||||
# Stop watchdog counters during halt
|
||||
# DBGMCU_APB1_FZ |= DBG_IWDG_STOP | DBG_WWDG_STOP
|
||||
mmw 0x40015808 0x00001800 0
|
||||
}
|
||||
|
||||
proc stm32g0x_default_reset_init {} {
|
||||
# Increase clock to 64 Mhz
|
||||
mmw 0x40022000 0x00000002 0x00000005 ;# FLASH_ACR: Latency = 2
|
||||
mww 0x4002100C 0x30000802 ;# RCC_PLLCFGR = PLLR=/2, PLLN=8, PLLM=/1, PLLSRC=0x2
|
||||
mmw 0x40021000 0x01000000 0x00000000 ;# RCC_CR |= PLLON
|
||||
mmw 0x40021008 0x00000002 0x00000005 ;# RCC_CFGR: SW=PLLRCLK
|
||||
|
||||
# Boost JTAG frequency
|
||||
adapter speed 4000
|
||||
}
|
||||
|
||||
# Default hooks
|
||||
$_TARGETNAME configure -event examine-end { stm32g0x_default_examine_end }
|
||||
$_TARGETNAME configure -event reset-start { stm32g0x_default_reset_start }
|
||||
$_TARGETNAME configure -event reset-init { stm32g0x_default_reset_init }
|
||||
269
G0:G070,G0B1/flash/strfunc.c
Normal file
269
G0:G070,G0B1/flash/strfunc.c
Normal file
@@ -0,0 +1,269 @@
|
||||
/*
|
||||
* This file is part of the flash project.
|
||||
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stm32g0.h>
|
||||
#include <string.h>
|
||||
|
||||
/**
|
||||
* @brief hexdump - dump hex array by 16 bytes in string
|
||||
* @param sendfun - function to send data
|
||||
* @param arr - array to dump
|
||||
* @param len - length of `arr`
|
||||
*/
|
||||
void hexdump(int (*sendfun)(const char *s), uint8_t *arr, uint16_t len){
|
||||
char buf[52], *bptr = buf;
|
||||
for(uint16_t l = 0; l < len; ++l, ++arr){
|
||||
for(int16_t j = 1; j > -1; --j){
|
||||
register uint8_t half = (*arr >> (4*j)) & 0x0f;
|
||||
if(half < 10) *bptr++ = half + '0';
|
||||
else *bptr++ = half - 10 + 'a';
|
||||
}
|
||||
if(l % 16 == 15){
|
||||
*bptr++ = '\n';
|
||||
*bptr = 0;
|
||||
sendfun(buf);
|
||||
bptr = buf;
|
||||
}else *bptr++ = ' ';
|
||||
}
|
||||
if(bptr != buf){
|
||||
*bptr++ = '\n';
|
||||
*bptr = 0;
|
||||
sendfun(buf);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief _2str - convert value into string buffer
|
||||
* @param val - |value|
|
||||
* @param minus - ==0 if value > 0
|
||||
* @return buffer with number
|
||||
*/
|
||||
static char *_2str(uint32_t val, uint8_t minus){
|
||||
static char strbuf[12];
|
||||
char *bufptr = &strbuf[11];
|
||||
*bufptr = 0;
|
||||
if(!val){
|
||||
*(--bufptr) = '0';
|
||||
}else{
|
||||
while(val){
|
||||
uint32_t x = val / 10;
|
||||
*(--bufptr) = (val - 10*x) + '0';
|
||||
val = x;
|
||||
//*(--bufptr) = val % 10 + '0';
|
||||
//val /= 10;
|
||||
}
|
||||
}
|
||||
if(minus) *(--bufptr) = '-';
|
||||
return bufptr;
|
||||
}
|
||||
|
||||
// return string with number `val`
|
||||
char *u2str(uint32_t val){
|
||||
return _2str(val, 0);
|
||||
}
|
||||
char *i2str(int32_t i){
|
||||
uint8_t minus = 0;
|
||||
uint32_t val;
|
||||
if(i < 0){
|
||||
minus = 1;
|
||||
val = -i;
|
||||
}else val = i;
|
||||
return _2str(val, minus);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief uhex2str - print 32bit unsigned int as hex
|
||||
* @param val - value
|
||||
* @return string with number
|
||||
*/
|
||||
char *uhex2str(uint32_t val){
|
||||
static char buf[12] = "0x";
|
||||
int npos = 2;
|
||||
uint8_t *ptr = (uint8_t*)&val + 3;
|
||||
int8_t i, j, z=1;
|
||||
for(i = 0; i < 4; ++i, --ptr){
|
||||
if(*ptr == 0){ // omit leading zeros
|
||||
if(i == 3) z = 0;
|
||||
if(z) continue;
|
||||
}
|
||||
else z = 0;
|
||||
for(j = 1; j > -1; --j){
|
||||
uint8_t half = (*ptr >> (4*j)) & 0x0f;
|
||||
if(half < 10) buf[npos++] = half + '0';
|
||||
else buf[npos++] = half - 10 + 'a';
|
||||
}
|
||||
}
|
||||
buf[npos] = 0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief omit_spaces - eliminate leading spaces and other trash in string
|
||||
* @param buf - string
|
||||
* @return - pointer to first character in `buf` > ' '
|
||||
*/
|
||||
const char *omit_spaces(const char *buf){
|
||||
while(*buf){
|
||||
if(*buf > ' ') break;
|
||||
++buf;
|
||||
}
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief getdec - read decimal number & return pointer to next non-number symbol
|
||||
* @param buf - string
|
||||
* @param N - number read
|
||||
* @return Next non-number symbol. In case of overflow return `buf` and N==0xffffffff
|
||||
*/
|
||||
static const char *getdec(const char *buf, uint32_t *N){
|
||||
char *start = (char*)buf;
|
||||
uint32_t num = 0;
|
||||
while(*buf){
|
||||
char c = *buf;
|
||||
if(c < '0' || c > '9'){
|
||||
break;
|
||||
}
|
||||
if(num > 429496729 || (num == 429496729 && c > '5')){ // overflow
|
||||
*N = 0xffffff;
|
||||
return start;
|
||||
}
|
||||
num *= 10;
|
||||
num += c - '0';
|
||||
++buf;
|
||||
}
|
||||
*N = num;
|
||||
return buf;
|
||||
}
|
||||
// read hexadecimal number (without 0x prefix!)
|
||||
static const char *gethex(const char *buf, uint32_t *N){
|
||||
const char *start = buf;
|
||||
uint32_t num = 0;
|
||||
while(*buf){
|
||||
char c = *buf;
|
||||
uint8_t M = 0;
|
||||
if(c >= '0' && c <= '9'){
|
||||
M = '0';
|
||||
}else if(c >= 'A' && c <= 'F'){
|
||||
M = 'A' - 10;
|
||||
}else if(c >= 'a' && c <= 'f'){
|
||||
M = 'a' - 10;
|
||||
}
|
||||
if(M){
|
||||
if(num & 0xf0000000){ // overflow
|
||||
*N = 0xffffff;
|
||||
return start;
|
||||
}
|
||||
num <<= 4;
|
||||
num += c - M;
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
++buf;
|
||||
}
|
||||
*N = num;
|
||||
return buf;
|
||||
}
|
||||
// read octal number (without 0 prefix!)
|
||||
static const char *getoct(const char *buf, uint32_t *N){
|
||||
const char *start = (char*)buf;
|
||||
uint32_t num = 0;
|
||||
while(*buf){
|
||||
char c = *buf;
|
||||
if(c < '0' || c > '7'){
|
||||
break;
|
||||
}
|
||||
if(num & 0xe0000000){ // overflow
|
||||
*N = 0xffffff;
|
||||
return start;
|
||||
}
|
||||
num <<= 3;
|
||||
num += c - '0';
|
||||
++buf;
|
||||
}
|
||||
*N = num;
|
||||
return buf;
|
||||
}
|
||||
// read binary number (without b prefix!)
|
||||
static const char *getbin(const char *buf, uint32_t *N){
|
||||
const char *start = (char*)buf;
|
||||
uint32_t num = 0;
|
||||
while(*buf){
|
||||
char c = *buf;
|
||||
if(c < '0' || c > '1'){
|
||||
break;
|
||||
}
|
||||
if(num & 0x80000000){ // overflow
|
||||
*N = 0xffffff;
|
||||
return start;
|
||||
}
|
||||
num <<= 1;
|
||||
if(c == '1') num |= 1;
|
||||
++buf;
|
||||
}
|
||||
*N = num;
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief getnum - read uint32_t from string (dec, hex or bin: 127, 0x7f, 0b1111111)
|
||||
* @param buf - buffer with number and so on
|
||||
* @param N - the number read
|
||||
* @return pointer to first non-number symbol in buf
|
||||
* (if it is == buf, there's no number or if *N==0xffffffff there was overflow)
|
||||
*/
|
||||
const char *getnum(const char *txt, uint32_t *N){
|
||||
const char *nxt = NULL;
|
||||
const char *s = omit_spaces(txt);
|
||||
if(*s == '0'){ // hex, oct or 0
|
||||
if(s[1] == 'x' || s[1] == 'X'){ // hex
|
||||
nxt = gethex(s+2, N);
|
||||
if(nxt == s+2) nxt = (char*)txt;
|
||||
}else if(s[1] > '0'-1 && s[1] < '8'){ // oct
|
||||
nxt = getoct(s+1, N);
|
||||
if(nxt == s+1) nxt = (char*)txt;
|
||||
}else{ // 0
|
||||
nxt = s+1;
|
||||
*N = 0;
|
||||
}
|
||||
}else if(*s == 'b' || *s == 'B'){
|
||||
nxt = getbin(s+1, N);
|
||||
if(nxt == s+1) nxt = (char*)txt;
|
||||
}else{
|
||||
nxt = getdec(s, N);
|
||||
if(nxt == s) nxt = (char*)txt;
|
||||
}
|
||||
return nxt;
|
||||
}
|
||||
|
||||
// get signed integer
|
||||
const char *getint(const char *txt, int32_t *I){
|
||||
const char *s = omit_spaces(txt);
|
||||
int32_t sign = 1;
|
||||
uint32_t U;
|
||||
if(*s == '-'){
|
||||
sign = -1;
|
||||
++s;
|
||||
}
|
||||
const char *nxt = getnum(s, &U);
|
||||
if(nxt == s) return txt;
|
||||
if(U & 0x80000000) return txt; // overfull
|
||||
*I = sign * (int32_t)U;
|
||||
return nxt;
|
||||
}
|
||||
|
||||
30
G0:G070,G0B1/flash/strfunc.h
Normal file
30
G0:G070,G0B1/flash/strfunc.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* This file is part of the flash project.
|
||||
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
void hexdump(int (*sendfun)(const char *s), uint8_t *arr, uint16_t len);
|
||||
char *u2str(uint32_t val);
|
||||
char *i2str(int32_t i);
|
||||
char *uhex2str(uint32_t val);
|
||||
const char *getnum(const char *txt, uint32_t *N);
|
||||
const char *omit_spaces(const char *buf);
|
||||
const char *getint(const char *txt, int32_t *I);
|
||||
174
G0:G070,G0B1/flash/usart.c
Normal file
174
G0:G070,G0B1/flash/usart.c
Normal file
@@ -0,0 +1,174 @@
|
||||
/*
|
||||
* This file is part of the flash project.
|
||||
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stm32g0.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "usart.h"
|
||||
|
||||
// RX/TX DMA->CCR without EN flag
|
||||
#define DMARXCCR (DMA_CCR_MINC | DMA_CCR_TCIE | DMA_CCR_TEIE)
|
||||
#define DMATXCCR (DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_TCIE | DMA_CCR_TEIE)
|
||||
|
||||
static volatile int txrdy = 1, rxrdy = 0; // transmission done, next line received
|
||||
static volatile int bufovr = 0, wasbufovr = 0; // Rx buffer overflow or error flag -> delete next line
|
||||
static volatile int rbufno = 0, tbufno = 0; // current buf number
|
||||
static volatile char rbuf[2][UARTBUFSZ], tbuf[2][UARTBUFSZ]; // receive & transmit buffers
|
||||
static volatile int rxlen[2] = {0}, txlen[2] = {0};
|
||||
|
||||
char *usart3_getline(int *wasbo){
|
||||
if(wasbo) *wasbo = wasbufovr;
|
||||
wasbufovr = 0;
|
||||
if(!rxrdy) return NULL;
|
||||
rxrdy = 0; // clear ready flag
|
||||
return (char*)rbuf[!rbufno]; // current buffer is in filling stage, return old - filled - buffer
|
||||
}
|
||||
|
||||
#define USART_BRR(speed) ((64000000 + speed/2) / speed)
|
||||
|
||||
// USART3 @ PD8 (Tx) and PD9 (Rx) - both AF0
|
||||
void usart3_setup(){
|
||||
RCC->IOPENR |= RCC_IOPENR_GPIODEN; // enable PD
|
||||
RCC->AHBENR |= RCC_AHBENR_DMA1EN; // enable DMA1
|
||||
// set PD8 and PD9 as AF
|
||||
GPIOD->MODER = (GPIOD->MODER & ~(GPIO_MODER_MODE8 | GPIO_MODER_MODE9))
|
||||
| GPIO_MODER_MODER8_AF | GPIO_MODER_MODER9_AF;
|
||||
// AF0 for USART3 @ PD8/PD9
|
||||
GPIOD->AFR[1] = GPIOD->AFR[1] & ~(GPIO_AFRH_AFSEL8 | GPIO_AFRH_AFSEL9);
|
||||
// enable USART3 clocking
|
||||
RCC->APBENR1 |= RCC_APBENR1_USART3EN;
|
||||
// baudrate 115200
|
||||
USART3->BRR = USART_BRR(115200);
|
||||
// eol character: '/n'
|
||||
USART3->CR2 = USART_CR2_ADD_VAL('\n');
|
||||
// enable DMA transmission
|
||||
USART3->CR3 = USART_CR3_DMAT | USART_CR3_DMAR;
|
||||
// set up DMA channels: 2 - Tx, 3 - Rx
|
||||
// Tx channel: mem++, mem->periph, 8bit, compl.&err. irq
|
||||
DMA1_Channel2->CCR = DMATXCCR;
|
||||
DMA1_Channel2->CPAR = (uint32_t) &USART3->TDR; // peripherial address
|
||||
// Rx channel: mem++, periph->mem, 8bit, compl.&err. irq
|
||||
DMA1_Channel3->CCR = DMARXCCR;
|
||||
DMA1_Channel3->CPAR = (uint32_t) &USART3->RDR; // peripherial address
|
||||
DMA1_Channel3->CNDTR = UARTBUFSZ;
|
||||
DMA1_Channel3->CMAR = (uint32_t)&rbuf[rbufno];
|
||||
// set up DMAMUX channels: 55 - USART3_TX, 54 - USART3_RX
|
||||
// enumeration of DMAMUX starts from 0 (DMA - from 1)!
|
||||
DMAMUX1_Channel1->CCR = 55;
|
||||
DMAMUX1_Channel2->CCR = 54;
|
||||
// charmatch interrupt, enable transmitter and receiver, enable usart
|
||||
USART3->CR1 = USART_CR1_CMIE | USART_CR1_TE | USART_CR1_RE | USART_CR1_UE;
|
||||
USART3->ICR = 0xffffffff; // clear all flags
|
||||
DMA1_Channel3->CCR = DMARXCCR | DMA_CCR_EN; // start receiving right now
|
||||
NVIC_EnableIRQ(USART3_4_IRQn);
|
||||
NVIC_EnableIRQ(DMA1_Channel2_3_IRQn);
|
||||
}
|
||||
|
||||
static void mymemcpy(char *dest, const char *src, int len){
|
||||
while(len--) *dest++ = *src++;
|
||||
}
|
||||
|
||||
int usart3_send(const char *str, int len){
|
||||
int rest = UARTBUFSZ - txlen[tbufno];
|
||||
if(rest == 0 && !txrdy) return 0; // buffer is full while transmission in process
|
||||
if(len < rest) rest = len;
|
||||
mymemcpy((char*)(tbuf[tbufno] + txlen[tbufno]), str, rest);
|
||||
txlen[tbufno] += rest;
|
||||
if(!txrdy) return rest;
|
||||
if(txlen[tbufno] == UARTBUFSZ) usart3_sendbuf();
|
||||
if(rest == len) return len;
|
||||
len -= rest;
|
||||
// now fill another - empty - buffer
|
||||
if(len > UARTBUFSZ) len = UARTBUFSZ;
|
||||
mymemcpy((char*)tbuf[tbufno], str + rest, len);
|
||||
txlen[tbufno] = len;
|
||||
return rest + len;
|
||||
}
|
||||
|
||||
int usart3_sendstr(const char *str){
|
||||
int l = strlen(str);
|
||||
return usart3_send(str, l);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usart3_sendbuf - send current buffer
|
||||
*/
|
||||
void usart3_sendbuf(){
|
||||
if(!txrdy || txlen[tbufno] == 0) return;
|
||||
// set up DMA
|
||||
DMA1_Channel2->CCR = DMATXCCR;
|
||||
DMA1_Channel2->CMAR = (uint32_t)&tbuf[tbufno];
|
||||
DMA1_Channel2->CNDTR = txlen[tbufno];
|
||||
USART3->ICR = USART_ICR_TCCF; // clear TC flag
|
||||
txrdy = 0;
|
||||
// activate DMA
|
||||
DMA1_Channel2->CCR = DMATXCCR | DMA_CCR_EN;
|
||||
tbufno = !tbufno; // swap buffers
|
||||
txlen[tbufno] = 0;
|
||||
}
|
||||
|
||||
// return amount of bytes sents
|
||||
int usart3_send_blocking(const char *str, int len){
|
||||
if(!txrdy) return 0;
|
||||
USART3->CR1 |= USART_CR1_TE;
|
||||
for(int i = 0; i < len; ++i){
|
||||
while(!(USART3->ISR & USART_ISR_TXE_TXFNF));
|
||||
USART3->TDR = *str++;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
// interrupt by '\n'
|
||||
void usart3_4_isr(){
|
||||
if(USART3->ISR & USART_ISR_CMF){ // got '\n' @ USART3
|
||||
DMA1_Channel3->CCR = DMARXCCR;
|
||||
if(!bufovr){ // forget about broken line @ buffer overflow
|
||||
rxrdy = 1;
|
||||
int l = UARTBUFSZ - DMA1_Channel3->CNDTR - 1; // strlen
|
||||
rxlen[rbufno] = l;
|
||||
rbuf[rbufno][l] = 0;
|
||||
rbufno = !rbufno;
|
||||
}else{
|
||||
bufovr = 0;
|
||||
wasbufovr = 1;
|
||||
}
|
||||
// reload DMA Rx with next buffer
|
||||
DMA1_Channel3->CMAR = (uint32_t)&rbuf[rbufno];
|
||||
DMA1_Channel3->CNDTR = UARTBUFSZ;
|
||||
DMA1_Channel3->CCR = DMARXCCR | DMA_CCR_EN;
|
||||
}
|
||||
USART3->ICR = 0xffffffff; // clear all flags
|
||||
}
|
||||
|
||||
// ch2 - Tx, ch3 - Rx
|
||||
void dma1_channel2_3_isr(){
|
||||
uint32_t isr = DMA1->ISR;
|
||||
if(isr & (DMA_ISR_TCIF2 | DMA_ISR_TEIF2)){ // transfer complete or error
|
||||
txrdy = 1;
|
||||
//DMA1_Channel2->CCR = DMATXCCR;
|
||||
}
|
||||
if(isr & (DMA_ISR_TCIF3 | DMA_ISR_TEIF3)){ // receive complete or error -> buffer overflow
|
||||
if(rbuf[rbufno][UARTBUFSZ-1] != '\n'){ // last symbol is not a newline
|
||||
bufovr = 1;
|
||||
DMA1_Channel3->CCR = DMARXCCR;
|
||||
DMA1_Channel3->CNDTR = UARTBUFSZ;
|
||||
DMA1_Channel3->CCR = DMARXCCR | DMA_CCR_EN;
|
||||
}
|
||||
}
|
||||
DMA1->IFCR = 0xffffffff; // clear all flags
|
||||
}
|
||||
35
G0:G070,G0B1/flash/usart.h
Normal file
35
G0:G070,G0B1/flash/usart.h
Normal file
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* This file is part of the flash project.
|
||||
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "strfunc.h"
|
||||
|
||||
#define UARTBUFSZ (512)
|
||||
|
||||
#define SEND(x) do{usart3_sendstr(x);}while(0)
|
||||
#define newline() do{usart3_sendstr("\n");}while(0)
|
||||
#define printu(x) do{usart3_sendstr(u2str(x));}while(0)
|
||||
#define printuhex(x) do{usart3_sendstr(uhex2str(x));}while(0)
|
||||
|
||||
void usart3_setup();
|
||||
int usart3_send_blocking(const char *str, int len);
|
||||
int usart3_send(const char *str, int len);
|
||||
void usart3_sendbuf();
|
||||
char *usart3_getline(int *wasbo);
|
||||
int usart3_sendstr(const char *str);
|
||||
9
G0:G070,G0B1/g0b1/Makefile
Normal file
9
G0:G070,G0B1/g0b1/Makefile
Normal file
@@ -0,0 +1,9 @@
|
||||
BINARY := test
|
||||
# MCU code
|
||||
MCU := G0B1xx
|
||||
# change this linking script depending on particular MCU model,
|
||||
LDSCRIPT := stm32g0b1xb.ld
|
||||
|
||||
include ../makefile.g0
|
||||
include ../../makefile.stm32
|
||||
|
||||
3
G0:G070,G0B1/g0b1/README
Normal file
3
G0:G070,G0B1/g0b1/README
Normal file
@@ -0,0 +1,3 @@
|
||||
Toggle LED on STM32G0B1-pill depending on user button:
|
||||
- pressed - 'SOS' in Morze
|
||||
- not pressed - blink with period of 1 second
|
||||
86
G0:G070,G0B1/g0b1/main.c
Normal file
86
G0:G070,G0B1/g0b1/main.c
Normal file
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* This file is part of the blink project.
|
||||
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "stm32g0.h"
|
||||
|
||||
#define KEY_PORT GPIOC
|
||||
#define KEY_PIN (1<<13)
|
||||
#define LED_PORT GPIOC
|
||||
#define LED_PIN (1<<6)
|
||||
#define KEY_PRESSED() (pin_read(KEY_PORT, KEY_PIN) == 1)
|
||||
#define LED_ON() do{pin_set(LED_PORT, LED_PIN);}while(0)
|
||||
#define LED_OFF() do{pin_clear(LED_PORT, LED_PIN);}while(0)
|
||||
|
||||
// KEY (intpullup->0) - PC13
|
||||
// LED - PC6
|
||||
|
||||
static volatile uint32_t blink_ctr = 0;
|
||||
|
||||
/* Called when systick fires */
|
||||
void sys_tick_handler(void){
|
||||
++blink_ctr;
|
||||
}
|
||||
|
||||
/*
|
||||
* Set up timer to fire every x milliseconds
|
||||
*/
|
||||
static void systick_setup(uint32_t xms){ // xms < 2098!!!
|
||||
blink_ctr = 0;
|
||||
static uint32_t curms = 0;
|
||||
if(curms == xms) return;
|
||||
// 8MHz - HCLK/8
|
||||
// this function also clears counter so it starts right away
|
||||
SysTick_Config(8000 * xms); // arg should be < 0xffffff, so ms should be < 2098
|
||||
curms = xms;
|
||||
}
|
||||
|
||||
static void gpio_setup(void){
|
||||
RCC->IOPENR = RCC_IOPENR_GPIOCEN; // enable PC
|
||||
// set PC8 as opendrain output, PC0 is pullup input, other as default (AIN)
|
||||
GPIOC->MODER = (0xffffffff & ~(GPIO_MODER_MODE6 | GPIO_MODER_MODE13)) | GPIO_MODER_MODER6_O; // GPIO_MODER_MODER13_I == 0
|
||||
GPIOC->PUPDR = GPIO_PUPDR13_PD; // pull down
|
||||
}
|
||||
|
||||
static const uint32_t L[] = {125,100,125,100,125,200, 350,100,350,100,350,200, 125,100,125,100,125, 1000};
|
||||
|
||||
int main(void){
|
||||
StartHSE();
|
||||
gpio_setup();
|
||||
systick_setup(500);
|
||||
uint32_t M = 0;
|
||||
int pressed = 0;
|
||||
/* Do nothing in main loop */
|
||||
while (1){
|
||||
if(KEY_PRESSED()){ // key pressed - 'sos'
|
||||
pressed = 1;
|
||||
systick_setup(L[M]);
|
||||
if(M & 1) LED_OFF();
|
||||
else LED_ON();
|
||||
if(++M == 18) M = 0;
|
||||
while(blink_ctr == 0);
|
||||
}else{ // key not pressed - blink with period of 1s
|
||||
if(pressed){
|
||||
M = 0;
|
||||
pressed = 0;
|
||||
systick_setup(500);
|
||||
}
|
||||
if(blink_ctr & 1) LED_ON();
|
||||
else LED_OFF();
|
||||
}
|
||||
}
|
||||
}
|
||||
4
G0:G070,G0B1/g0b1/openocd.cfg
Normal file
4
G0:G070,G0B1/g0b1/openocd.cfg
Normal file
@@ -0,0 +1,4 @@
|
||||
set FLASH_SIZE 0x20000
|
||||
|
||||
source [find interface/stlink-v2-1.cfg]
|
||||
source [find target/stm32g0x.cfg]
|
||||
BIN
G0:G070,G0B1/g0b1/test.bin
Executable file
BIN
G0:G070,G0B1/g0b1/test.bin
Executable file
Binary file not shown.
1
G0:G070,G0B1/g0b1/test.cflags
Normal file
1
G0:G070,G0B1/g0b1/test.cflags
Normal file
@@ -0,0 +1 @@
|
||||
-std=c17
|
||||
3
G0:G070,G0B1/g0b1/test.config
Normal file
3
G0:G070,G0B1/g0b1/test.config
Normal file
@@ -0,0 +1,3 @@
|
||||
#define EBUG
|
||||
#define STM32G0
|
||||
#define STM32G0B1xx
|
||||
1
G0:G070,G0B1/g0b1/test.creator
Normal file
1
G0:G070,G0B1/g0b1/test.creator
Normal file
@@ -0,0 +1 @@
|
||||
[General]
|
||||
214
G0:G070,G0B1/g0b1/test.creator.user
Normal file
214
G0:G070,G0B1/g0b1/test.creator.user
Normal file
@@ -0,0 +1,214 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE QtCreatorProject>
|
||||
<!-- Written by QtCreator 18.0.2, 2026-03-01T23:07:02. -->
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>EnvironmentId</variable>
|
||||
<value type="QByteArray">{7bd84e39-ca37-46d3-be9d-99ebea85bc0d}</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.ActiveTarget</variable>
|
||||
<value type="qlonglong">0</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.EditorSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="bool" key="EditorConfiguration.AutoDetect">true</value>
|
||||
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
|
||||
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
|
||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
|
||||
<value type="QString" key="language">Cpp</value>
|
||||
<valuemap type="QVariantMap" key="value">
|
||||
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
|
||||
<value type="QString" key="language">QmlJS</value>
|
||||
<valuemap type="QVariantMap" key="value">
|
||||
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="EditorConfiguration.CodeStyle.Count">2</value>
|
||||
<value type="QByteArray" key="EditorConfiguration.Codec">KOI8-R</value>
|
||||
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
|
||||
<value type="int" key="EditorConfiguration.IndentSize">4</value>
|
||||
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
|
||||
<value type="int" key="EditorConfiguration.LineEndingBehavior">0</value>
|
||||
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
|
||||
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
|
||||
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
|
||||
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
|
||||
<value type="int" key="EditorConfiguration.PreferAfterWhitespaceComments">0</value>
|
||||
<value type="bool" key="EditorConfiguration.PreferSingleLineComments">false</value>
|
||||
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
|
||||
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
|
||||
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
|
||||
<value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
|
||||
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
|
||||
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
|
||||
<value type="int" key="EditorConfiguration.TabSize">8</value>
|
||||
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
|
||||
<value type="bool" key="EditorConfiguration.UseIndenter">false</value>
|
||||
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
|
||||
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanIndentation">false</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
|
||||
<value type="QString" key="EditorConfiguration.ignoreFileTypes">*.md, *.MD, Makefile</value>
|
||||
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
|
||||
<value type="bool" key="EditorConfiguration.skipTrailingWhitespace">true</value>
|
||||
<value type="bool" key="EditorConfiguration.tintMarginArea">true</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.PluginSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<valuemap type="QVariantMap" key="AutoTest.ActiveFrameworks">
|
||||
<value type="bool" key="AutoTest.Framework.Boost">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.CTest">false</value>
|
||||
<value type="bool" key="AutoTest.Framework.Catch">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.GTest">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.QtQuickTest">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.QtTest">true</value>
|
||||
</valuemap>
|
||||
<value type="bool" key="AutoTest.ApplyFilter">false</value>
|
||||
<valuemap type="QVariantMap" key="AutoTest.CheckStates"/>
|
||||
<valuelist type="QVariantList" key="AutoTest.PathFilters"/>
|
||||
<value type="int" key="AutoTest.RunAfterBuild">0</value>
|
||||
<value type="bool" key="AutoTest.UseGlobal">true</value>
|
||||
<valuemap type="QVariantMap" key="ClangTools">
|
||||
<value type="bool" key="ClangTools.AnalyzeOpenFiles">true</value>
|
||||
<value type="bool" key="ClangTools.BuildBeforeAnalysis">true</value>
|
||||
<value type="QString" key="ClangTools.DiagnosticConfig">Builtin.DefaultTidyAndClazy</value>
|
||||
<value type="int" key="ClangTools.ParallelJobs">2</value>
|
||||
<value type="bool" key="ClangTools.PreferConfigFile">false</value>
|
||||
<valuelist type="QVariantList" key="ClangTools.SelectedDirs"/>
|
||||
<valuelist type="QVariantList" key="ClangTools.SelectedFiles"/>
|
||||
<valuelist type="QVariantList" key="ClangTools.SuppressedDiagnostics"/>
|
||||
<value type="bool" key="ClangTools.UseGlobalSettings">true</value>
|
||||
</valuemap>
|
||||
<value type="int" key="RcSync">0</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Target.0</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="QString" key="DeviceType">Desktop</value>
|
||||
<value type="bool" key="HasPerBcDcs">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{65a14f9e-e008-4c1b-89df-4eaa4774b6e3}</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/Big/Data/00__Electronics/STM32/G0-nolib/blink</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<valuelist type="QVariantList" key="GenericProjectManager.GenericMakeStep.BuildTargets">
|
||||
<value type="QString">all</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">GenericProjectManager.GenericMakeStep</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Build</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<valuelist type="QVariantList" key="GenericProjectManager.GenericMakeStep.BuildTargets">
|
||||
<value type="QString">clean</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">GenericProjectManager.GenericMakeStep</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Clean</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">По умолчанию</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">GenericProjectManager.GenericBuildConfiguration</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deploy</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
|
||||
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph dwarf,4096 -F 250</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.CustomExecutableRunConfiguration</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey"></value>
|
||||
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.UniqueId"></value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.BuildConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<value type="qlonglong" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Deploy</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Deploy</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||
<value type="bool" key="Analyzer.Perf.Settings.UseGlobalSettings">true</value>
|
||||
<value type="bool" key="Analyzer.QmlProfiler.Settings.UseGlobalSettings">true</value>
|
||||
<value type="bool" key="Analyzer.Valgrind.Settings.UseGlobalSettings">true</value>
|
||||
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||
<value type="bool" key="PE.EnvironmentAspect.PrintOnRun">false</value>
|
||||
<value type="QString" key="PerfRecordArgsId">-e cpu-cycles --call-graph dwarf,4096 -F 250</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName"></value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.CustomExecutableRunConfiguration</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey"></value>
|
||||
<value type="bool" key="ProjectExplorer.RunConfiguration.Customized">false</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.UniqueId"></value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||
</valuemap>
|
||||
<value type="qlonglong" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.TargetCount</variable>
|
||||
<value type="qlonglong">1</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>Version</variable>
|
||||
<value type="int">22</value>
|
||||
</data>
|
||||
</qtcreator>
|
||||
1
G0:G070,G0B1/g0b1/test.cxxflags
Normal file
1
G0:G070,G0B1/g0b1/test.cxxflags
Normal file
@@ -0,0 +1 @@
|
||||
-std=c++17
|
||||
2
G0:G070,G0B1/g0b1/test.files
Normal file
2
G0:G070,G0B1/g0b1/test.files
Normal file
@@ -0,0 +1,2 @@
|
||||
main.c
|
||||
systick_blink.c
|
||||
4
G0:G070,G0B1/g0b1/test.includes
Normal file
4
G0:G070,G0B1/g0b1/test.includes
Normal file
@@ -0,0 +1,4 @@
|
||||
.
|
||||
../inc
|
||||
../inc/Fx
|
||||
../inc/cm
|
||||
9
G0:G070,G0B1/i2c/Makefile
Normal file
9
G0:G070,G0B1/i2c/Makefile
Normal file
@@ -0,0 +1,9 @@
|
||||
BINARY := rtc
|
||||
# MCU code
|
||||
MCU := G070xx
|
||||
# change this linking script depending on particular MCU model,
|
||||
LDSCRIPT := stm32g070xb.ld
|
||||
|
||||
include ../makefile.g0
|
||||
include ../../makefile.stm32
|
||||
|
||||
164
G0:G070,G0B1/i2c/Makefile.old
Normal file
164
G0:G070,G0B1/i2c/Makefile.old
Normal file
@@ -0,0 +1,164 @@
|
||||
BINARY = i2cscan
|
||||
BOOTPORT ?= /dev/ttyUSB0
|
||||
BOOTSPEED ?= 115200
|
||||
# MCU FAMILY
|
||||
FAMILY = G0
|
||||
# MCU code
|
||||
MCU = G070xx
|
||||
#DEFS = -DEBUG -g3
|
||||
# change this linking script depending on particular MCU model,
|
||||
# for example, if you have STM32F103VBT6, you should write:
|
||||
LDSCRIPT = stm32g070xb.ld
|
||||
|
||||
INDEPENDENT_HEADERS=
|
||||
|
||||
FP_FLAGS ?= -msoft-float
|
||||
ASM_FLAGS = -mthumb -mcpu=cortex-m0plus -march=armv6-m -mtune=cortex-m0plus
|
||||
ARCH_FLAGS = $(ASM_FLAGS) $(FP_FLAGS)
|
||||
|
||||
# autoincremental version & build date
|
||||
VERSION_FILE = version.inc
|
||||
ifeq ($(shell test -e $(VERSION_FILE) && echo -n yes), yes)
|
||||
NEXTVER := $(shell expr $$(awk '/#define BUILD_NUMBER/' $(VERSION_FILE) | tr -cd "[0-9]") + 1)
|
||||
else
|
||||
NEXTVER := "1"
|
||||
endif
|
||||
|
||||
BUILDDATE := $(shell date +%Y-%m-%d)
|
||||
|
||||
###############################################################################
|
||||
# Executables
|
||||
PREFIX ?= /opt/bin/arm-none-eabi
|
||||
|
||||
RM := rm -f
|
||||
RMDIR := rmdir
|
||||
SIZE := $(PREFIX)-size
|
||||
CC := $(PREFIX)-gcc
|
||||
LD := $(PREFIX)-gcc
|
||||
AR := $(PREFIX)-ar
|
||||
AS := $(PREFIX)-as
|
||||
OBJCOPY := $(PREFIX)-objcopy
|
||||
OBJDUMP := $(PREFIX)-objdump
|
||||
GDB := $(PREFIX)-gdb
|
||||
STFLASH := $(shell which st-flash)
|
||||
STBOOT := $(shell which stm32flash)
|
||||
|
||||
###############################################################################
|
||||
# Source files
|
||||
OBJDIR = mk
|
||||
LDSCRIPT ?= $(BINARY).ld
|
||||
SRC := $(wildcard *.c)
|
||||
OBJS := $(addprefix $(OBJDIR)/, $(SRC:%.c=%.o))
|
||||
STARTUP = $(OBJDIR)/startup.o
|
||||
OBJS += $(STARTUP)
|
||||
DEPS := $(OBJS:.o=.d)
|
||||
|
||||
INC_DIR ?= ../inc
|
||||
|
||||
INCLUDE := -I$(INC_DIR)/Fx -I$(INC_DIR)/cm
|
||||
LIB_DIR := $(INC_DIR)/ld
|
||||
|
||||
###############################################################################
|
||||
# C flags
|
||||
CFLAGS += -O2 -MD -D__thumb2__=1
|
||||
CFLAGS += -Wall -Werror -Wextra -Wshadow -Wimplicit-function-declaration
|
||||
CFLAGS += -Wredundant-decls $(INCLUDE)
|
||||
# -Wmissing-prototypes -Wstrict-prototypes
|
||||
CFLAGS += -fno-common -ffunction-sections -fdata-sections -flto
|
||||
|
||||
###############################################################################
|
||||
# Linker flags
|
||||
LDFLAGS += --static -nostartfiles --specs=nano.specs -flto
|
||||
LDFLAGS += -L$(LIB_DIR)
|
||||
LDFLAGS += -T$(LDSCRIPT)
|
||||
LDFLAGS += -Wl,-Map=$(OBJDIR)/$(BINARY).map
|
||||
LDFLAGS += -Wl,--gc-sections
|
||||
|
||||
###############################################################################
|
||||
# Used libraries
|
||||
LDLIBS += -Wl,--start-group -lc -lgcc -Wl,--end-group
|
||||
LDLIBS += $(shell $(CC) $(CFLAGS) -print-libgcc-file-name)
|
||||
|
||||
DEFS += -DSTM32$(FAMILY) -DSTM32$(MCU)
|
||||
|
||||
#.SUFFIXES: .elf .bin .hex .srec .list .map .images
|
||||
#.SECONDEXPANSION:
|
||||
#.SECONDARY:
|
||||
|
||||
ELF := $(OBJDIR)/$(BINARY).elf
|
||||
LIST := $(OBJDIR)/$(BINARY).list
|
||||
BIN := $(BINARY).bin
|
||||
HEX := $(BINARY).hex
|
||||
|
||||
all: bin list size
|
||||
|
||||
elf: $(ELF)
|
||||
bin: $(BIN)
|
||||
hex: $(HEX)
|
||||
list: $(LIST)
|
||||
|
||||
ifneq ($(MAKECMDGOALS),clean)
|
||||
-include $(DEPS)
|
||||
endif
|
||||
|
||||
$(OBJDIR):
|
||||
mkdir $(OBJDIR)
|
||||
|
||||
$(STARTUP): $(INC_DIR)/startup/vector.c
|
||||
$(CC) $(CFLAGS) $(DEFS) $(INCLUDE) $(ARCH_FLAGS) -o $@ -c $<
|
||||
|
||||
$(VERSION_FILE): *.[ch]
|
||||
[ -f $(VERSION_FILE) ] || echo -e "#define BUILD_NUMBER \"0\"\n#define BUILD_DATE \"none\"" > $(VERSION_FILE)
|
||||
@echo " Generate version: $(NEXTVER) for date $(BUILDDATE)"
|
||||
@sed -i "s/#define BUILD_NUMBER.*/#define BUILD_NUMBER \"$(NEXTVER)\"/" $(VERSION_FILE)
|
||||
@sed -i "s/#define BUILD_DATE.*/#define BUILD_DATE \"$(BUILDDATE)\"/" $(VERSION_FILE)
|
||||
|
||||
# Uncomment and rename file, which includes version.inc
|
||||
#$(OBJDIR)/proto.o: proto.c $(VERSION_FILE)
|
||||
|
||||
$(OBJDIR)/%.o: %.c
|
||||
@echo " CC $<"
|
||||
$(CC) $(CFLAGS) $(DEFS) $(INCLUDE) $(ARCH_FLAGS) -o $@ -c $<
|
||||
|
||||
#$(OBJDIR)/%.d: %.c $(OBJDIR)
|
||||
# $(CC) -MM -MG $< | sed -e 's,^\([^:]*\)\.o[ ]*:,$(@D)/\1.o $(@D)/\1.d:,' >$@
|
||||
|
||||
$(BIN): $(ELF)
|
||||
@echo " OBJCOPY $(BIN)"
|
||||
$(OBJCOPY) -Obinary $(ELF) $(BIN)
|
||||
|
||||
$(HEX): $(ELF)
|
||||
@echo " OBJCOPY $(HEX)"
|
||||
$(OBJCOPY) -Oihex $(ELF) $(HEX)
|
||||
|
||||
$(LIST): $(ELF)
|
||||
@echo " OBJDUMP $(LIST)"
|
||||
$(OBJDUMP) -S $(ELF) > $(LIST)
|
||||
|
||||
$(ELF): $(OBJDIR) $(OBJS)
|
||||
@echo " LD $(ELF)"
|
||||
$(LD) $(LDFLAGS) $(ARCH_FLAGS) $(OBJS) $(LDLIBS) -o $(ELF)
|
||||
|
||||
clean:
|
||||
@echo " CLEAN"
|
||||
$(RM) $(OBJS) $(DEPS) $(ELF) $(HEX) $(LIST) $(OBJDIR)/*.map
|
||||
@rmdir $(OBJDIR) 2>/dev/null || true
|
||||
|
||||
size: $(ELF)
|
||||
$(SIZE) -Ax $(ELF)
|
||||
|
||||
flash: $(BIN)
|
||||
@echo " FLASH $(BIN)"
|
||||
$(STFLASH) write $(BIN) 0x8000000
|
||||
|
||||
boot: $(BIN)
|
||||
@echo " LOAD $(BIN) through bootloader"
|
||||
$(STBOOT) -b$(BOOTSPEED) $(BOOTPORT) -w $(BIN)
|
||||
|
||||
openocd:
|
||||
openocd -f openocd.cfg
|
||||
dbg:
|
||||
arm-none-eabi-gdb $(ELF) -ex 'target remote localhost:3333' -ex 'monitor reset halt'
|
||||
|
||||
|
||||
.PHONY: clean flash boot size openocd dbg
|
||||
16
G0:G070,G0B1/i2c/README
Normal file
16
G0:G070,G0B1/i2c/README
Normal file
@@ -0,0 +1,16 @@
|
||||
I2C @ PB6/PB7
|
||||
Scan available addresses, read/write data directly or over DMA
|
||||
|
||||
Proto:
|
||||
|
||||
i0..2 - setup I2C with lowest..highest speed (7.7, 10 and 100kHz)
|
||||
Ia addr - set I2C address
|
||||
Ig - dump content of I2Cbuf
|
||||
Iw bytes - send bytes (hex/dec/oct/bin) to I2C
|
||||
IW bytes - the same over DMA
|
||||
Ir reg n - read n bytes from I2C reg
|
||||
I2 reg16 n - read n bytes from 16-bit register
|
||||
In n - just read n bytes
|
||||
IN n - the same but with DMA
|
||||
Is - scan I2C bus
|
||||
U - send long buffer over USART
|
||||
304
G0:G070,G0B1/i2c/i2c.c
Normal file
304
G0:G070,G0B1/i2c/i2c.c
Normal file
@@ -0,0 +1,304 @@
|
||||
/*
|
||||
* This file is part of the i2cscan project.
|
||||
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stm32g0.h>
|
||||
#include <string.h>
|
||||
#include "strfunc.h" // hexdump
|
||||
#include "usart.h"
|
||||
#include "i2c.h"
|
||||
|
||||
I2C_SPEED curI2Cspeed = LOW_SPEED;
|
||||
extern volatile uint32_t Tms;
|
||||
static uint32_t cntr;
|
||||
static uint8_t i2c_got_DMA_Rx = 0;
|
||||
volatile uint8_t I2C_scan_mode = 0; // == 1 when I2C is in scan mode
|
||||
static uint8_t i2caddr = I2C_ADDREND; // current address in scan mode
|
||||
static volatile int I2Cbusy = 0, goterr = 0; // busy==1 when DMA active, goterr==1 if 't was error @ last sent
|
||||
static uint8_t I2Cbuf[256], i2cbuflen = 0; // buffer for DMA tx/rx and its len
|
||||
|
||||
// macros for I2C rx/tx
|
||||
#define DMARXCCR (DMA_CCR_MINC | DMA_CCR_TCIE | DMA_CCR_TEIE)
|
||||
#define DMATXCCR (DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_TCIE | DMA_CCR_TEIE)
|
||||
// macro for I2CCR1
|
||||
#define I2CCR1 (I2C_CR1_PE | I2C_CR1_RXDMAEN | I2C_CR1_TXDMAEN)
|
||||
|
||||
// return 1 if I2Cbusy is set & timeout reached
|
||||
static inline int isI2Cbusy(){
|
||||
cntr = Tms;
|
||||
do{
|
||||
if(Tms - cntr > I2C_TIMEOUT){ USND("Timeout, DMA transfer in progress?\n"); return 1;}
|
||||
}while(I2Cbusy);
|
||||
return 0;
|
||||
}
|
||||
|
||||
// GPIO Resources: I2C1_SCL - PB6 (AF6), I2C1_SDA - PB7 (AF6)
|
||||
void i2c_setup(I2C_SPEED speed){
|
||||
if(speed >= CURRENT_SPEED){
|
||||
speed = curI2Cspeed;
|
||||
}else{
|
||||
curI2Cspeed = speed;
|
||||
}
|
||||
RCC->IOPENR |= RCC_IOPENR_GPIOBEN;
|
||||
I2C1->CR1 = 0;
|
||||
I2C1->ICR = 0x3f38; // clear all errors
|
||||
GPIOB->AFR[0] = (GPIOB->AFR[0] & ~(GPIO_AFRL_AFSEL6 | GPIO_AFRL_AFSEL7)) |
|
||||
6 << (6 * 4) | 6 << (7 * 4);
|
||||
GPIOB->MODER = (GPIOB->MODER & ~(GPIO_MODER_MODE6 | GPIO_MODER_MODE7)) |
|
||||
GPIO_MODER_MODER6_AF | GPIO_MODER_MODER7_AF;
|
||||
GPIOB->PUPDR = (GPIOB->PUPDR & !(GPIO_PUPDR_PUPD6 | GPIO_PUPDR_PUPD7)) |
|
||||
GPIO_PUPDR6_PU | GPIO_PUPDR7_PU; // pullup
|
||||
GPIOB->OTYPER |= GPIO_OTYPER_OT6 | GPIO_OTYPER_OT7; // both open-drain outputs
|
||||
// I2C (default timing from PCLK - 64MHz)
|
||||
RCC->APBENR1 |= RCC_APBENR1_I2C1EN; // clocking
|
||||
if(speed == LOW_SPEED){ // 10kHz
|
||||
// PRESC=F, SCLDEL=4, SDADEL=2, SCLH=0xC3, SCLL=0xC7
|
||||
I2C1->TIMINGR = (0xF<<28) | (4<<20) | (2<<16) | (0xC3<<8) | (0xC7);
|
||||
}else if(speed == HIGH_SPEED){ // 100kHz
|
||||
I2C1->TIMINGR = (0xF<<28) | (4<<20) | (2<<16) | (0xF<<8) | (0x13);
|
||||
}else{ // VERYLOW_SPEED - the lowest speed by STM register: ~7.7kHz
|
||||
I2C1->TIMINGR = (0xF<<28) | (4<<20) | (2<<16) | (0xff<<8) | (0xff);
|
||||
}
|
||||
I2C1->CR1 = I2CCR1;
|
||||
RCC->AHBENR |= RCC_AHBENR_DMA1EN;
|
||||
NVIC_EnableIRQ(DMA1_Channel1_IRQn);
|
||||
I2Cbusy = 0;
|
||||
}
|
||||
|
||||
// setup DMA for rx (tx==0) or tx (tx==1)
|
||||
// DMAMUX: 10 - Rx, 11 - Tx
|
||||
static void i2cDMAsetup(int tx, uint8_t len){
|
||||
if(tx){
|
||||
DMA1_Channel1->CCR = DMATXCCR;
|
||||
DMA1_Channel1->CPAR = (uint32_t) &I2C1->TXDR;
|
||||
DMAMUX1_Channel0->CCR = 11;
|
||||
}else{
|
||||
DMA1_Channel1->CCR = DMARXCCR;
|
||||
DMA1_Channel1->CPAR = (uint32_t) &I2C1->RXDR;
|
||||
DMAMUX1_Channel0->CCR = 10;
|
||||
}
|
||||
DMA1_Channel1->CMAR = (uint32_t) I2Cbuf;
|
||||
DMA1_Channel1->CNDTR = i2cbuflen = len;
|
||||
}
|
||||
|
||||
static uint8_t i2c_start(uint8_t busychk){
|
||||
if(busychk){
|
||||
cntr = Tms;
|
||||
while(I2C1->ISR & I2C_ISR_BUSY){
|
||||
IWDG->KR = IWDG_REFRESH;
|
||||
if(Tms - cntr > I2C_TIMEOUT){
|
||||
USND("Line busy\n");
|
||||
return 0; // check busy
|
||||
}}
|
||||
}
|
||||
cntr = Tms;
|
||||
while(I2C1->CR2 & I2C_CR2_START){
|
||||
IWDG->KR = IWDG_REFRESH;
|
||||
if(Tms - cntr > I2C_TIMEOUT){
|
||||
USND("No start\n");
|
||||
return 0; // check start
|
||||
}}
|
||||
return 1;
|
||||
}
|
||||
|
||||
// start writing
|
||||
static uint8_t i2c_startw(uint8_t addr, uint8_t nbytes, uint8_t stop){
|
||||
if(!i2c_start(1)) return 0;
|
||||
I2C1->CR2 = nbytes << 16 | addr;
|
||||
if(stop) I2C1->CR2 |= I2C_CR2_AUTOEND; // autoend
|
||||
// now start transfer
|
||||
I2C1->CR2 |= I2C_CR2_START;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* write command byte to I2C
|
||||
* @param addr - device address (TSYS01_ADDR0 or TSYS01_ADDR1)
|
||||
* @param data - bytes to write
|
||||
* @param nbytes - amount of bytes to write
|
||||
* @param stop - to set STOP
|
||||
* @return 0 if error
|
||||
*/
|
||||
static uint8_t write_i2cs(uint8_t addr, uint8_t *data, uint8_t nbytes, uint8_t stop){
|
||||
if(!i2c_startw(addr, nbytes, stop)) return 0;
|
||||
for(int i = 0; i < nbytes; ++i){
|
||||
cntr = Tms;
|
||||
while(!(I2C1->ISR & I2C_ISR_TXIS)){ // ready to transmit
|
||||
IWDG->KR = IWDG_REFRESH;
|
||||
if(I2C1->ISR & I2C_ISR_NACKF){
|
||||
I2C1->ICR |= I2C_ICR_NACKCF;
|
||||
//USND("NAK\n");
|
||||
return 0;
|
||||
}
|
||||
if(Tms - cntr > I2C_TIMEOUT){
|
||||
//USND("Timeout\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
I2C1->TXDR = data[i]; // send data
|
||||
}
|
||||
cntr = Tms;
|
||||
// wait for data gone
|
||||
while(I2C1->ISR & I2C_ISR_BUSY){
|
||||
IWDG->KR = IWDG_REFRESH;
|
||||
if(Tms - cntr > I2C_TIMEOUT){break;}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t write_i2c(uint8_t addr, uint8_t *data, uint8_t nbytes){
|
||||
if(isI2Cbusy()) return 0;
|
||||
return write_i2cs(addr, data, nbytes, 1);
|
||||
}
|
||||
|
||||
uint8_t write_i2c_dma(uint8_t addr, uint8_t *data, uint8_t nbytes){
|
||||
if(!data || nbytes < 1) return 0;
|
||||
memcpy((char*)I2Cbuf, (char*)data, nbytes);
|
||||
if(isI2Cbusy()) return 0;
|
||||
i2cDMAsetup(1, nbytes);
|
||||
goterr = 0;
|
||||
if(!i2c_startw(addr, nbytes, 1)) return 0;
|
||||
I2Cbusy = 1;
|
||||
DMA1_Channel1->CCR = DMATXCCR | DMA_CCR_EN; // start transfer
|
||||
return 1;
|
||||
}
|
||||
|
||||
// start reading
|
||||
static uint8_t i2c_startr(uint8_t addr, uint8_t nbytes, uint8_t busychk){
|
||||
if(!i2c_start(busychk)) return 0;
|
||||
// read N bytes
|
||||
I2C1->CR2 = (nbytes<<16) | addr | 1 | I2C_CR2_AUTOEND | I2C_CR2_RD_WRN;
|
||||
I2C1->CR2 |= I2C_CR2_START;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* read nbytes of data from I2C line
|
||||
* all functions with `addr` should have addr = address << 1
|
||||
* `data` should be an array with at least `nbytes` length
|
||||
* @return 1 if all OK, 0 if NACK or no device found
|
||||
*/
|
||||
static uint8_t read_i2cb(uint8_t addr, uint8_t *data, uint8_t nbytes, uint8_t busychk){
|
||||
if(!i2c_startr(addr, nbytes, busychk)) return 0;
|
||||
uint8_t i;
|
||||
for(i = 0; i < nbytes; ++i){
|
||||
cntr = Tms;
|
||||
while(!(I2C1->ISR & I2C_ISR_RXNE)){ // wait for data
|
||||
IWDG->KR = IWDG_REFRESH;
|
||||
if(I2C1->ISR & I2C_ISR_NACKF){
|
||||
I2C1->ICR |= I2C_ICR_NACKCF;
|
||||
//USND("NAK\n");
|
||||
return 0;
|
||||
}
|
||||
if(Tms - cntr > I2C_TIMEOUT){
|
||||
//USND("Timeout\n");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
*data++ = I2C1->RXDR;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
uint8_t read_i2c(uint8_t addr, uint8_t *data, uint8_t nbytes){
|
||||
if(isI2Cbusy()) return 0;
|
||||
return read_i2cb(addr, data, nbytes, 1);
|
||||
}
|
||||
|
||||
uint8_t read_i2c_dma(uint8_t addr, uint8_t nbytes){
|
||||
if(nbytes < 1) return 0;
|
||||
if(isI2Cbusy()) return 0;
|
||||
i2cDMAsetup(0, nbytes);
|
||||
goterr = 0;
|
||||
if(!i2c_startr(addr, nbytes, 1)) return 0;
|
||||
I2Cbusy = 1;
|
||||
DMA1_Channel1->CCR = DMARXCCR | DMA_CCR_EN; // start transfer
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
// read register reg
|
||||
uint8_t read_i2c_reg(uint8_t addr, uint8_t reg, uint8_t *data, uint8_t nbytes){
|
||||
if(isI2Cbusy()) return 0;
|
||||
if(!write_i2cs(addr, ®, 1, 0)) return 0;
|
||||
return read_i2cb(addr, data, nbytes, 0);
|
||||
}
|
||||
|
||||
// read 16bit register reg
|
||||
uint8_t read_i2c_reg16(uint8_t addr, uint16_t reg16, uint8_t *data, uint8_t nbytes){
|
||||
if(isI2Cbusy()) return 0;
|
||||
if(!write_i2cs(addr, (uint8_t*)®16, 2, 0)) return 0;
|
||||
return read_i2cb(addr, data, nbytes, 0);
|
||||
}
|
||||
|
||||
void i2c_init_scan_mode(){
|
||||
i2caddr = 1; // start from 1 as 0 is a broadcast address
|
||||
I2C_scan_mode = 1;
|
||||
}
|
||||
|
||||
// return 1 if next addr is active & return in as `addr`
|
||||
// if addresses are over, return 1 and set addr to I2C_NOADDR
|
||||
// if scan mode inactive, return 0 and set addr to I2C_NOADDR
|
||||
int i2c_scan_next_addr(uint8_t *addr){
|
||||
if(isI2Cbusy()) return 0;
|
||||
*addr = i2caddr;
|
||||
if(i2caddr == I2C_ADDREND){
|
||||
*addr = I2C_ADDREND;
|
||||
I2C_scan_mode = 0;
|
||||
return 0;
|
||||
}
|
||||
/*while(!u3txrdy);
|
||||
USND("Addr: "); USND(uhex2str(i2caddr)); USND("\n");
|
||||
usart3_sendbuf();*/
|
||||
uint8_t byte;
|
||||
if(!read_i2c((i2caddr++)<<1, &byte, 1)) return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
// dump I2Cbuf
|
||||
void i2c_bufdudump(){
|
||||
if(goterr){
|
||||
USND("Last transfer ends with error!\n");
|
||||
goterr = 0;
|
||||
}
|
||||
USND("I2C buffer:\n");
|
||||
hexdump(usart3_sendstr, I2Cbuf, i2cbuflen);
|
||||
}
|
||||
|
||||
void i2c_have_DMA_Rx(){
|
||||
if(!i2c_got_DMA_Rx) return;
|
||||
i2c_got_DMA_Rx = 0;
|
||||
i2c_bufdudump();
|
||||
}
|
||||
|
||||
int i2cdma_haderr(){
|
||||
int r = goterr;
|
||||
goterr = 0;
|
||||
return r;
|
||||
}
|
||||
|
||||
// Rx/Tx interrupts
|
||||
void dma1_channel1_isr(){
|
||||
uint32_t isr = DMA1->ISR;
|
||||
if(isr & (DMA_ISR_TCIF1 | DMA_ISR_TEIF1)){
|
||||
if(isr & DMA_ISR_TEIF1) goterr = 1;
|
||||
if(!(DMA1_Channel1->CCR & DMA_CCR_DIR)) i2c_got_DMA_Rx = 1; // last transfer was Rx
|
||||
DMA1_Channel1->CCR = 0;
|
||||
I2Cbusy = 0;
|
||||
}
|
||||
DMA1->IFCR = 0xf; // clear all flags for channel1
|
||||
}
|
||||
50
G0:G070,G0B1/i2c/i2c.h
Normal file
50
G0:G070,G0B1/i2c/i2c.h
Normal file
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* This file is part of the i2cscan project.
|
||||
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <stdint.h>
|
||||
|
||||
#define I2C_ADDREND (0x80)
|
||||
|
||||
typedef enum{
|
||||
VERYLOW_SPEED,
|
||||
LOW_SPEED,
|
||||
HIGH_SPEED,
|
||||
CURRENT_SPEED
|
||||
} I2C_SPEED;
|
||||
|
||||
extern I2C_SPEED curI2Cspeed;
|
||||
extern volatile uint8_t I2C_scan_mode;
|
||||
|
||||
// timeout of I2C bus in ms
|
||||
#define I2C_TIMEOUT (100)
|
||||
|
||||
void i2c_setup(I2C_SPEED speed);
|
||||
uint8_t read_i2c(uint8_t addr, uint8_t *data, uint8_t nbytes);
|
||||
uint8_t read_i2c_reg(uint8_t addr, uint8_t reg, uint8_t *data, uint8_t nbytes);
|
||||
uint8_t read_i2c_reg16(uint8_t addr, uint16_t reg16, uint8_t *data, uint8_t nbytes);
|
||||
uint8_t write_i2c(uint8_t addr, uint8_t *data, uint8_t nbytes);
|
||||
uint8_t write_i2c_dma(uint8_t addr, uint8_t *data, uint8_t nbytes);
|
||||
uint8_t read_i2c_dma(uint8_t addr, uint8_t nbytes);
|
||||
|
||||
void i2c_bufdudump();
|
||||
void i2c_have_DMA_Rx();
|
||||
int i2cdma_haderr();
|
||||
|
||||
void i2c_init_scan_mode();
|
||||
int i2c_scan_next_addr(uint8_t *addr);
|
||||
BIN
G0:G070,G0B1/i2c/i2cscan.bin
Executable file
BIN
G0:G070,G0B1/i2c/i2cscan.bin
Executable file
Binary file not shown.
1
G0:G070,G0B1/i2c/i2cscan.cflags
Normal file
1
G0:G070,G0B1/i2c/i2cscan.cflags
Normal file
@@ -0,0 +1 @@
|
||||
-std=c17
|
||||
3
G0:G070,G0B1/i2c/i2cscan.config
Normal file
3
G0:G070,G0B1/i2c/i2cscan.config
Normal file
@@ -0,0 +1,3 @@
|
||||
#define EBUG
|
||||
#define STM32G0
|
||||
#define STM32G070xx
|
||||
1
G0:G070,G0B1/i2c/i2cscan.creator
Normal file
1
G0:G070,G0B1/i2c/i2cscan.creator
Normal file
@@ -0,0 +1 @@
|
||||
[General]
|
||||
171
G0:G070,G0B1/i2c/i2cscan.creator.user
Normal file
171
G0:G070,G0B1/i2c/i2cscan.creator.user
Normal file
@@ -0,0 +1,171 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE QtCreatorProject>
|
||||
<!-- Written by QtCreator 8.0.2, 2022-12-22T21:13:47. -->
|
||||
<qtcreator>
|
||||
<data>
|
||||
<variable>EnvironmentId</variable>
|
||||
<value type="QByteArray">{7bd84e39-ca37-46d3-be9d-99ebea85bc0d}</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.ActiveTarget</variable>
|
||||
<value type="int">0</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.EditorSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="bool" key="EditorConfiguration.AutoIndent">true</value>
|
||||
<value type="bool" key="EditorConfiguration.AutoSpacesForTabs">false</value>
|
||||
<value type="bool" key="EditorConfiguration.CamelCaseNavigation">true</value>
|
||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.0">
|
||||
<value type="QString" key="language">Cpp</value>
|
||||
<valuemap type="QVariantMap" key="value">
|
||||
<value type="QByteArray" key="CurrentPreferences">CppGlobal</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="EditorConfiguration.CodeStyle.1">
|
||||
<value type="QString" key="language">QmlJS</value>
|
||||
<valuemap type="QVariantMap" key="value">
|
||||
<value type="QByteArray" key="CurrentPreferences">QmlJSGlobal</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
<value type="int" key="EditorConfiguration.CodeStyle.Count">2</value>
|
||||
<value type="QByteArray" key="EditorConfiguration.Codec">KOI8-R</value>
|
||||
<value type="bool" key="EditorConfiguration.ConstrainTooltips">false</value>
|
||||
<value type="int" key="EditorConfiguration.IndentSize">4</value>
|
||||
<value type="bool" key="EditorConfiguration.KeyboardTooltips">false</value>
|
||||
<value type="int" key="EditorConfiguration.MarginColumn">80</value>
|
||||
<value type="bool" key="EditorConfiguration.MouseHiding">true</value>
|
||||
<value type="bool" key="EditorConfiguration.MouseNavigation">true</value>
|
||||
<value type="int" key="EditorConfiguration.PaddingMode">1</value>
|
||||
<value type="bool" key="EditorConfiguration.PreferSingleLineComments">false</value>
|
||||
<value type="bool" key="EditorConfiguration.ScrollWheelZooming">true</value>
|
||||
<value type="bool" key="EditorConfiguration.ShowMargin">false</value>
|
||||
<value type="int" key="EditorConfiguration.SmartBackspaceBehavior">0</value>
|
||||
<value type="bool" key="EditorConfiguration.SmartSelectionChanging">true</value>
|
||||
<value type="bool" key="EditorConfiguration.SpacesForTabs">true</value>
|
||||
<value type="int" key="EditorConfiguration.TabKeyBehavior">0</value>
|
||||
<value type="int" key="EditorConfiguration.TabSize">8</value>
|
||||
<value type="bool" key="EditorConfiguration.UseGlobal">true</value>
|
||||
<value type="bool" key="EditorConfiguration.UseIndenter">false</value>
|
||||
<value type="int" key="EditorConfiguration.Utf8BomBehavior">1</value>
|
||||
<value type="bool" key="EditorConfiguration.addFinalNewLine">true</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanIndentation">false</value>
|
||||
<value type="bool" key="EditorConfiguration.cleanWhitespace">true</value>
|
||||
<value type="QString" key="EditorConfiguration.ignoreFileTypes">*.md, *.MD, Makefile</value>
|
||||
<value type="bool" key="EditorConfiguration.inEntireDocument">false</value>
|
||||
<value type="bool" key="EditorConfiguration.skipTrailingWhitespace">true</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.PluginSettings</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<valuemap type="QVariantMap" key="AutoTest.ActiveFrameworks">
|
||||
<value type="bool" key="AutoTest.Framework.Boost">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.CTest">false</value>
|
||||
<value type="bool" key="AutoTest.Framework.Catch">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.GTest">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.QtQuickTest">true</value>
|
||||
<value type="bool" key="AutoTest.Framework.QtTest">true</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="AutoTest.CheckStates"/>
|
||||
<value type="int" key="AutoTest.RunAfterBuild">0</value>
|
||||
<value type="bool" key="AutoTest.UseGlobal">true</value>
|
||||
<valuemap type="QVariantMap" key="ClangTools">
|
||||
<value type="bool" key="ClangTools.AnalyzeOpenFiles">true</value>
|
||||
<value type="bool" key="ClangTools.BuildBeforeAnalysis">true</value>
|
||||
<value type="QString" key="ClangTools.DiagnosticConfig">Builtin.DefaultTidyAndClazy</value>
|
||||
<value type="int" key="ClangTools.ParallelJobs">2</value>
|
||||
<valuelist type="QVariantList" key="ClangTools.SelectedDirs"/>
|
||||
<valuelist type="QVariantList" key="ClangTools.SelectedFiles"/>
|
||||
<valuelist type="QVariantList" key="ClangTools.SuppressedDiagnostics"/>
|
||||
<value type="bool" key="ClangTools.UseGlobalSettings">true</value>
|
||||
</valuemap>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Target.0</variable>
|
||||
<valuemap type="QVariantMap">
|
||||
<value type="QString" key="DeviceType">Desktop</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Desktop</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Desktop</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">{65a14f9e-e008-4c1b-89df-4eaa4774b6e3}</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveBuildConfiguration">0</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveDeployConfiguration">0</value>
|
||||
<value type="int" key="ProjectExplorer.Target.ActiveRunConfiguration">0</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.BuildConfiguration.0">
|
||||
<value type="QString" key="ProjectExplorer.BuildConfiguration.BuildDirectory">/Big/Data/00__Electronics/STM32/G0-nolib/i2cscan</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<valuelist type="QVariantList" key="GenericProjectManager.GenericMakeStep.BuildTargets">
|
||||
<value type="QString">all</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">GenericProjectManager.GenericMakeStep</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Сборка</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Сборка</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Build</value>
|
||||
</valuemap>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.1">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildStepList.Step.0">
|
||||
<valuelist type="QVariantList" key="GenericProjectManager.GenericMakeStep.BuildTargets">
|
||||
<value type="QString">clean</value>
|
||||
</valuelist>
|
||||
<value type="bool" key="ProjectExplorer.BuildStep.Enabled">true</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">GenericProjectManager.GenericMakeStep</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">1</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Очистка</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Очистка</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Clean</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">2</value>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ClearSystemEnvironment">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.CustomParsers"/>
|
||||
<value type="bool" key="ProjectExplorer.BuildConfiguration.ParseStandardOutput">false</value>
|
||||
<valuelist type="QVariantList" key="ProjectExplorer.BuildConfiguration.UserEnvironmentChanges"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">По умолчанию</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">GenericProjectManager.GenericBuildConfiguration</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.BuildConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.DeployConfiguration.0">
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.BuildConfiguration.BuildStepList.0">
|
||||
<value type="int" key="ProjectExplorer.BuildStepList.StepsCount">0</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DefaultDisplayName">Развёртывание</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.DisplayName">Развёртывание</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.BuildSteps.Deploy</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.BuildConfiguration.BuildStepListCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.DeployConfiguration.CustomData"/>
|
||||
<value type="bool" key="ProjectExplorer.DeployConfiguration.CustomDataEnabled">false</value>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.DefaultDeployConfiguration</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.DeployConfigurationCount">1</value>
|
||||
<valuemap type="QVariantMap" key="ProjectExplorer.Target.RunConfiguration.0">
|
||||
<valuelist type="QVariantList" key="CustomOutputParsers"/>
|
||||
<value type="int" key="PE.EnvironmentAspect.Base">2</value>
|
||||
<valuelist type="QVariantList" key="PE.EnvironmentAspect.Changes"/>
|
||||
<value type="QString" key="ProjectExplorer.ProjectConfiguration.Id">ProjectExplorer.CustomExecutableRunConfiguration</value>
|
||||
<value type="QString" key="ProjectExplorer.RunConfiguration.BuildKey"></value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebugger">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseCppDebuggerAuto">true</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebugger">false</value>
|
||||
<value type="bool" key="RunConfiguration.UseQmlDebuggerAuto">true</value>
|
||||
</valuemap>
|
||||
<value type="int" key="ProjectExplorer.Target.RunConfigurationCount">1</value>
|
||||
</valuemap>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.TargetCount</variable>
|
||||
<value type="int">1</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>ProjectExplorer.Project.Updater.FileVersion</variable>
|
||||
<value type="int">22</value>
|
||||
</data>
|
||||
<data>
|
||||
<variable>Version</variable>
|
||||
<value type="int">22</value>
|
||||
</data>
|
||||
</qtcreator>
|
||||
1
G0:G070,G0B1/i2c/i2cscan.cxxflags
Normal file
1
G0:G070,G0B1/i2c/i2cscan.cxxflags
Normal file
@@ -0,0 +1 @@
|
||||
-std=c++17
|
||||
9
G0:G070,G0B1/i2c/i2cscan.files
Normal file
9
G0:G070,G0B1/i2c/i2cscan.files
Normal file
@@ -0,0 +1,9 @@
|
||||
main.c
|
||||
usart.c
|
||||
usart.h
|
||||
strfunc.c
|
||||
strfunc.h
|
||||
proto.c
|
||||
proto.h
|
||||
i2c.c
|
||||
i2c.h
|
||||
4
G0:G070,G0B1/i2c/i2cscan.includes
Normal file
4
G0:G070,G0B1/i2c/i2cscan.includes
Normal file
@@ -0,0 +1,4 @@
|
||||
.
|
||||
../inc
|
||||
../inc/Fx
|
||||
../inc/cm
|
||||
80
G0:G070,G0B1/i2c/main.c
Normal file
80
G0:G070,G0B1/i2c/main.c
Normal file
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* This file is part of the usart project.
|
||||
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stm32g0.h>
|
||||
#include "i2c.h"
|
||||
#include "proto.h"
|
||||
#include "strfunc.h"
|
||||
#include "usart.h"
|
||||
|
||||
// KEY (intpullup->0) - PC0
|
||||
// LED - PC8
|
||||
|
||||
volatile uint32_t Tms = 0;
|
||||
|
||||
/* Called when systick fires */
|
||||
void sys_tick_handler(void){
|
||||
++Tms;
|
||||
}
|
||||
|
||||
static void gpio_setup(void){
|
||||
RCC->IOPENR |= RCC_IOPENR_GPIOCEN; // enable PC
|
||||
// set PC8 as opendrain output, PC0 is pullup input, other as default (AIN)
|
||||
GPIOC->MODER = (0xffffffff & ~(GPIO_MODER_MODE8 | GPIO_MODER_MODE0)) | GPIO_MODER_MODER8_O;
|
||||
GPIOC->PUPDR = GPIO_PUPDR0_PU; // pullup
|
||||
GPIOC->OTYPER = GPIO_OTYPER_OT8; // open drain
|
||||
}
|
||||
|
||||
int main(void){
|
||||
StartHSE();
|
||||
SysTick_Config(8000); // 1ms counter
|
||||
gpio_setup();
|
||||
usart3_setup();
|
||||
uint32_t T = 0;
|
||||
int sent = 0;
|
||||
/* Do nothing in main loop */
|
||||
while (1){
|
||||
if(I2C_scan_mode){
|
||||
uint8_t addr;
|
||||
int ok = i2c_scan_next_addr(&addr);
|
||||
if(addr == I2C_ADDREND) USND("Scan ends\n");
|
||||
else if(ok){
|
||||
USND(uhex2str(addr));
|
||||
USND(" ("); USND(u2str(addr));
|
||||
USND(") - found device\n");
|
||||
}
|
||||
}
|
||||
if(Tms - T > 499){ // blink LED
|
||||
T = Tms;
|
||||
pin_toggle(GPIOC, 1<<8);
|
||||
usart3_sendbuf();
|
||||
}
|
||||
if(pin_read(GPIOC, 1<<0) == 0){ // key pressed - send data over USART
|
||||
if(!sent){
|
||||
usart3_sendstr("Button pressed\n");
|
||||
sent = 1;
|
||||
}
|
||||
}else sent = 0;
|
||||
int wasbo = 0;
|
||||
char *rcv = usart3_getline(&wasbo);
|
||||
if(wasbo) usart3_sendstr("Buffer overflow occured @ last message\n");
|
||||
if(rcv) rcv = parse_cmd(rcv);
|
||||
if(rcv) usart3_sendstr(rcv);
|
||||
i2c_have_DMA_Rx(); // check if there's DMA Rx complete
|
||||
}
|
||||
}
|
||||
89
G0:G070,G0B1/i2c/openocd.cfg
Normal file
89
G0:G070,G0B1/i2c/openocd.cfg
Normal file
@@ -0,0 +1,89 @@
|
||||
# script for stm32g0x family
|
||||
|
||||
#
|
||||
# stm32g0 devices support SWD transports only.
|
||||
#
|
||||
source [find interface/stlink.cfg]
|
||||
source [find target/swj-dp.tcl]
|
||||
source [find mem_helper.tcl]
|
||||
|
||||
if { [info exists CHIPNAME] } {
|
||||
set _CHIPNAME $CHIPNAME
|
||||
} else {
|
||||
set _CHIPNAME stm32g0x
|
||||
}
|
||||
|
||||
set _ENDIAN little
|
||||
|
||||
# Work-area is a space in RAM used for flash programming
|
||||
# Smallest proposed target has 8kB ram, use 4kB by default to avoid surprises
|
||||
if { [info exists WORKAREASIZE] } {
|
||||
set _WORKAREASIZE $WORKAREASIZE
|
||||
} else {
|
||||
set _WORKAREASIZE 0x1000
|
||||
}
|
||||
|
||||
#jtag scan chain
|
||||
if { [info exists CPUTAPID] } {
|
||||
set _CPUTAPID $CPUTAPID
|
||||
} else {
|
||||
# Section 37.5.5 - corresponds to Cortex-M0+
|
||||
set _CPUTAPID 0x0bc11477
|
||||
}
|
||||
|
||||
swj_newdap $_CHIPNAME cpu -irlen 4 -ircapture 0x1 -irmask 0xf -expected-id $_CPUTAPID
|
||||
dap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu
|
||||
|
||||
set _TARGETNAME $_CHIPNAME.cpu
|
||||
target create $_TARGETNAME cortex_m -endian $_ENDIAN -dap $_CHIPNAME.dap
|
||||
|
||||
$_TARGETNAME configure -work-area-phys 0x20000000 -work-area-size $_WORKAREASIZE -work-area-backup 0
|
||||
|
||||
set _FLASHNAME $_CHIPNAME.flash
|
||||
flash bank $_FLASHNAME stm32l4x 0 0 0 0 $_TARGETNAME
|
||||
|
||||
# reasonable default
|
||||
adapter speed 2000
|
||||
|
||||
adapter srst delay 100
|
||||
if {[using_jtag]} {
|
||||
jtag_ntrst_delay 100
|
||||
}
|
||||
|
||||
reset_config srst_nogate
|
||||
|
||||
if {![using_hla]} {
|
||||
# if srst is not fitted use SYSRESETREQ to
|
||||
# perform a soft reset
|
||||
cortex_m reset_config sysresetreq
|
||||
}
|
||||
|
||||
proc stm32g0x_default_reset_start {} {
|
||||
# Reset clock is HSI16 (16 MHz)
|
||||
adapter speed 2000
|
||||
}
|
||||
|
||||
proc stm32g0x_default_examine_end {} {
|
||||
# DBGMCU_CR |= DBG_STANDBY | DBG_STOP
|
||||
mmw 0x40015804 0x00000006 0
|
||||
|
||||
# Stop watchdog counters during halt
|
||||
# DBGMCU_APB1_FZ |= DBG_IWDG_STOP | DBG_WWDG_STOP
|
||||
mmw 0x40015808 0x00001800 0
|
||||
}
|
||||
|
||||
proc stm32g0x_default_reset_init {} {
|
||||
# Increase clock to 64 Mhz
|
||||
mmw 0x40022000 0x00000002 0x00000005 ;# FLASH_ACR: Latency = 2
|
||||
mww 0x4002100C 0x30000802 ;# RCC_PLLCFGR = PLLR=/2, PLLN=8, PLLM=/1, PLLSRC=0x2
|
||||
mmw 0x40021000 0x01000000 0x00000000 ;# RCC_CR |= PLLON
|
||||
mmw 0x40021008 0x00000002 0x00000005 ;# RCC_CFGR: SW=PLLRCLK
|
||||
|
||||
# Boost JTAG frequency
|
||||
adapter speed 4000
|
||||
}
|
||||
|
||||
# Default hooks
|
||||
$_TARGETNAME configure -event examine-end { stm32g0x_default_examine_end }
|
||||
$_TARGETNAME configure -event reset-start { stm32g0x_default_reset_start }
|
||||
$_TARGETNAME configure -event reset-init { stm32g0x_default_reset_init }
|
||||
186
G0:G070,G0B1/i2c/proto.c
Normal file
186
G0:G070,G0B1/i2c/proto.c
Normal file
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
* This file is part of the i2cscan project.
|
||||
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stm32g0.h>
|
||||
#include <string.h>
|
||||
#include "i2c.h"
|
||||
#include "strfunc.h"
|
||||
#include "usart.h"
|
||||
|
||||
#define LOCBUFFSZ (32)
|
||||
// local buffer for I2C data to send
|
||||
static uint8_t locBuffer[LOCBUFFSZ];
|
||||
extern volatile uint32_t Tms;
|
||||
|
||||
const char *helpstring =
|
||||
"i0..2 - setup I2C with lowest..highest speed (7.7, 10 and 100kHz)\n"
|
||||
"Ia addr - set I2C address\n"
|
||||
"Ig - dump content of I2Cbuf\n"
|
||||
"Iw bytes - send bytes (hex/dec/oct/bin) to I2C\n"
|
||||
"IW bytes - the same over DMA\n"
|
||||
"Ir reg n - read n bytes from I2C reg\n"
|
||||
"I2 reg16 n - read n bytes from 16-bit register\n"
|
||||
"In n - just read n bytes\n"
|
||||
"IN n - the same but with DMA\n"
|
||||
"Is - scan I2C bus\n"
|
||||
"T - print current Tms\n"
|
||||
"U - send long buffer over USART\n"
|
||||
;
|
||||
|
||||
const char *longbuff = "=======-10=======-20=======-30=======-40=======-50=======-60=======-70=======-80=======-90======-100\n";
|
||||
static void U3sendlong(const char *str){
|
||||
int l = strlen(str);
|
||||
while(l){
|
||||
int sent = usart3_sendstr(str);
|
||||
str += sent;
|
||||
l -= sent;
|
||||
}
|
||||
}
|
||||
|
||||
static uint8_t i2cinited = 0;
|
||||
TRUE_INLINE char *setupI2C(char *buf){
|
||||
buf = omit_spaces(buf);
|
||||
if(*buf < '0' || *buf > '2') return "Wrong speed";
|
||||
i2c_setup(*buf - '0');
|
||||
i2cinited = 1;
|
||||
return "OK";
|
||||
}
|
||||
|
||||
static uint8_t I2Caddress = 0;
|
||||
TRUE_INLINE char *saI2C(char *buf){
|
||||
uint32_t addr;
|
||||
if(!getnum(buf, &addr) || addr > 0x7f) return "Wrong address";
|
||||
I2Caddress = (uint8_t) addr << 1;
|
||||
USND("I2Caddr="); USND(uhex2str(addr)); USND("\n");
|
||||
return "OK";
|
||||
}
|
||||
static void rdI2C(char *buf, int is16){
|
||||
uint32_t N;
|
||||
int noreg = 0; // write register (==1 - just read, ==2 - -//- using DMA)
|
||||
char *nxt = NULL;
|
||||
if(*buf == 'n'){
|
||||
++buf;
|
||||
noreg = 1;
|
||||
}else if(*buf == 'N'){
|
||||
++buf;
|
||||
noreg = 2;
|
||||
}else{
|
||||
nxt = getnum(buf, &N);
|
||||
if(!nxt || buf == nxt || N > 0xffff || (!is16 && N > 0xff)){
|
||||
USND("Bad register number\n");
|
||||
return;
|
||||
}
|
||||
buf = nxt;
|
||||
}
|
||||
uint16_t reg = N;
|
||||
nxt = getnum(buf, &N);
|
||||
if(!nxt || buf == nxt || N > LOCBUFFSZ){
|
||||
USND("Bad length (<=32)\n");
|
||||
return;
|
||||
}
|
||||
const char *erd = "Error reading I2C\n";
|
||||
if(noreg){ // don't write register
|
||||
if(noreg == 1){
|
||||
USND("Simple read:\n");
|
||||
if(!read_i2c(I2Caddress, locBuffer, N)){
|
||||
USND(erd);
|
||||
return;
|
||||
}
|
||||
}else{
|
||||
USND("Try to read using DMA .. ");
|
||||
if(!read_i2c_dma(I2Caddress, N)) USND(erd);
|
||||
else USND("OK\n");
|
||||
return;
|
||||
}
|
||||
}else{
|
||||
if(is16){
|
||||
if(!read_i2c_reg16(I2Caddress, reg, locBuffer, N)){
|
||||
USND(erd);
|
||||
return;
|
||||
}
|
||||
}else{
|
||||
if(!read_i2c_reg(I2Caddress, reg, locBuffer, N)){
|
||||
USND(erd);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(N == 0){ USND("OK"); return; }
|
||||
if(!noreg){USND("Register "); USND(uhex2str(reg)); USND(":\n");}
|
||||
hexdump(usart3_sendstr, locBuffer, N);
|
||||
}
|
||||
// read N numbers from buf, @return 0 if wrong or none
|
||||
TRUE_INLINE uint16_t readNnumbers(char *buf){
|
||||
uint32_t D;
|
||||
char *nxt;
|
||||
uint16_t N = 0;
|
||||
while((nxt = getnum(buf, &D)) && nxt != buf && N < LOCBUFFSZ){
|
||||
buf = nxt;
|
||||
locBuffer[N++] = (uint8_t) D&0xff;
|
||||
USND("add byte: "); USND(uhex2str(D&0xff)); USND("\n");
|
||||
}
|
||||
USND("Send "); USND(u2str(N)); USND(" bytes\n");
|
||||
return N;
|
||||
}
|
||||
static char *wrI2C(char *buf, int isdma){
|
||||
uint16_t N = readNnumbers(buf);
|
||||
int result = isdma ? write_i2c_dma(I2Caddress, locBuffer, N) :
|
||||
write_i2c(I2Caddress, locBuffer, N);
|
||||
if(!result) return "Error writing I2C";
|
||||
return "OK";
|
||||
}
|
||||
|
||||
|
||||
char *parse_cmd(char *buf){
|
||||
// "long" commands
|
||||
switch(*buf){
|
||||
case 'i':
|
||||
return setupI2C(buf + 1);
|
||||
break;
|
||||
case 'I':
|
||||
if(!i2cinited) return "Init I2C first";
|
||||
buf = omit_spaces(buf + 1);
|
||||
if(*buf == 'a') return saI2C(buf + 1);
|
||||
else if(*buf == 'r'){ rdI2C(buf + 1, 0); return NULL; }
|
||||
else if(*buf == '2'){ rdI2C(buf + 1, 1); return NULL; }
|
||||
else if(*buf == 'n'){ rdI2C(buf, 0); return NULL; }
|
||||
else if(*buf == 'N'){ rdI2C(buf, 0); return NULL; }
|
||||
else if(*buf == 'w') return wrI2C(buf + 1, 0);
|
||||
else if(*buf == 'W') return wrI2C(buf + 1, 1);
|
||||
else if(*buf == 's'){ i2c_init_scan_mode(); return "Start scan\n"; }
|
||||
else if(*buf == 'g'){ i2c_bufdudump(); return NULL; }
|
||||
else return "Command should be 'Ia', 'Iw', 'Ir' or 'Is'\n";
|
||||
break;
|
||||
}
|
||||
// "short" commands
|
||||
if(buf[1]) return buf; // echo wrong data
|
||||
switch(*buf){
|
||||
case 'T':
|
||||
usart3_sendstr("T=");
|
||||
usart3_sendstr(u2str(Tms));
|
||||
usart3_send("\n", 1);
|
||||
break;
|
||||
case 'U':
|
||||
U3sendlong(longbuff);
|
||||
break;
|
||||
default: // help
|
||||
U3sendlong(helpstring);
|
||||
break;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
22
G0:G070,G0B1/i2c/proto.h
Normal file
22
G0:G070,G0B1/i2c/proto.h
Normal file
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* This file is part of the i2cscan project.
|
||||
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
char *parse_cmd(char *buf);
|
||||
|
||||
BIN
G0:G070,G0B1/i2c/rtc.bin
Executable file
BIN
G0:G070,G0B1/i2c/rtc.bin
Executable file
Binary file not shown.
255
G0:G070,G0B1/i2c/strfunc.c
Normal file
255
G0:G070,G0B1/i2c/strfunc.c
Normal file
@@ -0,0 +1,255 @@
|
||||
/*
|
||||
* This file is part of the i2cscan project.
|
||||
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stm32g0.h>
|
||||
|
||||
/**
|
||||
* @brief hexdump - dump hex array by 16 bytes in string
|
||||
* @param sendfun - function to send data
|
||||
* @param arr - array to dump
|
||||
* @param len - length of `arr`
|
||||
*/
|
||||
void hexdump(int (*sendfun)(const char *s), uint8_t *arr, uint16_t len){
|
||||
char buf[52], *bptr = buf;
|
||||
for(uint16_t l = 0; l < len; ++l, ++arr){
|
||||
for(int16_t j = 1; j > -1; --j){
|
||||
register uint8_t half = (*arr >> (4*j)) & 0x0f;
|
||||
if(half < 10) *bptr++ = half + '0';
|
||||
else *bptr++ = half - 10 + 'a';
|
||||
}
|
||||
if(l % 16 == 15){
|
||||
*bptr++ = '\n';
|
||||
*bptr = 0;
|
||||
sendfun(buf);
|
||||
bptr = buf;
|
||||
}else *bptr++ = ' ';
|
||||
}
|
||||
if(bptr != buf){
|
||||
*bptr++ = '\n';
|
||||
*bptr = 0;
|
||||
sendfun(buf);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief _2str - convert value into string buffer
|
||||
* @param val - |value|
|
||||
* @param minus - ==0 if value > 0
|
||||
* @return buffer with number
|
||||
*/
|
||||
static char *_2str(uint32_t val, uint8_t minus){
|
||||
static char strbuf[12];
|
||||
char *bufptr = &strbuf[11];
|
||||
*bufptr = 0;
|
||||
if(!val){
|
||||
*(--bufptr) = '0';
|
||||
}else{
|
||||
while(val){
|
||||
*(--bufptr) = val % 10 + '0';
|
||||
val /= 10;
|
||||
}
|
||||
}
|
||||
if(minus) *(--bufptr) = '-';
|
||||
return bufptr;
|
||||
}
|
||||
|
||||
// return string with number `val`
|
||||
char *u2str(uint32_t val){
|
||||
return _2str(val, 0);
|
||||
}
|
||||
char *i2str(int32_t i){
|
||||
uint8_t minus = 0;
|
||||
uint32_t val;
|
||||
if(i < 0){
|
||||
minus = 1;
|
||||
val = -i;
|
||||
}else val = i;
|
||||
return _2str(val, minus);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief uhex2str - print 32bit unsigned int as hex
|
||||
* @param val - value
|
||||
* @return string with number
|
||||
*/
|
||||
char *uhex2str(uint32_t val){
|
||||
static char buf[12] = "0x";
|
||||
int npos = 2;
|
||||
uint8_t *ptr = (uint8_t*)&val + 3;
|
||||
int8_t i, j, z=1;
|
||||
for(i = 0; i < 4; ++i, --ptr){
|
||||
if(*ptr == 0){ // omit leading zeros
|
||||
if(i == 3) z = 0;
|
||||
if(z) continue;
|
||||
}
|
||||
else z = 0;
|
||||
for(j = 1; j > -1; --j){
|
||||
uint8_t half = (*ptr >> (4*j)) & 0x0f;
|
||||
if(half < 10) buf[npos++] = half + '0';
|
||||
else buf[npos++] = half - 10 + 'a';
|
||||
}
|
||||
}
|
||||
buf[npos] = 0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief omit_spaces - eliminate leading spaces and other trash in string
|
||||
* @param buf - string
|
||||
* @return - pointer to first character in `buf` > ' '
|
||||
*/
|
||||
char *omit_spaces(const char *buf){
|
||||
while(*buf){
|
||||
if(*buf > ' ') break;
|
||||
++buf;
|
||||
}
|
||||
return (char*)buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief getdec - read decimal number & return pointer to next non-number symbol
|
||||
* @param buf - string
|
||||
* @param N - number read
|
||||
* @return Next non-number symbol. In case of overflow return `buf` and N==0xffffffff
|
||||
*/
|
||||
static char *getdec(const char *buf, uint32_t *N){
|
||||
char *start = (char*)buf;
|
||||
uint32_t num = 0;
|
||||
while(*buf){
|
||||
char c = *buf;
|
||||
if(c < '0' || c > '9'){
|
||||
break;
|
||||
}
|
||||
if(num > 429496729 || (num == 429496729 && c > '5')){ // overflow
|
||||
*N = 0xffffff;
|
||||
return start;
|
||||
}
|
||||
num *= 10;
|
||||
num += c - '0';
|
||||
++buf;
|
||||
}
|
||||
*N = num;
|
||||
return (char*)buf;
|
||||
}
|
||||
// read hexadecimal number (without 0x prefix!)
|
||||
static char *gethex(const char *buf, uint32_t *N){
|
||||
char *start = (char*)buf;
|
||||
uint32_t num = 0;
|
||||
while(*buf){
|
||||
char c = *buf;
|
||||
uint8_t M = 0;
|
||||
if(c >= '0' && c <= '9'){
|
||||
M = '0';
|
||||
}else if(c >= 'A' && c <= 'F'){
|
||||
M = 'A' - 10;
|
||||
}else if(c >= 'a' && c <= 'f'){
|
||||
M = 'a' - 10;
|
||||
}
|
||||
if(M){
|
||||
if(num & 0xf0000000){ // overflow
|
||||
*N = 0xffffff;
|
||||
return start;
|
||||
}
|
||||
num <<= 4;
|
||||
num += c - M;
|
||||
}else{
|
||||
break;
|
||||
}
|
||||
++buf;
|
||||
}
|
||||
*N = num;
|
||||
return (char*)buf;
|
||||
}
|
||||
// read octal number (without 0 prefix!)
|
||||
static char *getoct(const char *buf, uint32_t *N){
|
||||
char *start = (char*)buf;
|
||||
uint32_t num = 0;
|
||||
while(*buf){
|
||||
char c = *buf;
|
||||
if(c < '0' || c > '7'){
|
||||
break;
|
||||
}
|
||||
if(num & 0xe0000000){ // overflow
|
||||
*N = 0xffffff;
|
||||
return start;
|
||||
}
|
||||
num <<= 3;
|
||||
num += c - '0';
|
||||
++buf;
|
||||
}
|
||||
*N = num;
|
||||
return (char*)buf;
|
||||
}
|
||||
// read binary number (without b prefix!)
|
||||
static char *getbin(const char *buf, uint32_t *N){
|
||||
char *start = (char*)buf;
|
||||
uint32_t num = 0;
|
||||
while(*buf){
|
||||
char c = *buf;
|
||||
if(c < '0' || c > '1'){
|
||||
break;
|
||||
}
|
||||
if(num & 0x80000000){ // overflow
|
||||
*N = 0xffffff;
|
||||
return start;
|
||||
}
|
||||
num <<= 1;
|
||||
if(c == '1') num |= 1;
|
||||
++buf;
|
||||
}
|
||||
*N = num;
|
||||
return (char*)buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief getnum - read uint32_t from string (dec, hex or bin: 127, 0x7f, 0b1111111)
|
||||
* @param buf - buffer with number and so on
|
||||
* @param N - the number read
|
||||
* @return pointer to first non-number symbol in buf
|
||||
* (if it is == buf, there's no number or if *N==0xffffffff there was overflow)
|
||||
*/
|
||||
char *getnum(const char *txt, uint32_t *N){
|
||||
char *nxt = NULL;
|
||||
char *s = omit_spaces(txt);
|
||||
if(*s == '0'){ // hex, oct or 0
|
||||
if(s[1] == 'x' || s[1] == 'X'){ // hex
|
||||
nxt = gethex(s+2, N);
|
||||
if(nxt == s+2) nxt = (char*)txt;
|
||||
}else if(s[1] > '0'-1 && s[1] < '8'){ // oct
|
||||
nxt = getoct(s+1, N);
|
||||
if(nxt == s+1) nxt = (char*)txt;
|
||||
}else{ // 0
|
||||
nxt = s+1;
|
||||
*N = 0;
|
||||
}
|
||||
}else if(*s == 'b' || *s == 'B'){
|
||||
nxt = getbin(s+1, N);
|
||||
if(nxt == s+1) nxt = (char*)txt;
|
||||
}else{
|
||||
nxt = getdec(s, N);
|
||||
if(nxt == s) nxt = (char*)txt;
|
||||
}
|
||||
return nxt;
|
||||
}
|
||||
|
||||
/*
|
||||
void mymemcpy(char *dest, const char *src, int len){
|
||||
if(len < 1) return;
|
||||
while(len--) *dest++ = *src++;
|
||||
}
|
||||
*/
|
||||
29
G0:G070,G0B1/i2c/strfunc.h
Normal file
29
G0:G070,G0B1/i2c/strfunc.h
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* This file is part of the i2cscan project.
|
||||
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string.h>
|
||||
|
||||
void hexdump(int (*sendfun)(const char *s), uint8_t *arr, uint16_t len);
|
||||
char *u2str(uint32_t val);
|
||||
char *i2str(int32_t i);
|
||||
char *uhex2str(uint32_t val);
|
||||
char *getnum(const char *txt, uint32_t *N);
|
||||
char *omit_spaces(const char *buf);
|
||||
void mymemcpy(char *dest, const char *src, int len);
|
||||
169
G0:G070,G0B1/i2c/usart.c
Normal file
169
G0:G070,G0B1/i2c/usart.c
Normal file
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* This file is part of the usart project.
|
||||
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stm32g0.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "usart.h"
|
||||
|
||||
// RX/TX DMA->CCR without EN flag
|
||||
#define DMARXCCR (DMA_CCR_MINC | DMA_CCR_TCIE | DMA_CCR_TEIE)
|
||||
#define DMATXCCR (DMA_CCR_MINC | DMA_CCR_DIR | DMA_CCR_TCIE | DMA_CCR_TEIE)
|
||||
|
||||
volatile int u3txrdy = 1, u3rxrdy = 0; // transmission done, next line received
|
||||
static volatile int bufovr = 0, wasbufovr = 0; // Rx buffer overflow or error flag -> delete next line
|
||||
static volatile int rbufno = 0, tbufno = 0; // current buf number
|
||||
static volatile char rbuf[2][UARTBUFSZ], tbuf[2][UARTBUFSZ]; // receive & transmit buffers
|
||||
static volatile int rxlen[2] = {0}, txlen[2] = {0};
|
||||
|
||||
char *usart3_getline(int *wasbo){
|
||||
if(wasbo) *wasbo = wasbufovr;
|
||||
wasbufovr = 0;
|
||||
if(!u3rxrdy) return NULL;
|
||||
u3rxrdy = 0; // clear ready flag
|
||||
return (char*)rbuf[!rbufno]; // current buffer is in filling stage, return old - filled - buffer
|
||||
}
|
||||
|
||||
#define USART_BRR(speed) ((64000000 + speed/2) / speed)
|
||||
|
||||
// USART3 @ PD8 (Tx) and PD9 (Rx) - both AF0
|
||||
void usart3_setup(){
|
||||
RCC->IOPENR |= RCC_IOPENR_GPIODEN; // enable PD
|
||||
RCC->AHBENR |= RCC_AHBENR_DMA1EN; // enable DMA1
|
||||
// set PD8 and PD9 as AF
|
||||
GPIOD->MODER = (GPIOD->MODER & ~(GPIO_MODER_MODE8 | GPIO_MODER_MODE9))
|
||||
| GPIO_MODER_MODER8_AF | GPIO_MODER_MODER9_AF;
|
||||
// AF0 for USART3 @ PD8/PD9
|
||||
GPIOD->AFR[1] = GPIOD->AFR[1] & ~(GPIO_AFRH_AFSEL8 | GPIO_AFRH_AFSEL9);
|
||||
// enable USART3 clocking
|
||||
RCC->APBENR1 |= RCC_APBENR1_USART3EN;
|
||||
// baudrate 115200
|
||||
USART3->BRR = USART_BRR(115200);
|
||||
// eol character: '/n'
|
||||
USART3->CR2 = USART_CR2_ADD_VAL('\n');
|
||||
// enable DMA transmission
|
||||
USART3->CR3 = USART_CR3_DMAT | USART_CR3_DMAR;
|
||||
// set up DMA channels: 2 - Tx, 3 - Rx
|
||||
// Tx channel: mem++, mem->periph, 8bit, compl.&err. irq
|
||||
DMA1_Channel2->CCR = DMATXCCR;
|
||||
DMA1_Channel2->CPAR = (uint32_t) &USART3->TDR; // peripherial address
|
||||
// Rx channel: mem++, periph->mem, 8bit, compl.&err. irq
|
||||
DMA1_Channel3->CCR = DMARXCCR;
|
||||
DMA1_Channel3->CPAR = (uint32_t) &USART3->RDR; // peripherial address
|
||||
DMA1_Channel3->CNDTR = UARTBUFSZ;
|
||||
DMA1_Channel3->CMAR = (uint32_t)&rbuf[rbufno];
|
||||
// set up DMAMUX channels: 55 - USART3_TX, 54 - USART3_RX
|
||||
// enumeration of DMAMUX starts from 0 (DMA - from 1)!
|
||||
DMAMUX1_Channel1->CCR = 55;
|
||||
DMAMUX1_Channel2->CCR = 54;
|
||||
// charmatch interrupt, enable transmitter and receiver, enable usart
|
||||
USART3->CR1 = USART_CR1_CMIE | USART_CR1_TE | USART_CR1_RE | USART_CR1_UE;
|
||||
USART3->ICR = 0xffffffff; // clear all flags
|
||||
DMA1_Channel3->CCR = DMARXCCR | DMA_CCR_EN; // start receiving right now
|
||||
NVIC_EnableIRQ(USART3_4_IRQn);
|
||||
NVIC_EnableIRQ(DMA1_Channel2_3_IRQn);
|
||||
}
|
||||
|
||||
int usart3_send(const char *str, int len){
|
||||
int rest = UARTBUFSZ - txlen[tbufno];
|
||||
if(rest == 0 && !u3txrdy) return 0; // buffer is full while transmission in process
|
||||
if(len < rest) rest = len;
|
||||
memcpy((char*)(tbuf[tbufno] + txlen[tbufno]), str, rest);
|
||||
txlen[tbufno] += rest;
|
||||
if(!u3txrdy) return rest;
|
||||
if(txlen[tbufno] == UARTBUFSZ) usart3_sendbuf();
|
||||
if(rest == len) return len;
|
||||
len -= rest;
|
||||
// now fill another - empty - buffer
|
||||
if(len > UARTBUFSZ) len = UARTBUFSZ;
|
||||
memcpy((char*)tbuf[tbufno], str + rest, len);
|
||||
txlen[tbufno] = len;
|
||||
return rest + len;
|
||||
}
|
||||
|
||||
int usart3_sendstr(const char *str){
|
||||
int l = strlen(str);
|
||||
return usart3_send(str, l);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief usart3_sendbuf - send current buffer
|
||||
*/
|
||||
void usart3_sendbuf(){
|
||||
if(!u3txrdy || txlen[tbufno] == 0) return;
|
||||
// set up DMA
|
||||
DMA1_Channel2->CCR = DMATXCCR;
|
||||
DMA1_Channel2->CMAR = (uint32_t)&tbuf[tbufno];
|
||||
DMA1_Channel2->CNDTR = txlen[tbufno];
|
||||
USART3->ICR = USART_ICR_TCCF; // clear TC flag
|
||||
u3txrdy = 0;
|
||||
// activate DMA
|
||||
DMA1_Channel2->CCR = DMATXCCR | DMA_CCR_EN;
|
||||
tbufno = !tbufno; // swap buffers
|
||||
txlen[tbufno] = 0;
|
||||
}
|
||||
|
||||
// return amount of bytes sents
|
||||
int usart3_send_blocking(const char *str, int len){
|
||||
if(!u3txrdy) return 0;
|
||||
USART3->CR1 |= USART_CR1_TE;
|
||||
for(int i = 0; i < len; ++i){
|
||||
while(!(USART3->ISR & USART_ISR_TXE_TXFNF));
|
||||
USART3->TDR = *str++;
|
||||
}
|
||||
return len;
|
||||
}
|
||||
|
||||
// interrupt by '\n'
|
||||
void usart3_4_isr(){
|
||||
if(USART3->ISR & USART_ISR_CMF){ // got '\n' @ USART3
|
||||
DMA1_Channel3->CCR = DMARXCCR;
|
||||
if(!bufovr){ // forget about broken line @ buffer overflow
|
||||
u3rxrdy = 1;
|
||||
int l = UARTBUFSZ - DMA1_Channel3->CNDTR - 1; // strlen
|
||||
rxlen[rbufno] = l;
|
||||
rbuf[rbufno][l] = 0;
|
||||
rbufno = !rbufno;
|
||||
}else{
|
||||
bufovr = 0;
|
||||
wasbufovr = 1;
|
||||
}
|
||||
// reload DMA Rx with next buffer
|
||||
DMA1_Channel3->CMAR = (uint32_t)&rbuf[rbufno];
|
||||
DMA1_Channel3->CNDTR = UARTBUFSZ;
|
||||
DMA1_Channel3->CCR = DMARXCCR | DMA_CCR_EN;
|
||||
}
|
||||
USART3->ICR = 0xffffffff; // clear all flags
|
||||
}
|
||||
|
||||
// ch2 - Tx, ch3 - Rx
|
||||
void dma1_channel2_3_isr(){
|
||||
uint32_t isr = DMA1->ISR;
|
||||
if(isr & (DMA_ISR_TCIF2 | DMA_ISR_TEIF2)){ // transfer complete or error
|
||||
u3txrdy = 1;
|
||||
}
|
||||
if(isr & (DMA_ISR_TCIF3 | DMA_ISR_TEIF3)){ // receive complete or error -> buffer overflow
|
||||
if(rbuf[rbufno][UARTBUFSZ-1] != '\n'){ // last symbol is not a newline
|
||||
bufovr = 1;
|
||||
DMA1_Channel3->CCR = DMARXCCR;
|
||||
DMA1_Channel3->CNDTR = UARTBUFSZ;
|
||||
DMA1_Channel3->CCR = DMARXCCR | DMA_CCR_EN;
|
||||
}
|
||||
}
|
||||
DMA1->IFCR = 0xff0; // clear all flags for 2&3
|
||||
}
|
||||
32
G0:G070,G0B1/i2c/usart.h
Normal file
32
G0:G070,G0B1/i2c/usart.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* This file is part of the usart project.
|
||||
* Copyright 2023 Edward V. Emelianov <edward.emelianoff@gmail.com>.
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define UARTBUFSZ (64)
|
||||
|
||||
#define USND(t) do{usart3_sendstr(t);}while(0)
|
||||
|
||||
extern volatile int u3txrdy, u3rxrdy;
|
||||
|
||||
void usart3_setup();
|
||||
int usart3_send_blocking(const char *str, int len);
|
||||
int usart3_send(const char *str, int len);
|
||||
void usart3_sendbuf();
|
||||
char *usart3_getline(int *wasbo);
|
||||
int usart3_sendstr(const char *str);
|
||||
2
G0:G070,G0B1/i2c/version.inc
Normal file
2
G0:G070,G0B1/i2c/version.inc
Normal file
@@ -0,0 +1,2 @@
|
||||
#define BUILD_NUMBER "1"
|
||||
#define BUILD_DATE "2023-01-18"
|
||||
61
G0:G070,G0B1/inc/Fx/common_macros.h
Normal file
61
G0:G070,G0B1/inc/Fx/common_macros.h
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* common_macros.h - common usable things
|
||||
*
|
||||
* Copyright 2018 Edward V. Emelianoff <eddy@sao.ru, edward.emelianoff@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301, USA.
|
||||
*/
|
||||
#pragma once
|
||||
#ifndef __COMMON_MACROS_H__
|
||||
#define __COMMON_MACROS_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef _U_
|
||||
#define _U_ __attribute__((__unused__))
|
||||
#endif
|
||||
|
||||
#ifndef TRUE
|
||||
#define TRUE 1
|
||||
#endif
|
||||
|
||||
#ifndef FALSE
|
||||
#define FALSE 0
|
||||
#endif
|
||||
|
||||
#ifndef TRUE_INLINE
|
||||
#define TRUE_INLINE __attribute__((always_inline)) static inline
|
||||
#endif
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL (0)
|
||||
#endif
|
||||
|
||||
// some good things from CMSIS
|
||||
#define nop() __NOP()
|
||||
|
||||
#define pin_toggle(gpioport, gpios) do{ \
|
||||
register uint32_t __port = gpioport->ODR; \
|
||||
gpioport->BSRR = ((__port & (gpios)) << 16) | (~__port & (gpios));}while(0)
|
||||
|
||||
#define pin_set(gpioport, gpios) do{gpioport->BSRR = gpios;}while(0)
|
||||
#define pin_clear(gpioport, gpios) do{gpioport->BSRR = ((gpios) << 16);}while(0)
|
||||
#define pin_read(gpioport, gpios) (gpioport->IDR & (gpios) ? 1 : 0)
|
||||
#define pin_write(gpioport, gpios) do{gpioport->ODR = gpios;}while(0)
|
||||
|
||||
|
||||
|
||||
#endif // __COMMON_MACROS_H__
|
||||
12
G0:G070,G0B1/inc/Fx/flash_size_reg.h
Normal file
12
G0:G070,G0B1/inc/Fx/flash_size_reg.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#define STM32F0_FlashAddr 0x1FFFF7CC // âÁÚÏ×ÙÊ ÁÄÒÅÓ ÅÍËÏÓÔÉ ÆÌÜÛ-ÐÁÍÑÔÉ STM32F0
|
||||
#define STM32F1_FlashAddr 0x1FFFF7E0 // âÁÚÏ×ÙÊ ÁÄÒÅÓ ÅÍËÏÓÔÉ ÆÌÜÛ-ÐÁÍÑÔÉ STM32F1
|
||||
#define STM32F2_FlashAddr 0x1FFF7A22 // âÁÚÏ×ÙÊ ÁÄÒÅÓ ÅÍËÏÓÔÉ ÆÌÜÛ-ÐÁÍÑÔÉ STM32F2
|
||||
#define STM32F3_FlashAddr 0x1FFFF7CC // âÁÚÏ×ÙÊ ÁÄÒÅÓ ÅÍËÏÓÔÉ ÆÌÜÛ-ÐÁÍÑÔÉ STM32F3
|
||||
#define STM32F4_FlashAddr 0x1FFF7A22 // âÁÚÏ×ÙÊ ÁÄÒÅÓ ÅÍËÏÓÔÉ ÆÌÜÛ-ÐÁÍÑÔÉ STM32F4
|
||||
#define STM32F7_FlashAddr 0x1FF0F442 // âÁÚÏ×ÙÊ ÁÄÒÅÓ ÆÌÜÛ-ÐÁÍÑÔÉ STM32F7
|
||||
#define STM32L0_FlashAddr 0x1FF8007C // âÁÚÏ×ÙÊ ÁÄÒÅÓ ÅÍËÏÓÔÉ ÆÌÜÛ-ÐÁÍÑÔÉ STM32L0
|
||||
#define STM32L1_FlashAddr 0x1FF8004C // âÁÚÏ×ÙÊ ÁÄÒÅÓ ÅÍËÏÓÔÉ ÆÌÜÛ-ÐÁÍÑÔÉ STM32L1
|
||||
#define STM32L4_FlashAddr 0x1FFF75E0 // âÁÚÏ×ÙÊ ÁÄÒÅÓ ÅÍËÏÓÔÉ ÆÌÜÛ-ÐÁÍÑÔÉ STM32L4
|
||||
#define STM32H7_FlashAddr 0x1FF0F442 // âÁÚÏ×ÙÊ ÁÄÒÅÓ ÆÌÜÛ-ÐÁÍÑÔÉ STM32H7
|
||||
|
||||
blocksize=2k if memory>=128k
|
||||
260
G0:G070,G0B1/inc/Fx/stm32g0.h
Normal file
260
G0:G070,G0B1/inc/Fx/stm32g0.h
Normal file
@@ -0,0 +1,260 @@
|
||||
/*
|
||||
* stm32f0.h
|
||||
*
|
||||
* Copyright 2017 Edward V. Emelianoff <eddy@sao.ru, edward.emelianoff@gmail.com>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
||||
* MA 02110-1301, USA.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "vector.h"
|
||||
#include "stm32g0xx.h"
|
||||
#include "common_macros.h"
|
||||
|
||||
|
||||
/************************* RCC *************************/
|
||||
// reset clocking registers
|
||||
/* TRUE_INLINE void sysreset(void){ // do nothing
|
||||
}
|
||||
*/
|
||||
|
||||
/*
|
||||
* R=2..8, Q=2..8, P=2..32; N=8..86, M=1..8
|
||||
* fvco = 64..344MHz (after /M should be 2.66..16 -> for 8MHz HSE M=1..3!!!)
|
||||
* For 8MHZ:
|
||||
* fvco = (8/M)*N -> N(128)=16, M(128)=1
|
||||
* fpllp = fvco/P (<=122MHz) -> P(64)=2
|
||||
* fpllq = fvco/Q (<=128MHz) -> Q(64)=2
|
||||
* fpllr = fvco/R (<=64MHz) -> R(64)=2
|
||||
* AHB prescaler (64MHz) = 1
|
||||
* APB prescaler (64MHz) = 1
|
||||
*
|
||||
* fp=fq=fr=fsys=64MHz => M=1, N=16, P=2, Q=2, R=2
|
||||
*/
|
||||
#ifndef PLLN
|
||||
#define PLLN 16
|
||||
#endif
|
||||
#ifndef PLLM
|
||||
#define PLLM 1
|
||||
#endif
|
||||
#ifndef PLLP
|
||||
#define PLLP 2
|
||||
#endif
|
||||
#ifndef PLLQ
|
||||
#define PLLQ 2
|
||||
#endif
|
||||
#ifndef PLLR
|
||||
#define PLLR 2
|
||||
#endif
|
||||
#ifndef PPRE
|
||||
#define PPRE 1
|
||||
#endif
|
||||
#ifndef HPRE
|
||||
#define HPRE 1
|
||||
#endif
|
||||
|
||||
#define WAITWHILE(x) do{register uint32_t StartUpCounter = 0; while((x) && (++StartUpCounter < 0xffffff)){nop();}}while(0)
|
||||
TRUE_INLINE void StartHSEHSI(int isHSE){
|
||||
RCC->CR &= ~RCC_CR_PLLON; // disable PLL
|
||||
WAITWHILE(RCC->CR & RCC_CR_PLLRDY); // wait while PLL on
|
||||
if(isHSE){
|
||||
RCC->CR |= RCC_CR_HSEON;
|
||||
WAITWHILE(!(RCC->CR & RCC_CR_HSERDY)); // wait while HSE isn't on
|
||||
}else RCC->CR |= RCC_CR_HSION;
|
||||
RCC->APBENR1 |= RCC_APBENR1_PWREN;
|
||||
// Enable high performance mode
|
||||
PWR->CR1 = PWR_CR1_VOS_0;
|
||||
WAITWHILE(PWR->SR2 & PWR_SR2_VOSF);
|
||||
if(isHSE){
|
||||
RCC->PLLCFGR = ((PLLR-1)<<29) | ((PLLQ-1)<<25) | ((PLLP-1)<<17) | (PLLN<<8) | ((PLLM-1)<<4)
|
||||
| RCC_PLLCFGR_PLLREN | RCC_PLLCFGR_PLLQEN /* | RCC_PLLCFGR_PLLPEN */
|
||||
| RCC_PLLCFGR_PLLSRC_HSE;
|
||||
}else{ // 64MHz from HSI16
|
||||
RCC->PLLCFGR = (8<<8) | (1<<4)
|
||||
// enable P if need
|
||||
| RCC_PLLCFGR_PLLREN | RCC_PLLCFGR_PLLQEN /* | RCC_PLLCFGR_PLLPEN */
|
||||
| RCC_PLLCFGR_PLLSRC_HSI;
|
||||
}
|
||||
RCC->CR |= RCC_CR_PLLON;
|
||||
WAITWHILE(!(RCC->CR & RCC_CR_PLLRDY));
|
||||
FLASH->ACR |= FLASH_ACR_PRFTEN | FLASH_ACR_ICEN | FLASH_ACR_LATENCY_2; // FLASH_ACR_LATENCY_2 for 64MHz
|
||||
// set sysclk switch to pll, setup AHB/APB
|
||||
RCC->CFGR = RCC_CFGR_SW_1 | PPRE << 12 | HPRE << 8;
|
||||
}
|
||||
|
||||
#define StartHSE() do{StartHSEHSI(1);}while(0)
|
||||
#define StartHSI() do{StartHSEHSI(0);}while(0)
|
||||
|
||||
/************************* GPIO *************************/
|
||||
|
||||
/******************* Bit definition for GPIO_MODER register *****************/
|
||||
// _AI - analog inpt, _O - general output, _AF - alternate function
|
||||
#define GPIO_MODER_MODER0_AI ((uint32_t)0x00000003)
|
||||
#define GPIO_MODER_MODER0_O ((uint32_t)0x00000001)
|
||||
#define GPIO_MODER_MODER0_AF ((uint32_t)0x00000002)
|
||||
#define GPIO_MODER_MODER1_AI ((uint32_t)0x0000000C)
|
||||
#define GPIO_MODER_MODER1_O ((uint32_t)0x00000004)
|
||||
#define GPIO_MODER_MODER1_AF ((uint32_t)0x00000008)
|
||||
#define GPIO_MODER_MODER2_AI ((uint32_t)0x00000030)
|
||||
#define GPIO_MODER_MODER2_O ((uint32_t)0x00000010)
|
||||
#define GPIO_MODER_MODER2_AF ((uint32_t)0x00000020)
|
||||
#define GPIO_MODER_MODER3_AI ((uint32_t)0x000000C0)
|
||||
#define GPIO_MODER_MODER3_O ((uint32_t)0x00000040)
|
||||
#define GPIO_MODER_MODER3_AF ((uint32_t)0x00000080)
|
||||
#define GPIO_MODER_MODER4_AI ((uint32_t)0x00000300)
|
||||
#define GPIO_MODER_MODER4_O ((uint32_t)0x00000100)
|
||||
#define GPIO_MODER_MODER4_AF ((uint32_t)0x00000200)
|
||||
#define GPIO_MODER_MODER5_AI ((uint32_t)0x00000C00)
|
||||
#define GPIO_MODER_MODER5_O ((uint32_t)0x00000400)
|
||||
#define GPIO_MODER_MODER5_AF ((uint32_t)0x00000800)
|
||||
#define GPIO_MODER_MODER6_AI ((uint32_t)0x00003000)
|
||||
#define GPIO_MODER_MODER6_O ((uint32_t)0x00001000)
|
||||
#define GPIO_MODER_MODER6_AF ((uint32_t)0x00002000)
|
||||
#define GPIO_MODER_MODER7_AI ((uint32_t)0x0000C000)
|
||||
#define GPIO_MODER_MODER7_O ((uint32_t)0x00004000)
|
||||
#define GPIO_MODER_MODER7_AF ((uint32_t)0x00008000)
|
||||
#define GPIO_MODER_MODER8_AI ((uint32_t)0x00030000)
|
||||
#define GPIO_MODER_MODER8_O ((uint32_t)0x00010000)
|
||||
#define GPIO_MODER_MODER8_AF ((uint32_t)0x00020000)
|
||||
#define GPIO_MODER_MODER9_AI ((uint32_t)0x000C0000)
|
||||
#define GPIO_MODER_MODER9_O ((uint32_t)0x00040000)
|
||||
#define GPIO_MODER_MODER9_AF ((uint32_t)0x00080000)
|
||||
#define GPIO_MODER_MODER10_AI ((uint32_t)0x00300000)
|
||||
#define GPIO_MODER_MODER10_O ((uint32_t)0x00100000)
|
||||
#define GPIO_MODER_MODER10_AF ((uint32_t)0x00200000)
|
||||
#define GPIO_MODER_MODER11_AI ((uint32_t)0x00C00000)
|
||||
#define GPIO_MODER_MODER11_O ((uint32_t)0x00400000)
|
||||
#define GPIO_MODER_MODER11_AF ((uint32_t)0x00800000)
|
||||
#define GPIO_MODER_MODER12_AI ((uint32_t)0x03000000)
|
||||
#define GPIO_MODER_MODER12_O ((uint32_t)0x01000000)
|
||||
#define GPIO_MODER_MODER12_AF ((uint32_t)0x02000000)
|
||||
#define GPIO_MODER_MODER13_AI ((uint32_t)0x0C000000)
|
||||
#define GPIO_MODER_MODER13_O ((uint32_t)0x04000000)
|
||||
#define GPIO_MODER_MODER13_AF ((uint32_t)0x08000000)
|
||||
#define GPIO_MODER_MODER14_AI ((uint32_t)0x30000000)
|
||||
#define GPIO_MODER_MODER14_O ((uint32_t)0x10000000)
|
||||
#define GPIO_MODER_MODER14_AF ((uint32_t)0x20000000)
|
||||
#define GPIO_MODER_MODER15_AI ((uint32_t)0xC0000000)
|
||||
#define GPIO_MODER_MODER15_O ((uint32_t)0x40000000)
|
||||
#define GPIO_MODER_MODER15_AF ((uint32_t)0x80000000)
|
||||
|
||||
/******************* Bit definition for GPIO_PUPDR register *****************/
|
||||
// no/pullup/pulldown/reserved
|
||||
// for n in $(seq 0 15); do echo "#define GPIO_PUPDR${n}_PU ((uint32_t)(1<<$((n*2))))";
|
||||
// echo "#define GPIO_PUPDR${n}_PD ((uint32_t)(1<<$((n*2+1))))"; done
|
||||
// alt+select column -> delete
|
||||
#define GPIO_PUPDR0_PU ((uint32_t)(1<<0))
|
||||
#define GPIO_PUPDR0_PD ((uint32_t)(1<<1))
|
||||
#define GPIO_PUPDR1_PU ((uint32_t)(1<<2))
|
||||
#define GPIO_PUPDR1_PD ((uint32_t)(1<<3))
|
||||
#define GPIO_PUPDR2_PU ((uint32_t)(1<<4))
|
||||
#define GPIO_PUPDR2_PD ((uint32_t)(1<<5))
|
||||
#define GPIO_PUPDR3_PU ((uint32_t)(1<<6))
|
||||
#define GPIO_PUPDR3_PD ((uint32_t)(1<<7))
|
||||
#define GPIO_PUPDR4_PU ((uint32_t)(1<<8))
|
||||
#define GPIO_PUPDR4_PD ((uint32_t)(1<<9))
|
||||
#define GPIO_PUPDR5_PU ((uint32_t)(1<<10))
|
||||
#define GPIO_PUPDR5_PD ((uint32_t)(1<<11))
|
||||
#define GPIO_PUPDR6_PU ((uint32_t)(1<<12))
|
||||
#define GPIO_PUPDR6_PD ((uint32_t)(1<<13))
|
||||
#define GPIO_PUPDR7_PU ((uint32_t)(1<<14))
|
||||
#define GPIO_PUPDR7_PD ((uint32_t)(1<<15))
|
||||
#define GPIO_PUPDR8_PU ((uint32_t)(1<<16))
|
||||
#define GPIO_PUPDR8_PD ((uint32_t)(1<<17))
|
||||
#define GPIO_PUPDR9_PU ((uint32_t)(1<<18))
|
||||
#define GPIO_PUPDR9_PD ((uint32_t)(1<<19))
|
||||
#define GPIO_PUPDR10_PU ((uint32_t)(1<<20))
|
||||
#define GPIO_PUPDR10_PD ((uint32_t)(1<<21))
|
||||
#define GPIO_PUPDR11_PU ((uint32_t)(1<<22))
|
||||
#define GPIO_PUPDR11_PD ((uint32_t)(1<<23))
|
||||
#define GPIO_PUPDR12_PU ((uint32_t)(1<<24))
|
||||
#define GPIO_PUPDR12_PD ((uint32_t)(1<<25))
|
||||
#define GPIO_PUPDR13_PU ((uint32_t)(1<<26))
|
||||
#define GPIO_PUPDR13_PD ((uint32_t)(1<<27))
|
||||
#define GPIO_PUPDR14_PU ((uint32_t)(1<<28))
|
||||
#define GPIO_PUPDR14_PD ((uint32_t)(1<<29))
|
||||
#define GPIO_PUPDR15_PU ((uint32_t)(1<<30))
|
||||
#define GPIO_PUPDR15_PD ((uint32_t)(1<<31))
|
||||
// OSPEEDR
|
||||
// for n in $(seq 0 15); do echo "#define GPIO_OSPEEDR${n}_MED ((uint32_t)(1<<$((n*2))))";
|
||||
// echo "#define GPIO_OSPEEDR${n}_HIGH ((uint32_t)(3<<$((2*n))))"; done
|
||||
#define GPIO_OSPEEDR0_MED ((uint32_t)(1<<0))
|
||||
#define GPIO_OSPEEDR0_HIGH ((uint32_t)(3<<0))
|
||||
#define GPIO_OSPEEDR1_MED ((uint32_t)(1<<2))
|
||||
#define GPIO_OSPEEDR1_HIGH ((uint32_t)(3<<2))
|
||||
#define GPIO_OSPEEDR2_MED ((uint32_t)(1<<4))
|
||||
#define GPIO_OSPEEDR2_HIGH ((uint32_t)(3<<4))
|
||||
#define GPIO_OSPEEDR3_MED ((uint32_t)(1<<6))
|
||||
#define GPIO_OSPEEDR3_HIGH ((uint32_t)(3<<6))
|
||||
#define GPIO_OSPEEDR4_MED ((uint32_t)(1<<8))
|
||||
#define GPIO_OSPEEDR4_HIGH ((uint32_t)(3<<8))
|
||||
#define GPIO_OSPEEDR5_MED ((uint32_t)(1<<10))
|
||||
#define GPIO_OSPEEDR5_HIGH ((uint32_t)(3<<10))
|
||||
#define GPIO_OSPEEDR6_MED ((uint32_t)(1<<12))
|
||||
#define GPIO_OSPEEDR6_HIGH ((uint32_t)(3<<12))
|
||||
#define GPIO_OSPEEDR7_MED ((uint32_t)(1<<14))
|
||||
#define GPIO_OSPEEDR7_HIGH ((uint32_t)(3<<14))
|
||||
#define GPIO_OSPEEDR8_MED ((uint32_t)(1<<16))
|
||||
#define GPIO_OSPEEDR8_HIGH ((uint32_t)(3<<16))
|
||||
#define GPIO_OSPEEDR9_MED ((uint32_t)(1<<18))
|
||||
#define GPIO_OSPEEDR9_HIGH ((uint32_t)(3<<18))
|
||||
#define GPIO_OSPEEDR10_MED ((uint32_t)(1<<20))
|
||||
#define GPIO_OSPEEDR10_HIGH ((uint32_t)(3<<20))
|
||||
#define GPIO_OSPEEDR11_MED ((uint32_t)(1<<22))
|
||||
#define GPIO_OSPEEDR11_HIGH ((uint32_t)(3<<22))
|
||||
#define GPIO_OSPEEDR12_MED ((uint32_t)(1<<24))
|
||||
#define GPIO_OSPEEDR12_HIGH ((uint32_t)(3<<24))
|
||||
#define GPIO_OSPEEDR13_MED ((uint32_t)(1<<26))
|
||||
#define GPIO_OSPEEDR13_HIGH ((uint32_t)(3<<26))
|
||||
#define GPIO_OSPEEDR14_MED ((uint32_t)(1<<28))
|
||||
#define GPIO_OSPEEDR14_HIGH ((uint32_t)(3<<28))
|
||||
#define GPIO_OSPEEDR15_MED ((uint32_t)(1<<30))
|
||||
#define GPIO_OSPEEDR15_HIGH ((uint32_t)(3<<30))
|
||||
|
||||
|
||||
|
||||
/****************** FLASH Keys **********************************************/
|
||||
#define RDP_Key ((uint16_t)0x00A5)
|
||||
#define FLASH_KEY1 ((uint32_t)0x45670123)
|
||||
#define FLASH_KEY2 ((uint32_t)0xCDEF89AB)
|
||||
#define FLASH_SIZE_REG ((uint32_t)0x1FFFF7CC)
|
||||
|
||||
/************************* ADC *************************/
|
||||
/* inner termometer calibration values
|
||||
* Temp = (V30 - Vsense)/Avg_Slope + 30
|
||||
* Avg_Slope = (V30 - V110) / (110 - 30)
|
||||
*/
|
||||
#define TEMP110_CAL_ADDR ((uint16_t*) ((uint32_t) 0x1FFFF7C2))
|
||||
#define TEMP30_CAL_ADDR ((uint16_t*) ((uint32_t) 0x1FFFF7B8))
|
||||
// VDDA_Actual = 3.3V * VREFINT_CAL / average vref value
|
||||
#define VREFINT_CAL_ADDR ((uint16_t*) ((uint32_t) 0x1FFFF7BA))
|
||||
#define VDD_CALIB ((uint16_t) (330))
|
||||
#define VDD_APPLI ((uint16_t) (300))
|
||||
|
||||
/************************* USART *************************/
|
||||
|
||||
#define USART_CR2_ADD_SHIFT 24
|
||||
// set address/character match value
|
||||
#define USART_CR2_ADD_VAL(x) ((x) << USART_CR2_ADD_SHIFT)
|
||||
|
||||
/************************* IWDG *************************/
|
||||
#define IWDG_REFRESH (uint32_t)(0x0000AAAA)
|
||||
#define IWDG_WRITE_ACCESS (uint32_t)(0x00005555)
|
||||
#define IWDG_START (uint32_t)(0x0000CCCC)
|
||||
|
||||
|
||||
//#define do{}while(0)
|
||||
|
||||
7438
G0:G070,G0B1/inc/Fx/stm32g030xx.h
Normal file
7438
G0:G070,G0B1/inc/Fx/stm32g030xx.h
Normal file
File diff suppressed because it is too large
Load Diff
7979
G0:G070,G0B1/inc/Fx/stm32g031xx.h
Normal file
7979
G0:G070,G0B1/inc/Fx/stm32g031xx.h
Normal file
File diff suppressed because it is too large
Load Diff
8287
G0:G070,G0B1/inc/Fx/stm32g041xx.h
Normal file
8287
G0:G070,G0B1/inc/Fx/stm32g041xx.h
Normal file
File diff suppressed because it is too large
Load Diff
7562
G0:G070,G0B1/inc/Fx/stm32g050xx.h
Normal file
7562
G0:G070,G0B1/inc/Fx/stm32g050xx.h
Normal file
File diff suppressed because it is too large
Load Diff
8514
G0:G070,G0B1/inc/Fx/stm32g051xx.h
Normal file
8514
G0:G070,G0B1/inc/Fx/stm32g051xx.h
Normal file
File diff suppressed because it is too large
Load Diff
8822
G0:G070,G0B1/inc/Fx/stm32g061xx.h
Normal file
8822
G0:G070,G0B1/inc/Fx/stm32g061xx.h
Normal file
File diff suppressed because it is too large
Load Diff
7724
G0:G070,G0B1/inc/Fx/stm32g070xx.h
Normal file
7724
G0:G070,G0B1/inc/Fx/stm32g070xx.h
Normal file
File diff suppressed because it is too large
Load Diff
9248
G0:G070,G0B1/inc/Fx/stm32g071xx.h
Normal file
9248
G0:G070,G0B1/inc/Fx/stm32g071xx.h
Normal file
File diff suppressed because it is too large
Load Diff
9556
G0:G070,G0B1/inc/Fx/stm32g081xx.h
Normal file
9556
G0:G070,G0B1/inc/Fx/stm32g081xx.h
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user