From 1c779d395d0d3ecfe95d1a11ea4096d43ef87c29 Mon Sep 17 00:00:00 2001 From: Thomas Young Date: Tue, 28 May 2024 18:08:09 +0800 Subject: [PATCH] [SM7CUSTV1] add SM7 CUSTV1 support * add SM7CUSTV1 * fix poweroff function * [SM7CUSTV1] add SM7 CUSTV1 support Signed-off-by: siyuan.yang --------- Signed-off-by: siyuan.yang Co-authored-by: siyuan.yang --- SM7CUSTV1/Makefile | 132 +++++ SM7CUSTV1/README.md | 1 + SM7CUSTV1/board_power.c | 115 +++++ SM7CUSTV1/board_power.h | 8 + SM7CUSTV1/board_power_impl.c | 82 +++ SM7CUSTV1/board_power_porting.c | 95 ++++ SM7CUSTV1/checksum.c | 24 + SM7CUSTV1/checksum.h | 6 + SM7CUSTV1/chip.c | 94 ++++ SM7CUSTV1/chip.h | 18 + SM7CUSTV1/common.c | 151 ++++++ SM7CUSTV1/common.h | 86 ++++ SM7CUSTV1/console.c | 234 +++++++++ SM7CUSTV1/console.h | 8 + SM7CUSTV1/debug.h | 17 + SM7CUSTV1/ecdc.c | 878 ++++++++++++++++++++++++++++++++ SM7CUSTV1/ecdc.h | 275 ++++++++++ SM7CUSTV1/i2c-slaves/eeprom.c | 157 ++++++ SM7CUSTV1/i2c-slaves/eeprom.h | 28 + SM7CUSTV1/i2c-slaves/keyboard.c | 59 +++ SM7CUSTV1/i2c-slaves/keyboard.h | 7 + SM7CUSTV1/i2c-slaves/mcu.c | 436 ++++++++++++++++ SM7CUSTV1/i2c-slaves/mcu.h | 25 + SM7CUSTV1/i2c-slaves/pic.c | 112 ++++ SM7CUSTV1/i2c-slaves/pic.h | 30 ++ SM7CUSTV1/i2c-slaves/slt.c | 93 ++++ SM7CUSTV1/i2c-slaves/slt.h | 7 + SM7CUSTV1/i2c-slaves/tca6416a.c | 166 ++++++ SM7CUSTV1/i2c-slaves/tca6416a.h | 26 + SM7CUSTV1/i2c-slaves/tmp451.c | 287 +++++++++++ SM7CUSTV1/i2c-slaves/tmp451.h | 7 + SM7CUSTV1/i2c-slaves/wdt.c | 165 ++++++ SM7CUSTV1/i2c-slaves/wdt.h | 17 + SM7CUSTV1/i2c_master.c | 150 ++++++ SM7CUSTV1/i2c_master.h | 26 + SM7CUSTV1/i2c_slave.c | 320 ++++++++++++ SM7CUSTV1/i2c_slave.h | 43 ++ SM7CUSTV1/info.h | 19 + SM7CUSTV1/loop.c | 23 + SM7CUSTV1/loop.h | 10 + SM7CUSTV1/main.c | 136 +++++ SM7CUSTV1/mon.c | 212 ++++++++ SM7CUSTV1/mon.h | 12 + SM7CUSTV1/mon_print.c | 35 ++ SM7CUSTV1/mon_print.h | 8 + SM7CUSTV1/mp5475.c | 93 ++++ SM7CUSTV1/mp5475.h | 13 + SM7CUSTV1/pcie.c | 89 ++++ SM7CUSTV1/pcie.h | 8 + SM7CUSTV1/pin.c | 140 +++++ SM7CUSTV1/pin.h | 150 ++++++ SM7CUSTV1/power.c | 224 ++++++++ SM7CUSTV1/power.h | 39 ++ SM7CUSTV1/project.h | 21 + SM7CUSTV1/rst_key.c | 46 ++ SM7CUSTV1/rst_key.h | 9 + SM7CUSTV1/sm7.c | 174 +++++++ SM7CUSTV1/sm7.h | 11 + SM7CUSTV1/system.c | 201 ++++++++ SM7CUSTV1/system.h | 20 + SM7CUSTV1/target.ldi | 11 + SM7CUSTV1/tick.c | 75 +++ SM7CUSTV1/tick.h | 10 + SM7CUSTV1/timer.c | 109 ++++ SM7CUSTV1/timer.h | 13 + SM7CUSTV1/upgrade.c | 175 +++++++ SM7CUSTV1/upgrade.h | 29 ++ build/sm7custv1-layout.xml | 27 + build/sm7custv1.mak | 30 ++ tools/pack/common.c | 1 + tools/pack/project.h | 1 + tools/util/project.h | 1 + tools/util/stm32l0_util.c | 1 + upgrader/main.c | 1 + upgrader/project.h | 1 + upgrader/upgrader.c | 1 + 76 files changed, 6564 insertions(+) create mode 100644 SM7CUSTV1/Makefile create mode 100644 SM7CUSTV1/README.md create mode 100644 SM7CUSTV1/board_power.c create mode 100644 SM7CUSTV1/board_power.h create mode 100644 SM7CUSTV1/board_power_impl.c create mode 100644 SM7CUSTV1/board_power_porting.c create mode 100644 SM7CUSTV1/checksum.c create mode 100644 SM7CUSTV1/checksum.h create mode 100644 SM7CUSTV1/chip.c create mode 100644 SM7CUSTV1/chip.h create mode 100644 SM7CUSTV1/common.c create mode 100644 SM7CUSTV1/common.h create mode 100644 SM7CUSTV1/console.c create mode 100644 SM7CUSTV1/console.h create mode 100644 SM7CUSTV1/debug.h create mode 100644 SM7CUSTV1/ecdc.c create mode 100644 SM7CUSTV1/ecdc.h create mode 100644 SM7CUSTV1/i2c-slaves/eeprom.c create mode 100644 SM7CUSTV1/i2c-slaves/eeprom.h create mode 100644 SM7CUSTV1/i2c-slaves/keyboard.c create mode 100644 SM7CUSTV1/i2c-slaves/keyboard.h create mode 100644 SM7CUSTV1/i2c-slaves/mcu.c create mode 100644 SM7CUSTV1/i2c-slaves/mcu.h create mode 100644 SM7CUSTV1/i2c-slaves/pic.c create mode 100644 SM7CUSTV1/i2c-slaves/pic.h create mode 100644 SM7CUSTV1/i2c-slaves/slt.c create mode 100644 SM7CUSTV1/i2c-slaves/slt.h create mode 100644 SM7CUSTV1/i2c-slaves/tca6416a.c create mode 100644 SM7CUSTV1/i2c-slaves/tca6416a.h create mode 100644 SM7CUSTV1/i2c-slaves/tmp451.c create mode 100644 SM7CUSTV1/i2c-slaves/tmp451.h create mode 100644 SM7CUSTV1/i2c-slaves/wdt.c create mode 100644 SM7CUSTV1/i2c-slaves/wdt.h create mode 100644 SM7CUSTV1/i2c_master.c create mode 100644 SM7CUSTV1/i2c_master.h create mode 100644 SM7CUSTV1/i2c_slave.c create mode 100644 SM7CUSTV1/i2c_slave.h create mode 100644 SM7CUSTV1/info.h create mode 100644 SM7CUSTV1/loop.c create mode 100644 SM7CUSTV1/loop.h create mode 100644 SM7CUSTV1/main.c create mode 100644 SM7CUSTV1/mon.c create mode 100644 SM7CUSTV1/mon.h create mode 100644 SM7CUSTV1/mon_print.c create mode 100644 SM7CUSTV1/mon_print.h create mode 100644 SM7CUSTV1/mp5475.c create mode 100644 SM7CUSTV1/mp5475.h create mode 100644 SM7CUSTV1/pcie.c create mode 100644 SM7CUSTV1/pcie.h create mode 100644 SM7CUSTV1/pin.c create mode 100644 SM7CUSTV1/pin.h create mode 100644 SM7CUSTV1/power.c create mode 100644 SM7CUSTV1/power.h create mode 100644 SM7CUSTV1/project.h create mode 100644 SM7CUSTV1/rst_key.c create mode 100644 SM7CUSTV1/rst_key.h create mode 100644 SM7CUSTV1/sm7.c create mode 100644 SM7CUSTV1/sm7.h create mode 100644 SM7CUSTV1/system.c create mode 100644 SM7CUSTV1/system.h create mode 100644 SM7CUSTV1/target.ldi create mode 100644 SM7CUSTV1/tick.c create mode 100644 SM7CUSTV1/tick.h create mode 100644 SM7CUSTV1/timer.c create mode 100644 SM7CUSTV1/timer.h create mode 100644 SM7CUSTV1/upgrade.c create mode 100644 SM7CUSTV1/upgrade.h create mode 100644 build/sm7custv1-layout.xml create mode 100644 build/sm7custv1.mak diff --git a/SM7CUSTV1/Makefile b/SM7CUSTV1/Makefile new file mode 100644 index 00000000..10ac47f6 --- /dev/null +++ b/SM7CUSTV1/Makefile @@ -0,0 +1,132 @@ +TARGET = SM7CUSTV1 +DEBUG = 1 +STANDALONE = 0 +CLOSEPMIC = 0 + +ifeq ($(strip $(V)), 1) + Q = + E = +else + Q = @ + E = 1>/dev/null 2>&1 +endif + +OPENCM3_DIR = ../libopencm3 + +OUTDIR = build +SRCDIR = . i2c-slaves +INCDIR = . $(OPENCM3_DIR)/include i2c-slaves + +C_SRCS = $(foreach dir, $(SRCDIR), $(wildcard $(dir)/*.c)) +S_SRCS = $(foreach dir, $(SRCDIR), $(wildcard $(dir)/*.s)) +S_SRCS += $(foreach dir, $(SRCDIR), $(wildcard $(dir)/*.S)) + +SRCS = $(C_SRCS) $(S_SRCS) +OBJS = $(addprefix $(OUTDIR)/, $(notdir $(addsuffix .o, $(basename $(SRCS))))) +VPATH = $(sort $(dir $(SRCS))) + +OBJS := $(sort $(OBJS)) +DEPS := $(patsubst %.o, %.d, $(OBJS)) + +LDSCRIPT_APP = $(TARGET)_APP.ld +LDSCRIPT_LOADER = $(TARGET)_LOADER.ld + +OPT_CFLAGS = -g -O2 +ARCH_CFLAGS = -mthumb -mcpu=cortex-m0plus +SPEC_CFLAGS = -specs=nano.specs + +CPPFLAGS = $(foreach dir, $(INCDIR), -I$(dir)) +CFLAGS = $(CPPFLAGS) $(OPT_CFLAGS) $(ARCH_CFLAGS) $(SPEC_CFLAGS) \ + -std=gnu11 -ffunction-sections -fdata-sections -Wall -Werror \ + -DSTM32L0 + +ifeq ($(strip $(DEBUG)), 1) +CFLAGS += -DDEBUG +endif + +ifeq ($(strip $(STANDALONE)), 1) +CFLAGS += -DSTANDALONE +endif + +ifeq ($(strip $(CLOSEPMIC)), 1) +CFLAGS += -DCLOSEPMIC +endif + +ASFLAGS = $(CFLAGS) -x assembler-with-cpp -Wa,--no-warn + +LDFLAGS = $(SPEC_CFLAGS) $(ARCH_CFLAGS) $(OPT_CFLAGS) -static -specs=nosys.specs\ + -nostartfiles -Wl,--cref -Wl,--gc-sections \ + -L$(OPENCM3_DIR)/lib -lopencm3_stm32l0 + +CROSS_COMPILE = arm-none-eabi- +CC = $(CROSS_COMPILE)gcc +AS = $(CROSS_COMPILE)gcc +LD = $(CROSS_COMPILE)gcc +OBJCOPY = $(CROSS_COMPILE)objcopy +OBJDUMP = $(CROSS_COMPILE)objdump +READELF = $(CROSS_COMPILE)readelf + +all:$(OUTDIR) \ + $(OUTDIR)/$(TARGET)_APP.elf \ + $(OUTDIR)/$(TARGET)_APP.bin \ + $(OUTDIR)/$(TARGET)_APP.dis \ + $(OUTDIR)/$(TARGET)_LOADER.elf \ + $(OUTDIR)/$(TARGET)_LOADER.bin \ + $(OUTDIR)/$(TARGET)_LOADER.dis + +$(OUTDIR)/%.bin: $(OUTDIR)/%.elf + @echo '[CP] $@' + $(Q)$(OBJCOPY) -O binary $< $@ + +$(OUTDIR)/%.dis: $(OUTDIR)/%.elf + @echo '[DP] $@' + $(Q)$(READELF) -e $< > $@ + $(Q)$(OBJDUMP) -D $< >> $@ + +$(OUTDIR)/%.elf: $(OUTDIR)/%.ld $(OBJS) + @echo '[LD] $@' + $(Q)$(LD) $(OBJS) $(LDFLAGS) -Wl,-Map,$@.map \ + -T $< -o $@ + +$(OUTDIR)/$(LDSCRIPT_APP): target.ldi + @echo '[XP] $@' + $(Q)$(CC) $(CPPFLAGS) \ + -D'ROM_START=0x08008000' -D'ROM_SIZE=32K' \ + -D'RAM_START=0x20000000' -D'RAM_SIZE=8K' \ + -E -xc -P -C $< > $@ + +$(OUTDIR)/$(LDSCRIPT_LOADER): target.ldi + @echo '[XP] $@' + $(Q)$(CC) $(CPPFLAGS) \ + -D'ROM_START=0x08000000' -D'ROM_SIZE=32K' \ + -D'RAM_START=0x20000000' -D'RAM_SIZE=8K' \ + -E -xc -P -C $< > $@ + +$(OUTDIR)/%.o: %.c | $(OUTDIR) + @echo '[CC] $@' + $(Q)$(CC) $(CFLAGS) -c $< -o $@ + +$(OUTDIR)/%.d: %.c | $(OUTDIR) + @echo '[CD] $@' + $(Q)$(CC) $(CFLAGS) -MM -MF $@ $< + +$(OUTDIR): + @mkdir -p $@ + +burn: $(OUTDIR)/$(TARGET)_LOADER.bin + st-flash write $< 0x08000000 + +clean: + rm -rf $(OUTDIR) + +code: gencode.py config.xlsx + @echo '[GEN]' + $(Q)./gencode.py config.xlsx -s pin.c -e pin.h -y pin + $(Q)./gencode.py config.xlsx -s board_power.c -e board_power.h -p board_power_porting.c -y power + +cclean: + rm -rf pin.c pin.h board_power.c board_power.h + +.PHONY: clean burn + +include $(wildcard $(DEPS)) diff --git a/SM7CUSTV1/README.md b/SM7CUSTV1/README.md new file mode 100644 index 00000000..1f8f29fe --- /dev/null +++ b/SM7CUSTV1/README.md @@ -0,0 +1 @@ +This MCU firmware is for the SE7 passive cooling device. diff --git a/SM7CUSTV1/board_power.c b/SM7CUSTV1/board_power.c new file mode 100644 index 00000000..ba8038e0 --- /dev/null +++ b/SM7CUSTV1/board_power.c @@ -0,0 +1,115 @@ +/* AUTO GENERATED CODE */ + +#include +#include +#include +#include + +int powerchip_init_on(void); +void powerchip_init_off(void); + +int pmic_channel_a_on(void); +void pmic_channel_a_off(void); + +int pmic_channel_d_on(void); +void pmic_channel_d_off(void); + +int pmic_channel_b_on(void); +void pmic_channel_b_off(void); + +int pmic_channel_c_on(void); +void pmic_channel_c_off(void); + +int check_pcie_reset_on(void); +void check_pcie_reset_off(void); + +int sys_rst_deassert_on(void); +void sys_rst_deassert_off(void); + +int sys_rst_assert_on(void); +void sys_rst_assert_off(void); + +struct power_node board_power_nodes[19] = { + + {"EN_12V_SYS", NODE_TYPE_ENABLE, POWER_STATUS_OFF, 1000, + {(unsigned long)EN_12V_SYS_PORT, (unsigned long)EN_12V_SYS_PIN}, + }, + + {"POWERCHIP_INIT", NODE_TYPE_FUNCTION, POWER_STATUS_OFF, 0, + {(unsigned long)powerchip_init_on, (unsigned long)powerchip_init_off}, + }, + + {"PMIC-VDD-1.8V", NODE_TYPE_FUNCTION, POWER_STATUS_OFF, 1000, + {(unsigned long)pmic_channel_a_on, (unsigned long)pmic_channel_a_off}, + }, + + {"VDD-1.8V", NODE_TYPE_ENABLE, POWER_STATUS_OFF, 1000, + {(unsigned long)EN_VDDIO18_PORT, (unsigned long)EN_VDDIO18_PIN}, + }, + + {"VDD-CORE", NODE_TYPE_ENABLE, POWER_STATUS_OFF, 3000, + {(unsigned long)EN_VDDC_PORT, (unsigned long)EN_VDDC_PIN}, + }, + + {"VDD-3.3V", NODE_TYPE_ENABLE, POWER_STATUS_OFF, 1000, + {(unsigned long)EN_VDDIO33_PORT, (unsigned long)EN_VDDIO33_PIN}, + }, + + {"VDD-0.8V", NODE_TYPE_FUNCTION, POWER_STATUS_OFF, 1000, + {(unsigned long)pmic_channel_d_on, (unsigned long)pmic_channel_d_off}, + }, + + {"ACK-P08", NODE_TYPE_ENABLE, POWER_STATUS_OFF, 1000, + {(unsigned long)P08_PWR_GOOD_PORT, (unsigned long)P08_PWR_GOOD_PIN}, + }, + + {"VDD-PCIE", NODE_TYPE_ENABLE, POWER_STATUS_OFF, 1000, + {(unsigned long)EN_VDD_PCIE_VP_PORT, + (unsigned long)EN_VDD_PCIE_VP_PIN}, + }, + + {"ACK-PCIE", NODE_TYPE_ENABLE, POWER_STATUS_OFF, 1000, + {(unsigned long)GPIO2_PORT, (unsigned long)GPIO2_PIN}, + }, + + {"VDD-TPU", NODE_TYPE_ENABLE, POWER_STATUS_OFF, 1000, + {(unsigned long)EN_VDD_TPU_PORT, (unsigned long)EN_VDD_TPU_PIN}, + }, + + {"ACK-TPU", NODE_TYPE_ENABLE, POWER_STATUS_OFF, 1000, + {(unsigned long)GPIO3_PORT, (unsigned long)GPIO3_PIN}, + }, + + {"DDR-VDDQ", NODE_TYPE_FUNCTION, POWER_STATUS_OFF, 1000, + {(unsigned long)pmic_channel_b_on, (unsigned long)pmic_channel_b_off}, + }, + + {"DDR-VDDQLP", NODE_TYPE_FUNCTION, POWER_STATUS_OFF, 1000, + {(unsigned long)pmic_channel_c_on, (unsigned long)pmic_channel_c_off}, + }, + + {"VQPS-1.8V", NODE_TYPE_ENABLE, POWER_STATUS_OFF, 3000, + {(unsigned long)EN_VQPS18_PORT, (unsigned long)EN_VQPS18_PIN}, + }, + + {"CHECK-PCIE-RESET", NODE_TYPE_FUNCTION, POWER_STATUS_OFF, 0, + {(unsigned long)check_pcie_reset_on, + (unsigned long)check_pcie_reset_off}, + }, + + {"SYS-RST-DEASSERT", NODE_TYPE_FUNCTION, POWER_STATUS_OFF, 1000, + {(unsigned long)sys_rst_deassert_on, + (unsigned long)sys_rst_deassert_off}, + }, + + {"ACK-DDR", NODE_TYPE_ENABLE, POWER_STATUS_OFF, 29000, + {(unsigned long)DDR_PG_MCU_PORT, (unsigned long)DDR_PG_MCU_PIN}, + }, + + {"SYS-RST-ASSERT", NODE_TYPE_FUNCTION, POWER_STATUS_OFF, 30000, + {(unsigned long)sys_rst_assert_on, (unsigned long)sys_rst_assert_off}, + }, + +}; + +/* AUTO GENERATED CODE END */ diff --git a/SM7CUSTV1/board_power.h b/SM7CUSTV1/board_power.h new file mode 100644 index 00000000..7ec70e11 --- /dev/null +++ b/SM7CUSTV1/board_power.h @@ -0,0 +1,8 @@ +#ifndef __BOARD_POWER_H__ +#define __BOARD_POWER_H__ + +extern struct power_node board_power_nodes[19]; + +#endif + +/* AUTO GENERATED CODE END */ diff --git a/SM7CUSTV1/board_power_impl.c b/SM7CUSTV1/board_power_impl.c new file mode 100644 index 00000000..bfa44314 --- /dev/null +++ b/SM7CUSTV1/board_power_impl.c @@ -0,0 +1,82 @@ +#include +#include +#include +#include +int pmic_channel_a_on(void) +{ + return mp5475_buck_on(0); +} + +void pmic_channel_a_off(void) +{ + mp5475_buck_off(0); +} + +int pmic_channel_d_on(void) +{ + return mp5475_buck_on(3); +} + +void pmic_channel_d_off(void) +{ + mp5475_buck_off(3); +} + +int pmic_channel_b_on(void) +{ + return mp5475_buck_on(1); +} + +void pmic_channel_b_off(void) +{ + mp5475_buck_off(1); +} + +int pmic_channel_c_on(void) +{ + return mp5475_buck_on(2); +} + +void pmic_channel_c_off(void) +{ + mp5475_buck_off(2); +} + +int sys_rst_deassert_on(void) +{ + chip_enable(); + return 0; +} + +void sys_rst_deassert_off(void) +{ +} + +int sys_rst_assert_on(void) +{ + chip_disable(); + return 0; +} + +void sys_rst_assert_off(void) +{ + /* reset chip firstly when power off */ + chip_disable(); +} + +int check_pcie_reset_on(void) +{ + board_init(); + return 0; +} + +void check_pcie_reset_off(void) +{ +} + +int powerchip_init_on(void) +{ + mp5475_init(); + + return 0; +} diff --git a/SM7CUSTV1/board_power_porting.c b/SM7CUSTV1/board_power_porting.c new file mode 100644 index 00000000..7b518c21 --- /dev/null +++ b/SM7CUSTV1/board_power_porting.c @@ -0,0 +1,95 @@ +/* AUTO GENERATED CODE */ + +#ifndef __weak +#define __weak __attribute__((weak)) +#endif + +int __weak powerchip_init_on(void) +{ + /* add customer code here */ + return 0; +} + +void __weak powerchip_init_off(void) +{ + /* add customer code here */ +} + +int __weak pmic_channel_a_on(void) +{ + /* add customer code here */ + return 0; +} + +void __weak pmic_channel_a_off(void) +{ + /* add customer code here */ +} + +int __weak pmic_channel_d_on(void) +{ + /* add customer code here */ + return 0; +} + +void __weak pmic_channel_d_off(void) +{ + /* add customer code here */ +} + +int __weak pmic_channel_b_on(void) +{ + /* add customer code here */ + return 0; +} + +void __weak pmic_channel_b_off(void) +{ + /* add customer code here */ +} + +int __weak pmic_channel_c_on(void) +{ + /* add customer code here */ + return 0; +} + +void __weak pmic_channel_c_off(void) +{ + /* add customer code here */ +} + +int __weak check_pcie_reset_on(void) +{ + /* add customer code here */ + return 0; +} + +void __weak check_pcie_reset_off(void) +{ + /* add customer code here */ +} + +int __weak sys_rst_deassert_on(void) +{ + /* add customer code here */ + return 0; +} + +void __weak sys_rst_deassert_off(void) +{ + /* add customer code here */ +} + +int __weak sys_rst_assert_on(void) +{ + /* add customer code here */ + return 0; +} + +void __weak sys_rst_assert_off(void) +{ + /* add customer code here */ +} + +/* AUTO GENERATED CODE END */ diff --git a/SM7CUSTV1/checksum.c b/SM7CUSTV1/checksum.c new file mode 100644 index 00000000..5817df9d --- /dev/null +++ b/SM7CUSTV1/checksum.c @@ -0,0 +1,24 @@ +#include +#include + +void checksum(void *out, void *in, unsigned long len) +{ + uint32_t *src = in; + char *init = "*BITMAIN-SOPHON*"; + uint32_t result[4]; + unsigned long block = len >> 4; + unsigned long left = len & 0xf; + unsigned long i, j; + + memcpy(result, init, sizeof(result)); + + + for (i = 0; i < block; ++i, src += 4) + for (j = 0; j < 4; ++j) + result[j] ^= src[j]; + + for (i = 0; i < left; ++i) + ((uint8_t *)result)[i] ^= ((uint8_t *)src)[i]; + + memcpy(out, result, sizeof(result)); +} diff --git a/SM7CUSTV1/checksum.h b/SM7CUSTV1/checksum.h new file mode 100644 index 00000000..bf527662 --- /dev/null +++ b/SM7CUSTV1/checksum.h @@ -0,0 +1,6 @@ +#ifndef __CHECKSUM_H__ +#define __CHECKSUM_H__ + +void checksum(void *out, void *in, unsigned long len); + +#endif diff --git a/SM7CUSTV1/chip.c b/SM7CUSTV1/chip.c new file mode 100644 index 00000000..d778aa9f --- /dev/null +++ b/SM7CUSTV1/chip.c @@ -0,0 +1,94 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static uint32_t uptime; +static uint32_t reset_times; +static int chip_enabled; +static int needpoweron; + +uint32_t chip_reset_times(void) +{ + return reset_times; +} + +uint32_t chip_uptime(void) +{ + return uptime; +} + +void chip_disable(void) +{ + gpio_clear(SYS_RST_PORT, SYS_RST_PIN); + chip_enabled = false; + uptime = 0; +} + +void chip_enable(void) +{ + gpio_set(SYS_RST_PORT, SYS_RST_PIN); + chip_enabled = true; +} + +void chip_reset(void) +{ + chip_disable(); + mdelay(30); + uptime = 0; + ++reset_times; + chip_enable(); +} + +void chip_popd_reset_early(void) +{ + power_off(); + chip_disable(); + mdelay(50); +} + +void chip_popd_reset_end(void) +{ + power_on(); + uptime = 0; + ++reset_times; + chip_enable(); +} + +static void chip_process(void) +{ + if (chip_enabled) + ++uptime; +} + +void chip_init(void) +{ + tick_register_task(chip_process, 1000); +} + +int chip_is_enabled(void) +{ + return chip_enabled; +} + +void set_needpoweron(void) +{ + needpoweron = 1; +} + +void clr_needpoweron(void) +{ + needpoweron = 0; +} + +int get_needpoweron_satus(void) +{ + return needpoweron; +} diff --git a/SM7CUSTV1/chip.h b/SM7CUSTV1/chip.h new file mode 100644 index 00000000..094bf0b1 --- /dev/null +++ b/SM7CUSTV1/chip.h @@ -0,0 +1,18 @@ +#ifndef __CHIP_H__ +#define __CHIP_H__ + +#include + +void chip_init(void); +void chip_enable(void); +void chip_disable(void); +void chip_reset(void); +void chip_popd_reset_early(void); +void chip_popd_reset_end(void); +uint32_t chip_uptime(void); +uint32_t chip_reset_times(void); +int chip_is_enabled(void); +void set_needpoweron(void); +int get_needpoweron_satus(void); +void clr_needpoweron(void); +#endif diff --git a/SM7CUSTV1/common.c b/SM7CUSTV1/common.c new file mode 100644 index 00000000..754282ff --- /dev/null +++ b/SM7CUSTV1/common.c @@ -0,0 +1,151 @@ +#include +#include +#include +#include +#include +#include +#include + +#define MCU_SW_VER 0 +#define DDR_TYPE DDR_TYPE_LPDDR4X + +static uint8_t board_type; +static uint8_t work_mode; +static int board_temp, soc_temp; + +int get_board_temp(void) +{ + return board_temp; +} + +int get_soc_temp(void) +{ + return soc_temp; +} + +void set_board_temp(int temp) +{ + board_temp = temp; +} + +void set_soc_temp(int temp) +{ + soc_temp = temp; +} + +uint8_t get_ddr_type(void) +{ + return DDR_TYPE; +} + +char *get_board_type_name() +{ + switch (board_type) { + case SM7CUSTV1: + return "SM7 CUST V1"; + }; + /* U means unknown type */ + return "1684X-U"; +} + +void set_board_type(uint8_t type) +{ + board_type = type; +} + +uint8_t get_board_type(void) +{ + return board_type; +} + +uint8_t get_firmware_version(void) +{ + return MCU_SW_VER; +} + +void board_init(void) +{ + /* donot probe twice */ + if (work_mode) + return; + + work_mode = gpio_get(PCIE_RESET_PORT, PCIE_RESET_PIN) ? + WORK_MODE_SOC : WORK_MODE_PCIE; + + if (work_mode == WORK_MODE_PCIE) { + if (is_mixed_mode()) + work_mode = WORK_MODE_MIXED; + } +} + +int get_work_mode(void) +{ + return work_mode; +} + +uint8_t get_declared_board_type(void) +{ + return *(uint8_t*)EEPROM_BOARD_TYPE_ADDR; +} + +static inline void led_on(void) +{ + gpio_set(STATUS_LED0_PORT, STATUS_LED0_PIN); +} + +static inline void led_off(void) +{ + gpio_clear(STATUS_LED0_PORT, STATUS_LED0_PIN); +} + +int led_tick_handle; +int led_status; + +void led_isr(void); + +void led_init(void) +{ + /* donnot start now */ + led_tick_handle = tick_register_task(led_isr, 0); +} + +/* if freq > 500, turn on led + * if freq == 0, turn off led + */ +void led_set_frequency(unsigned long freq) +{ + if (freq > 500) { + /* turn off tick task */ + tick_set_task_interval(led_tick_handle, 0); + led_on(); + } else if (freq == 0) { + tick_set_task_interval(led_tick_handle, 0); + led_off(); + } else { + tick_set_task_interval(led_tick_handle, 1000 / freq / 2); + } +} + +void led_isr(void) +{ + led_status = !led_status; + if (led_status) + led_on(); + else + led_off(); +} +void set_led_on() +{ + gpio_set(STATUS_LED1_PORT, STATUS_LED1_PIN); +} + +void set_led_off() +{ + gpio_clear(STATUS_LED1_PORT, STATUS_LED1_PIN); +} + +int detect_test_mode(void) +{ + return (!!gpio_get(MCU_UART1_TX_PORT, MCU_UART1_TX_PIN) << 0) | + (!!gpio_get(MCU_UART1_RX_PORT, MCU_UART1_RX_PIN) << 1); +} diff --git a/SM7CUSTV1/common.h b/SM7CUSTV1/common.h new file mode 100644 index 00000000..12535ba6 --- /dev/null +++ b/SM7CUSTV1/common.h @@ -0,0 +1,86 @@ +#ifndef __COMMON_H__ +#define __COMMON_H__ + +#include + +#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0])) + +#define MCU_SLAVE_ADDR 0x17 + +#define I2C1_OA1 0x17 +#define I2C1_OA2 0x68 +#define I2C1_OA2_MASK 0x03 + +#define I2C2_OA1 0x38 +#define I2C2_OA2 0x00 +#define I2C2_OA2_MASK 0x00 + +#define PCIE_RESET_PORT PCIEE_RST_MCU_PORT +#define PCIE_RESET_PIN PCIEE_RST_MCU_PIN +#define PCIE_RESET_EXTI PCIEE_RST_MCU_EXTI +#define PCIE_RESET_NVIC NVIC_EXTI4_15_IRQ + +#define SYS_RST_PORT SYS_RST_X_PORT +#define SYS_RST_PIN SYS_RST_X_PIN + +#define EEPROM_BASE 0x08080000 +#define EEPROM_SIZE 0x00000800 + +#define EEPROM_CELL_SIZE 32 +#define EEPROM_CELL_OFFSET(n) (EEPROM_CELL_SIZE * n) +#define EEPROM_CELL_ADDR(n) (EEPROM_BASE + EEPROM_CELL_OFFSET(n)) + +#define EEPROM_MAC0_OFFSET EEPROM_CELL_OFFSET(0) +#define EEPROM_MAC1_OFFSET EEPROM_CELL_OFFSET(1) +#define EEPROM_SN_OFFSET EEPROM_CELL_OFFSET(2) +#define EEPROM_BOARD_TYPE_OFFSET EEPROM_CELL_OFFSET(3) +#define EEPROM_POWER_OFF_REASON_OFFSET EEPROM_CELL_OFFSET(5) +#define EEPROM_MIXED_MODE_OFFSET (EEPROM_CELL_OFFSET(5) + 1) + +#define EEPROM_MAC0_ADDR EEPROM_CELL_ADDR(0) +#define EEPROM_MAC1_ADDR EEPROM_CELL_ADDR(1) +#define EEPROM_SN_ADDR EEPROM_CELL_ADDR(2) +#define EEPROM_BOARD_TYPE_ADDR EEPROM_CELL_ADDR(3) +#define EEPROM_POWER_OFF_REASON_ADDR EEPROM_CELL_ADDR(5) +#define EEPROM_MIXED_MODE_ADDR (EEPROM_BASE + EEPROM_MIXED_MODE_OFFSET) + +#define BIT(n) (1 << n) + +#define LED_FREQ_ALWAYS_ON 1000 +#define LED_FREQ_ALWAYS_OFF 0 + +enum { + WORK_MODE_SOC = 1, + WORK_MODE_PCIE = 2, + WORK_MODE_MIXED = 3, +}; + +enum { + DDR_TYPE_LPDDR4X = 0, + DDR_TYPE_LPDDR4 = 1, +}; + +enum { + TEST_MODE_HALT = 1, + TEST_MODE_RUN = 2, +}; + +void set_board_type(uint8_t type); +uint8_t get_board_type(void); +uint8_t get_firmware_version(void); +int get_work_mode(void); +void board_init(void); +uint8_t get_declared_board_type(void); +uint8_t get_ddr_type(void); +char *get_board_type_name(); +void led_init(void); +void set_led_on(); +void set_led_off(); + +void led_set_frequency(unsigned long freq); +int detect_test_mode(void); +void set_soc_temp(int temp); +void set_board_temp(int temp); +int get_board_temp(void); +int get_soc_temp(void); +#endif diff --git a/SM7CUSTV1/console.c b/SM7CUSTV1/console.c new file mode 100644 index 00000000..84ce1929 --- /dev/null +++ b/SM7CUSTV1/console.c @@ -0,0 +1,234 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +static struct ecdc_console *console; + +static int console_getc(void *console_hint) +{ + int err; + + err = uart_getc(); + return err >= 0 ? err : ECDC_GETC_EOF; +} + +static void console_putc(void *console_hint, char c) +{ + uart_putc(c); +} + +static void cmd_hello(void *hint, int argc, char const *argv[]) +{ + printf("Hello BITMAIN SOPHON\n"); +} + +static const char cmd_poweron_usage[] = +"poweron\n" +" power on the bm1684x\n"; + +static void cmd_poweron(void *hint, int argc, char const *argv[]) +{ + power_on(); + chip_enable(); + + printf("BM1684XOK\n"); +} + +static const char cmd_poweroff_usage[] = +"poweroff\n" +" power off the bm1684x\n"; + +static void cmd_poweroff(void *hint, int argc, char const *argv[]) +{ + power_off(); + slt_reset(); + + printf("BM1684XOK\n"); +} + +static const char cmd_getmcutype_usage[] = +"getmcutype\n"; + +static void cmd_getmcutype(void *hint, int argc, char const *argv[]) +{ + printf("SM7CUSTV1\n"); +} + +static const char cmd_query_usage[] = +"query\n" +" query the result from bm1684x\n"; + +static void cmd_query(void *hint, int argc, char const *argv[]) +{ + printf("0x%x\n", get_slt_result()); +} + +static const char cmd_power_usage[] = +"power [on|off power_name]\n" +" on: enable power\n" +" off: disable power\n" +" if on or off ommited, get the status of power enable pin\n"; + +static void cmd_power(void *hint, int argc, char const *argv[]) +{ + int ret = 0; + + if (argc == 1){ + cmd_get_node_status(); + }else if (argc == 3){ + if (strcmp(argv[1], "on") == 0){ + ret = power_node_on(argv[2]); + printf(argv[2]); + + if (ret == -1) + printf(" enable failed\n"); + else + printf(" enable success\n"); + }else if (strcmp(argv[1], "off") == 0){ + power_node_off(argv[2]); + } + else + printf("invalid command\n"); + }else{ + printf(cmd_power_usage); + } +} + +static const char cmd_enprint_usage[] = +"enprint [second]\n" +" second: set time between two pinrt\n" +" default value is 1s\n"; + +static void cmd_enprint(void *hint, int argc, char const *argv[]) +{ + unsigned long time = 0; + + if (argc == 1){ + mon_print_fun(); + enable_mon_print_task(0); + }else if (argc == 2){ + mon_print_fun(); + time = strtol(argv[1], NULL, 10); + enable_mon_print_task(time*1000); + }else{ + printf(cmd_enprint_usage); + } +} + +struct command { + const char *name, *alias, *usage; + ecdc_callback_fn fn; +}; + +static void cmd_help(void *hint, int argc, char const *argv[]); + +static struct command command_list[] = { + {"help", NULL , NULL, cmd_help}, + {"hello", NULL , NULL, cmd_hello}, + {"poweron", NULL , cmd_poweron_usage, cmd_poweron}, + {"poweroff", NULL , cmd_poweroff_usage, cmd_poweroff}, + {"getmcutype", NULL, cmd_getmcutype_usage, cmd_getmcutype}, + {"query", NULL, cmd_query_usage, cmd_query}, + {"power", NULL, cmd_power_usage, cmd_power}, + {"enprint", NULL, cmd_enprint_usage, cmd_enprint}, +}; + +void print_usage(struct command *cmd) +{ + if (cmd->usage) + printf(cmd->usage); +} + +struct command *find_command(const char *name) +{ + int i; + struct command *cmd; + + for (i = 0; i < ARRAY_SIZE(command_list); ++i) { + cmd = &command_list[i]; + if (strcmp(cmd->name, name) == 0) + return cmd; + } + + return NULL; +} + +static void cmd_help(void *hint, int argc, char const *argv[]) +{ + int i; + struct command *cmd; + + if (argc == 1) { + for (i = 0; i < ARRAY_SIZE(command_list); ++i) + print_usage(&command_list[i]); + } else if (argc == 2) { + cmd = find_command(argv[1]); + if (cmd) + print_usage(cmd); + else + printf("\'%s\' not found\n", argv[1]); + } else { + printf("invalid usage\n"); + printf("help [command]"); + } +} + +int console_init(void) +{ + int i; + + console = ecdc_alloc_console(NULL, console_getc, console_putc, 128, 4); + if (console == NULL) { + printf("create console failed\n"); + return -1; + } + ecdc_configure_console(console, ECDC_MODE_ANSI, ECDC_SET_LOCAL_ECHO); + + for (i = 0; i < sizeof(command_list) / sizeof(command_list[0]); ++i) { + if (command_list[i].name) + ecdc_alloc_command(NULL, console, + command_list[i].name, + command_list[i].fn); + if (command_list[i].alias) + ecdc_alloc_command(NULL, console, + command_list[i].alias, + command_list[i].fn); + } + + ecdc_alloc_list_command(console, "list"); + + console_putc(NULL, '\r'); + console_putc(NULL, '\n'); + + return 0; +} + +void console_poll(void) +{ + ecdc_pump_console(console); +} + +void console_add(void) +{ + console_init(); + loop_add(console_poll); +} + +void console_test(void) +{ + while (1) + console_poll(); +} diff --git a/SM7CUSTV1/console.h b/SM7CUSTV1/console.h new file mode 100644 index 00000000..033e0cca --- /dev/null +++ b/SM7CUSTV1/console.h @@ -0,0 +1,8 @@ +#ifndef __CONSOLE_H_ +#define __CONSOLE_H_ + +int console_init(void); +void console_poll(void); +void console_test(void); +void console_add(void); +#endif diff --git a/SM7CUSTV1/debug.h b/SM7CUSTV1/debug.h new file mode 100644 index 00000000..ea4c7fa3 --- /dev/null +++ b/SM7CUSTV1/debug.h @@ -0,0 +1,17 @@ +#ifndef __DEBUG_H__ +#define __DEBUG_H__ + + +#ifdef DEBUG + +#include + +#define debug(...) printf(__VA_ARGS__) + +#else + +#define debug(...) do {} while (0) + +#endif + +#endif diff --git a/SM7CUSTV1/ecdc.c b/SM7CUSTV1/ecdc.c new file mode 100644 index 00000000..413dd2c0 --- /dev/null +++ b/SM7CUSTV1/ecdc.c @@ -0,0 +1,878 @@ +/** + * Copyright (c) 2016 Bradley Kim Schleusner < bradschl@gmail.com > + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include +#include +#include + +#include "ecdc.h" + +// ------------------------------------------------------------ Private settings + + +// Size of the control sequence buffer. There is no upper bound specified +// in a standard, but we can assume that we won't have to process any of the +// really complex ones. That is mostly the terminals problem +#define CS_BUFFER_SIZE 16 +#define DEFAULT_PROMPT "# " + +// -------------------------------------------------------------- Private types + + +typedef void (*console_state_fn)(struct ecdc_console *); + + +struct ecdc_command { + // Command linked list storage + struct ecdc_command * next; + struct ecdc_console * console; + + + // Callback + ecdc_callback_fn callback; + void * hint; + + + // Command info + char * name; +}; + + +struct ecdc_console { + // Command linked list root pointer + struct ecdc_command * root; + + + // Argument line storage + char * arg_line; + size_t arg_line_size; + size_t arg_line_write_index; + + + // Argument pointer storage + const char ** argv; + size_t max_argc; + + + // Console read / write + ecdc_getc_fn getc; + ecdc_putc_fn putc; + void * hint; + int snoop_char; + + + // State machine + console_state_fn state; + + + // Control sequence handling + char cs_buffer[CS_BUFFER_SIZE]; + size_t cs_write_index; + + + // Flags and settings + bool f_local_echo; + enum ecdc_mode mode; + + // Prompt + char * prompt; +}; + +// ---------------------------------------------------------- Private functions + + +static struct ecdc_command * +locate_command(struct ecdc_console * console, + const char * name) +{ + struct ecdc_command * ret = NULL; + + if(NULL != console) { + struct ecdc_command * node = NULL; + for(node = console->root; NULL != node; node = node->next) { + if(0 == strcmp(node->name, name)) { + ret = node; + break; + } + } + } + + return ret; +} + + +static struct ecdc_command * +get_last_command(struct ecdc_console * console) +{ + struct ecdc_command * last_command = NULL; + + if(NULL != console) { + for(last_command = console->root; + NULL != last_command; + last_command = last_command->next) { + + if(NULL == last_command->next) { + break; + } + } + } + + return last_command; +} + + +static struct ecdc_command * +get_previous_command(struct ecdc_command * command) +{ + struct ecdc_command * prev = NULL; + do { + if(NULL == command) { + break; + } + + struct ecdc_console * console = command->console; + if(NULL == console) { + break; + } + + if(console->root == command) { + break; + } + + struct ecdc_command * node = NULL; + for(node = console->root; node != NULL; node = node->next) { + if(command == node->next) { + prev = node; + break; + } + } + + } while(0); + + return prev; +} + + +static void +register_command(struct ecdc_console * console, + struct ecdc_command * command) +{ + if(NULL != console) { + command->console = console; + command->next = NULL; + + struct ecdc_command * last_command = get_last_command(console); + if(NULL == last_command) { + console->root = command; + } + else { + last_command->next = command; + } + } +} + + +static void +unregister_command(struct ecdc_command * command) +{ + do { + if(NULL == command) { + break; + } + + struct ecdc_console * console = command->console; + if(NULL == console) { + break; + } + + if(console->root == command) { + console->root = command->next; + } + else { + struct ecdc_command * prev = get_previous_command(command); + if(NULL != prev) + { + prev->next = command->next; + } + } + + command->console = NULL; + command->next = NULL; + } while(0); +} + + +static char * +find_first_non_whitesapce(char * str) +{ + char * out_ptr = NULL; + if(str == NULL) { + goto out; + } + + while(*str != '\0') { + switch(*str) { + case '\x20': + case '\x09': + case '\x0A': + case '\x0B': + case '\x0C': + case '\x0D': + ++str; + break; + default: + out_ptr = str; + goto out; + } + } + + out: + return out_ptr; +} + + +static char * +find_fist_whitespace(char * str) +{ + char * out_ptr = NULL; + if(str == NULL) { + goto out; + } + + while(*str != '\0') { + switch(*str) { + case '\x20': + case '\x09': + case '\x0A': + case '\x0B': + case '\x0C': + case '\x0D': + out_ptr = str; + goto out; + default: + ++str; + break; + } + } + + out: + return out_ptr; +} + + +// --------------------------------------------------------- Terminal functions + +// ---------------------------- Newline + +static void +term_put_ansi_newline(struct ecdc_console * console) +{ + console->putc(console->hint, '\r'); + console->putc(console->hint, '\n'); +} + + +static inline void +term_put_newline(struct ecdc_console * console) +{ + switch(console->mode) { + case ECDC_MODE_ANSI: + default: + term_put_ansi_newline(console); + break; + } +} + + +// -------------------------- Backspace + +static inline void +term_backspace_ansi(struct ecdc_console * console) +{ + console->putc(console->hint, '\x08'); // BS + console->putc(console->hint, '\x20'); // SP + console->putc(console->hint, '\x08'); // BS +} + + +static inline void +term_backspace(struct ecdc_console * console) +{ + switch(console->mode) { + case ECDC_MODE_ANSI: + default: + term_backspace_ansi(console); + break; + } +} + + +//------------------- Character writing + +static void +term_puts(struct ecdc_console * console, const char * str) +{ + if(NULL != str) { + while(*str != '\0') { + if('\n' == *str) { + term_put_newline(console); + } else if('\x08' == *str) { + term_backspace(console); + } else { + console->putc(console->hint, *str); + } + ++str; + } + } +} + + +static inline void +term_putc(struct ecdc_console * console, char c) +{ + if('\n' == c) { + term_put_newline(console); + } else if('\x08' == c) { + term_backspace(console); + } else { + console->putc(console->hint, c); + } +} + + +static inline void +term_puts_raw(struct ecdc_console * console, const char * str) +{ + if(NULL != str) { + while(*str != '\0') { + console->putc(console->hint, *str); + ++str; + } + } +} + + +static inline void +term_putc_raw(struct ecdc_console * console, char c) +{ + console->putc(console->hint, c); +} + + +// ------------------ Character reading + +static inline int +term_getc_raw(struct ecdc_console * console) +{ + int ret = console->snoop_char; + console->snoop_char = ECDC_GETC_EOF; + + if(ECDC_GETC_EOF == ret) { + ret = console->getc(console->hint); + } + + return ret; +} + + +static inline void +term_set_snoop_char(struct ecdc_console * console, char c) +{ + console->snoop_char = c; +} + + +// ---------------------------------------------------- State machine functions + + +static void +state_start_new_command(struct ecdc_console * console); + + +static void +state_read_input(struct ecdc_console * console); + + +static void +state_parse_escape_sequence_ansi(struct ecdc_console * console) +{ + // TODO: Stub + // This would be a great spot to handle arrow keys + console->state = state_read_input; +} + + +static void +state_read_escape_sequence(struct ecdc_console * console) +{ + bool abort_sequence = false; + bool parse_sequence = false; + + int loop_limit; + for(loop_limit = 0; loop_limit < 8; ++loop_limit) + { + int new_char = term_getc_raw(console); + if(ECDC_GETC_EOF == new_char) { + break; + } + + char in = new_char; + + if(('\x18' == in) || ('\x1A' == in)) { + // CAN or SUB + abort_sequence = true; + break; + } else if(console->cs_write_index < CS_BUFFER_SIZE) { + console->cs_buffer[console->cs_write_index] = in; + size_t index = console->cs_write_index; + ++console->cs_write_index; + + if(1 == index) { + if('[' == in) { + // Control sequence introducer, this will be a 3 or more + // character sequence + } else if(('\x40' <= in) && ('\x5F' >= in)) { + // End of a two character escape sequence + parse_sequence = true; + break; + } + } else if(1 < index) { + if(('\x40' <= in) && ('\x7E' >= in)) { + // End of a multi character sequence + parse_sequence = true; + break; + } + } + } else { + // Dump the sequence, parsing it would be meaningless + term_set_snoop_char(console, in); + abort_sequence = true; + break; + } + } + + if(abort_sequence) { + size_t i; + for(i = 0; i < console->cs_write_index; ++i) { + term_putc_raw(console, console->cs_buffer[i]); + } + console->cs_write_index = 0; + console->state = state_read_input; + } else if(parse_sequence) { + switch(console->mode) { + case ECDC_MODE_ANSI: + default: + console->state = state_parse_escape_sequence_ansi; + break; + } + } +} + + +static void +state_parse_input(struct ecdc_console * console) +{ + if(NULL == console) { + return; + } + + // Clear argv + { + size_t i; + for(i = 0; i < console->max_argc; ++i) { + console->argv[i] = NULL; + } + } + + // Split + size_t argc = 0; + { + char * arg_line = console->arg_line; + arg_line[console->arg_line_write_index] = '\0'; + + size_t i = 0; + for(; i < console->max_argc; ++i) { + char * start = find_first_non_whitesapce(arg_line); + if(NULL == start) { + // Reached the \0 at the end of the string + break; + } + + console->argv[i] = start; + argc = i + 1; + + char * stop = find_fist_whitespace(start); + if(NULL == stop) { + // Reached the \0 at the end of the string + break; + } + *stop = '\0'; + arg_line = stop + 1; + } + } + + // Search for handler + if(argc > 0) { + struct ecdc_command * command = locate_command(console, console->argv[0]); + if(NULL != command) { + // Found + command->callback(command->hint, argc, console->argv); + } else { + term_puts(console, "'"); + term_puts(console, console->argv[0]); + term_puts(console, "' not found\n"); + } + } + + console->state = state_start_new_command; +} + + +static void +state_read_input(struct ecdc_console * console) +{ + int loop_limit; + for(loop_limit = 0; loop_limit < 8; ++loop_limit) + { + int new_char = term_getc_raw(console); + if(ECDC_GETC_EOF == new_char) { + break; + } + + bool local_echo = false; + + char in = new_char; + if('\r' == in) { + term_put_newline(console); + console->state = state_parse_input; + break; + } else if('\x00' == in) { + // Nothing to do here + } else if(('\x08' == in) || ('\x7F' == in)) { + // Backspace + // This stuff gets super weird, apparently everyone on the planet + // screwed up how backspace and delete work. See + // http://www.ibb.net/~anne/keyboard.html for the full train wreck + if(console->arg_line_write_index > 0) { + term_backspace(console); + --console->arg_line_write_index; + } + } else if('\x1B' == in) { + // Start of a control sequence + term_set_snoop_char(console, in); + console->cs_write_index = 0; + console->state = state_read_escape_sequence; + } else if('\x1F' < in) { + // Non-control sequence characters + if(console->arg_line_write_index < console->arg_line_size) { + console->arg_line[console->arg_line_write_index] = in; + ++console->arg_line_write_index; + local_echo = console->f_local_echo; + } + } + + if(local_echo) { + term_putc_raw(console, in); + } + } +} + + +static void +state_start_new_command(struct ecdc_console * console) +{ + // Clear input string + console->arg_line_write_index = 0; + + // Clear argv + { + size_t i; + for(i = 0; i < console->max_argc; ++i) { + console->argv[i] = NULL; + } + } + + // Set new state to read user input + if (NULL == console->prompt) + { + term_puts(console, DEFAULT_PROMPT); + } + else + { + term_puts(console, console->prompt); + } + + console->state = state_read_input; +} + + +static void +__attribute__((unused)) +state_wait_for_client(struct ecdc_console * console) +{ + int in = term_getc_raw(console); + if(ECDC_GETC_EOF != in) { + term_set_snoop_char(console, in); + console->state = state_start_new_command; + } +} + + + +// ---------------------------------------------------------- Build in commands + + +static void +built_in_list_command(void * hint, int argc, char const * argv[]) +{ + (void) argc; + (void) argv; + + struct ecdc_console * console = (struct ecdc_console *) hint; + + struct ecdc_command * command; + for(command = console->root; NULL != command; command = command->next) { + term_puts(console, command->name); + term_put_newline(console); + } +} + + +// ----------------------------------------------------------- Public functions + + +struct ecdc_console * +ecdc_alloc_console(void * console_hint, + ecdc_getc_fn getc_fn, + ecdc_putc_fn putc_fn, + size_t max_arg_line_length, + size_t max_arg_count) +{ + struct ecdc_console * console = + (struct ecdc_console *) malloc(sizeof(struct ecdc_console)); + if(NULL == console) { + goto out; + } + + console->root = NULL; + console->getc = getc_fn; + console->putc = putc_fn; + console->hint = console_hint; + console->snoop_char = ECDC_GETC_EOF; + console->state = state_start_new_command; + console->prompt = NULL; + + if(max_arg_line_length < 16) { + max_arg_line_length = 16; + } + console->arg_line_size = max_arg_line_length; + console->arg_line_write_index = 0; + + size_t alloc_size = (max_arg_line_length + 1) * sizeof(char); + console->arg_line = (char *) malloc(alloc_size); + if(NULL == console->arg_line) { + goto out_arg_line_fail; + } + + + if(max_arg_count < 1) { + max_arg_count = 1; + } + console->max_argc = max_arg_count; + + console->argv = (const char **) malloc(sizeof(char *) * max_arg_count); + if(NULL == console->argv) { + goto out_argv_fail; + } + + size_t i; + for(i = 0; i < max_arg_count; ++i) { + console->argv[i] = NULL; + } + + + // Initialize control sequence + console->cs_write_index = 0; + for(i = 0; i < CS_BUFFER_SIZE; ++i) { + console->cs_buffer[i] = '\x00'; + } + + + // Set default settings + ecdc_configure_console(console, ECDC_MODE_ANSI, ECDC_SET_LOCAL_ECHO); + + + // Success + goto out; + + out_argv_fail: + free(console->arg_line); + + out_arg_line_fail: + free(console); + console = NULL; + + out: + return console; +} + + +void +ecdc_free_console(struct ecdc_console * console) +{ + if(console != NULL) { + while(NULL != console->root) { + unregister_command(console->root); + } + + free(console->argv); + free(console->arg_line); + free(console->prompt); + free(console); + } +} + + +void +ecdc_pump_console(struct ecdc_console * console) +{ + if(NULL != console) + { + console->state(console); + } +} + + +void +ecdc_configure_console(struct ecdc_console * console, + enum ecdc_mode mode, + int flags) +{ + if(NULL != console) { + console->mode = mode; + + console->f_local_echo = (ECDC_SET_LOCAL_ECHO & flags) ? true : false; + } +} + + + +struct ecdc_command * +ecdc_alloc_command(void * command_hint, + struct ecdc_console * console, + const char * command_name, + ecdc_callback_fn callback) +{ + struct ecdc_command * command = NULL; + + do { + if(NULL == command_name) { + break; + } + + if(NULL != locate_command(console, command_name)) { + break; + } + + command = (struct ecdc_command *) malloc(sizeof(struct ecdc_command)); + if(NULL == command) { + break; + } + + command->console = NULL; + command->next = NULL; + command->callback = callback; + command->hint = command_hint; + + command->name = strdup(command_name); + + register_command(console, command); + } while(0); + + return command; +} + + +void +ecdc_free_command(struct ecdc_command * command) +{ + if(NULL != command) { + unregister_command(command); + + free(command->name); + free(command); + } +} + + +struct ecdc_command * +ecdc_alloc_list_command(struct ecdc_console * console, + const char * command_name) +{ + return ecdc_alloc_command(console, + console, + command_name, + built_in_list_command); +} + + +char const * +ecdc_replace_prompt(struct ecdc_console *console, + char const *prompt) +{ + if ((NULL == console) || (NULL == prompt)) + { + return NULL; + } + + // If the prompt was previously not set, it will be NULL which will not + // have any ill side effects when calling free + free(console->prompt); + + console->prompt = strdup(prompt); + return console->prompt; +} + +void +ecdc_free_prompt(struct ecdc_console *console) +{ + free(console->prompt); + console->prompt = NULL; +} + +void +ecdc_putc(struct ecdc_console * console, char c) +{ + if(NULL != console) { + term_putc(console, c); + } +} + + +void +ecdc_puts(struct ecdc_console * console, const char * str) +{ + if(NULL != console) { + term_puts(console, str); + } +} + diff --git a/SM7CUSTV1/ecdc.h b/SM7CUSTV1/ecdc.h new file mode 100644 index 00000000..99b26a78 --- /dev/null +++ b/SM7CUSTV1/ecdc.h @@ -0,0 +1,275 @@ +/** + * Copyright (c) 2016 Bradley Kim Schleusner < bradschl@gmail.com > + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef ECDC_H_ +#define ECDC_H_ + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +#include + + +// --------------------------- Console allocation, deallocation, and processing + + +// ---------- ecdc_getc_fn return value +#define ECDC_GETC_EOF (-1) + + +// ---------------- Configuration modes +enum ecdc_mode { + ECDC_MODE_ANSI = 0 +}; + + +// ---------------- Configuration flags + +// Enable local echo +#define ECDC_SET_LOCAL_ECHO (1 << 0) + + +// --------- Internal console structure +struct ecdc_console; + + +/** + * @brief Function pointer prototype for non-blocking character reads + * @details When the console is pumped, this is polled for incoming characters. + * If there are no characters to read, then ECDC_GETC_EOF should be + * returned. + * It is expected that this is non-blocking + * + * @param console_hint Optional console hint parameter. This pointer may be + * used for whatever the implementation wants (such as a this pointer, + * or a buffer pointer) + * @return User input character or ECDC_GETC_EOF + */ +typedef int (*ecdc_getc_fn)(void * console_hint); + + +/** + * @brief Function pointer prototype for writing characters + * @details It is expected that this is non-blocking + * + * @param console_hint Optional console hint parameter. This pointer may be + * used for whatever the implementation wants (such as a this pointer, + * or a buffer pointer) + * @param c Character to write to the output console + */ +typedef void (*ecdc_putc_fn)(void * console_hint, char c); + + +/** + * @brief Allocates a console structure on the heap + * @details The console will be allocated with default settings and no + * registered commands. + * The default settings are ECDC_MODE_ANSI with local echo enabled + * + * @param console_hint Optional console hint parameter. The getc_fn and putc_fn + * functions will be called with this pointer. This pointer may be + * used for whatever the implementation wants (such as a this pointer, + * or a buffer pointer). Set to NULL if not used + * @param getc_fn Character read function + * @param putc_fn Character write function + * @param max_arg_line_length Maximum length of an input line. This is the + * maximum size of the input line and its arguments. 80 characters is + * a sane default. + * @param max_arg_count Maximum number of arguments allowed per command. There + * should be moderate ratio between the argument line length and the + * maximum number of arguments. 10 arguments is a sane default. + * + * @return Console pointer. It is the responsibility of the caller to deallocate + * this with a call to ecdc_free_console. + */ +struct ecdc_console * +ecdc_alloc_console(void * console_hint, + ecdc_getc_fn getc_fn, + ecdc_putc_fn putc_fn, + size_t max_arg_line_length, + size_t max_arg_count); + + +/** + * @brief Deallocates a console + * @details This will free all resources and unregistering all commands + * + * @param ecdc_console Console to deallocate + */ +void +ecdc_free_console(struct ecdc_console * console); + + +/** + * @brief Periodic call to drive character receiving and parsing + * @details This needs to be periodically called to drive the receiving and + * parsing of the commands by the console. Callbacks will also be + * driven by this call. + * + * @param ecdc_console Console to execute + */ +void +ecdc_pump_console(struct ecdc_console * console); + + +/** + * @brief Modifies the console's configuration + * @details This is used to modify the control sequence standard (mode) used by + * the console, as well as configure things like local echo. + * + * @param ecdc_console Console to configure + * @param ecdc_mode Control sequence standard + * @param flags Option flags + */ +void +ecdc_configure_console(struct ecdc_console * console, + enum ecdc_mode mode, + int flags); + +/** + * @brief Replaces prompt + * @details This command will set the prompt or replaces it if previously set by user + * + * @param ecdc_console Console to set prompt on + * @param prompt Pointer to C-string containing the desired prompt + * + * @return Pointer to newly allocated prompt string. It is the responsibility + * of the user to deallocate this with the ecdc_free_prompt fucnction. NULL + * is returned on failure. + * + */ +char const * +ecdc_replace_prompt(struct ecdc_console *console, + char const *prompt); + +/** + * @brief Deallocated previously allocated prompt + * @details This will deallocate any resources allocated by the ecdc_set_prompt command + * and resets prompt to default. + * + * @param ecdc_console Console for which to deallocate prompt + */ +void +ecdc_free_prompt(struct ecdc_console *console); + + +// ------------------------------------------ Command allocation / deallocation + + +// --------- Internal command structure +struct ecdc_command; + + +/** + * @brief Function pointer prototype for console command callbacks + * + * @param hint Optional command hint parameter. This pointer may be used for + * whatever the implementation wants (such as a this pointer) + * @param argc Argument count + * @param argv Argument values. First argument is always the command name + */ +typedef void (*ecdc_callback_fn)(void * hint, int argc, char const * argv[]); + + +/** + * @brief Allocates a new command on the heap + * + * @param command_hint Optional command hint parameter. This will be passed to + * the command callback. This pointer may be used for whatever the + * implementation wants (such as a this pointer). If not used, set + * to NULL + * @param ecdc_console Console to register the command with + * @param command_name Name of the command. When a user inputs a string that + * matches this, the callback will be called. This string is copied, so + * its storage is allowed to be shorter than the returned pointer + * @param callback Command callback + * + * @return Command structure. It is the responsibility of the caller to + * deallocate this with the ecdc_free_command function. NULL is + * returned on failure. + */ +struct ecdc_command * +ecdc_alloc_command(void * command_hint, + struct ecdc_console * console, + const char * command_name, + ecdc_callback_fn callback); + + +/** + * @brief Deallocates a command structure + * @details This will unregister the command and free any resources held by it + * + * @param ecdc_command Command to deallocate + */ +void +ecdc_free_command(struct ecdc_command * command); + + +// ------------------------------------------------- Built-in optional commands + + +/** + * @brief Creates a list command + * @details This command will print the name of every registered command + * + * @param ecdc_console Console to register the command with + * @param command_name Name of the command, i.e. "list", "ls", "dir" + * + * @return Command structure. It is the responsibility of the caller to + * deallocate this with the ecdc_free_command function. NULL is + * returned on failure. + */ +struct ecdc_command * +ecdc_alloc_list_command(struct ecdc_console * console, + const char * command_name); + +// --------------------------------------------------------------------- Extras + + +/** + * @brief Writes a single character to the console output + * @details The console may change the character to handle newlines correctly + * + * @param ecdc_console Console output to use + * @param c Character to write + */ +void +ecdc_putc(struct ecdc_console * console, char c); + + +/** + * @brief Writes a string to the console output + * @details The console may insert sequences to handle newlines correctly + * + * @param ecdc_console Console output to use + * @param str String to write + */ +void +ecdc_puts(struct ecdc_console * console, const char * str); + + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* ECDC_H_ */ diff --git a/SM7CUSTV1/i2c-slaves/eeprom.c b/SM7CUSTV1/i2c-slaves/eeprom.c new file mode 100644 index 00000000..12668180 --- /dev/null +++ b/SM7CUSTV1/i2c-slaves/eeprom.c @@ -0,0 +1,157 @@ +/* + * eeprom.c + * + * Created on: Jul 22, 2019 + * Author: weic + */ +#include +#include +#include +#include +#include + +uint8_t eeprom_read_byte(uint32_t offset) +{ + return *((volatile uint8_t *)(EEPROM_BASE + offset)); +} + +void eeprom_write_byte(uint32_t offset, uint8_t data) +{ + eeprom_program_byte(EEPROM_BASE + offset, data); +} + +static struct eeprom_ctx { + int set_idx; + int idx; + unsigned char tmp; +} ctx; + +static void eeprom_match(void *priv, int dir) +{ + if (dir == I2C_SLAVE_WRITE) { + ctx.set_idx = 2; + } +} + +static inline void idx_set_lo(uint8_t idx) +{ + ctx.idx |= idx; + ctx.idx = ctx.idx % EEPROM_SIZE; +} +static inline void idx_set_hi(uint8_t idx) +{ + ctx.idx = idx << 8; +} +static inline void idx_inc(void) +{ + ctx.idx = (ctx.idx + 1) % EEPROM_SIZE; +} + +static inline void eeprom_spin_lock(void) +{ + __disable_irq(); +} + +static inline void eeprom_spin_unlock(void) +{ + __enable_irq(); +} + +static volatile uint8_t lock = 1; +static volatile uint8_t unlock_code; + +int eeprom_get_lock_status(void) +{ + int tmp; + + eeprom_spin_lock(); + tmp = lock; + eeprom_spin_unlock(); + + return tmp; +} + +void eeprom_lock_code(uint8_t code) +{ + eeprom_spin_lock(); + + /* 'LO': lock + * 'CK': unlock + */ + + /* begin of a sequence */ + if (code == 'L' || code == 'C') + unlock_code = code; + else { + if (code == 'O' && unlock_code == 'L') + lock = 1; + else if (code == 'K' && unlock_code == 'C') + lock = 0; + + unlock_code = 0; + } + + eeprom_spin_unlock(); +} + +void eeprom_write_byte_protected(uint16_t offset, uint8_t data) +{ + if (!eeprom_get_lock_status()) + eeprom_write_byte(offset, data); +} + +static void eeprom_write(void *priv, uint8_t data) +{ + switch (ctx.set_idx) { + case 2: + ctx.tmp = data; + ctx.set_idx = 1; + return; + case 1: + idx_set_hi(ctx.tmp); + idx_set_lo(data); + ctx.set_idx = 0; + return; + default: + break; + } + eeprom_write_byte_protected(ctx.idx, data); + idx_inc(); +} + +static uint8_t eeprom_read(void *priv) +{ + uint8_t tmp; + if (ctx.set_idx == 1) + { + idx_set_hi(0); + idx_set_lo(ctx.tmp); + } + tmp = eeprom_read_byte(ctx.idx); + idx_inc(); + return tmp; +} + +static struct i2c_slave_op slave = { + .addr = 0x6a, + .match = eeprom_match, + .write = eeprom_write, + .read = eeprom_read, +}; + +void eeprom_init(struct i2c_slave_ctx *i2c) +{ + i2c_slave_register(i2c, &slave); +} + +void eeprom_log_power_off_reason(int reason) +{ + uint8_t tmp = reason; + + eeprom_write_byte(EEPROM_POWER_OFF_REASON_OFFSET, tmp); +} + +int is_mixed_mode(void) +{ + return eeprom_read_byte(EEPROM_MIXED_MODE_OFFSET) == 1 ? 1 : 0; +} \ No newline at end of file diff --git a/SM7CUSTV1/i2c-slaves/eeprom.h b/SM7CUSTV1/i2c-slaves/eeprom.h new file mode 100644 index 00000000..3df45076 --- /dev/null +++ b/SM7CUSTV1/i2c-slaves/eeprom.h @@ -0,0 +1,28 @@ +/* + * eeprom.h + * + * Created on: Jul 22, 2019 + * Author: weic + */ + +#ifndef __EEPROM__ +#define __EEPROM__ + +#include +#include + +void eeprom_init(struct i2c_slave_ctx *i2c); +void eeprom_log_power_off_reason(int reason); + +#define EEPROM_POWER_OFF_REASON_POWER_OFF 0x80 +#define EEPROM_POWER_OFF_REASON_RESET 0x81 +#define EEPROM_POWER_OFF_REASON_REBOOT 0x82 +#define EEPROM_POWER_OFF_REASON_OVER_HEAT 0x83 +#define EEPROM_POWER_OFF_REASON_WATCHDOG 0x84 + +int eeprom_get_lock_status(void); +void eeprom_lock_code(uint8_t code); +void eeprom_write_byte_protected(uint16_t offset, uint8_t data); +uint8_t eeprom_read_byte(uint32_t offset); +int is_mixed_mode(void); +#endif diff --git a/SM7CUSTV1/i2c-slaves/keyboard.c b/SM7CUSTV1/i2c-slaves/keyboard.c new file mode 100644 index 00000000..d05dbe2b --- /dev/null +++ b/SM7CUSTV1/i2c-slaves/keyboard.c @@ -0,0 +1,59 @@ +/* + * kbd.c + * + * Created on: Apr 25, 2019 + * Author: weic + */ +#include + +#define KEY_PORT_COUNT 256 +/* +#define KEY_PORT_WIDTH 8 +#define KEY_COUNT (KEY_PORT_COUNT * KEY_PORT_WIDTH) +*/ + +static struct kbd_ctx { + int set_idx; + int idx; + uint8_t map[KEY_PORT_COUNT]; +} kbd_ctx; + +static void kbd_match(void *priv, int dir) +{ + if (dir == I2C_SLAVE_WRITE) + kbd_ctx.set_idx = 1; +} + +static void kbd_write(void *priv, uint8_t data) +{ + if (kbd_ctx.set_idx) { + kbd_ctx.idx = data; + kbd_ctx.set_idx = 0; + return; + } + kbd_ctx.map[kbd_ctx.idx++] &= ~data; +} + +static uint8_t kbd_read(void *priv) +{ + return kbd_ctx.map[kbd_ctx.idx++]; +} + +static struct i2c_slave_op slave = { + .addr = 0x6d, /* kbd common slave address */ + .match = kbd_match, + .write = kbd_write, + .read = kbd_read, +}; + +void kbd_init(struct i2c_slave_ctx *i2c) +{ + i2c_slave_register(i2c, &slave); +} + + +void kbd_set(int port, int key) +{ + kbd_ctx.map[port & 0xff] |= key; +} + diff --git a/SM7CUSTV1/i2c-slaves/keyboard.h b/SM7CUSTV1/i2c-slaves/keyboard.h new file mode 100644 index 00000000..16b30f17 --- /dev/null +++ b/SM7CUSTV1/i2c-slaves/keyboard.h @@ -0,0 +1,7 @@ +#ifndef __KEYBOARD_H__ +#define __KEYBOARD_H__ + +void kbd_set(int port, int key); +void kbd_init(struct i2c_slave_ctx *i2c); + +#endif diff --git a/SM7CUSTV1/i2c-slaves/mcu.c b/SM7CUSTV1/i2c-slaves/mcu.c new file mode 100644 index 00000000..edf2dd6b --- /dev/null +++ b/SM7CUSTV1/i2c-slaves/mcu.c @@ -0,0 +1,436 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include +#include +#include +#define REG_BOARD_TYPE 0x00 +#define REG_SW_VER 0x01 +#define REG_HW_VER 0x02 +#define REG_CMD 0x03 +#define REG_BM1686_TMP 0x04 +#define REG_BOARD_TMP 0x05 +#define REG_INT_STATUS1 0x06 +#define REG_INT_STATUS2 0x07 +#define REG_INT_MASK1 0x08 +#define REG_INT_MASK2 0x09 + +//old +#define REG_INT_STATUS 0x06 +#define REG_TEST_INTR_EN 0x07 +#define REG_INT_MASK 0x08 + +#define REG_SOC_RST_TIMES 0x0a +#define REG_UPTIME_LO 0x0b +#define REG_UPTIME_HI 0x0c +#define REG_POWEROFF_REASON 0x0d + +#define RTC_SECONDS 0x0e +#define RTC_MINUTES 0x0f +#define RTC_HOURS 0x10 +#define RTC_DATE 0x11 +#define RTC_MONTH 0x12 +#define RTC_YEAR 0x13 + +#define I_12V_ATX_L 0x28 + +#define BM1686_TMP_OVER_REPORT 1<<0 +#define POWER_68127_TMP_OVER_REPORT 1<<1 +#define BOARD_TMP_OVER_REPORT 1<<2 +#define BOARD_TMP_OVER_POWEROFF 1<<3 +#define BM1686_TMP_OVER_POWEROFF 1<<4 +#define SYS_POWER_EXCEPTION_POWEROFF 1<<5 +#define V12_EXCEPTION_POWEROFF 1<<6 +#define BM1686_REBOOT_CMD 1<<7 + +#define WATCH_DOG 1<<0 +#define TEST_INT 1<<1 + + +#define REG_GP0 0x14 +#define REG_DDR 0x15 +#define REG_PWR_GOOD 0x16 +#define REG_MODE_FLAG 0x17 + +#define REG_TPU_POWER_CONTROL 0x22 /* tpu power control 0: off 1: on */ +#define REG_POWER_LO 0x24 +#define REG_POWER_HI 0x25 +#define REG_VOLTAGE_LO 0x26 +#define REG_VOLTAGE_HI 0x27 +#define REG_CURRENT_LO 0x28 +#define REG_CURRENT_HI 0x29 + +#define REG_STAGE 0x3c +#define REG_EEPROM_OFFSET_LO 0x3e /* 16bit eeprom address, low 8bits */ +#define REG_EEPROM_OFFSET_HI 0x3f /* 16bit eeprom address, high 8bits */ +#define REG_EEPROM_DATA 0x40 /* eeprom data */ +#define REG_EEPROM_LOCK 0x60 /* eeprom write lock */ +#define REG_CRITICAL_ACTIONS 0x65 +#define REG_CTRITICAL_TEMP 0x66 +#define REG_REPOWERON_TEMP 0x67 +#define MCU_REG_MAX 0x68 + +#define MCU_EEPROM_DATA_MAX 0x20 + +extern uint8_t sm7_power_off_flag; + +struct mcu_ctx { + int set_idx; + int idx; + int cmd_tmp; + uint8_t cmd; + uint8_t gp0; + uint8_t int_status[2]; + uint8_t int_mask[2]; + uint8_t eeprom_offset_l, eeprom_offset_h; + uint16_t tmp; + uint8_t critical_action; + uint8_t repoweron_temp; + uint8_t critical_temp; +}; + +static struct mcu_ctx mcu_ctx; + +static const char *tpu_powers[] = { + "VDD-TPU", + "ACK-TPU", + "VDD-TPU-MEM", + "ACK-TPU_MEM" +}; + +static void tpu_power_setup(unsigned char enable) +{ + if (enable) + power_nodes_on(tpu_powers, ARRAY_SIZE(tpu_powers)); + else + power_nodes_off(tpu_powers, ARRAY_SIZE(tpu_powers)); +} + +static int tpu_get_power_status(void) +{ + return power_nodes_status(tpu_powers, ARRAY_SIZE(tpu_powers)); +} + +void mcu_raise_interrupt(uint8_t reg_idx, uint8_t interrupts) +{ + mcu_ctx.int_status[reg_idx] |= interrupts; + if ((mcu_ctx.int_status[0]&(~mcu_ctx.int_mask[0])) || (mcu_ctx.int_status[1]&(~mcu_ctx.int_mask[1]))) + gpio_set(MCU_INT_PORT, MCU_INT_PIN); +} + +void mcu_clear_interrupt(uint8_t reg_idx, uint8_t interrupts) +{ + mcu_ctx.int_status[reg_idx] &= ~interrupts; + if ((mcu_ctx.int_status[0]&(~mcu_ctx.int_mask[0] == 0)) && (mcu_ctx.int_status[1]&(~mcu_ctx.int_mask[1] == 0))) + gpio_clear(MCU_INT_PORT, MCU_INT_PIN); +} + +void mcu_set_int_mask(uint8_t reg_idx, uint8_t mask) +{ + mcu_ctx.int_mask[reg_idx] = mask; +} + +static inline void idx_set(struct mcu_ctx *ctx, uint8_t idx) +{ + ctx->idx = idx % MCU_REG_MAX; +} + +static inline void idx_inc(struct mcu_ctx *ctx) +{ + ctx->idx = (ctx->idx + 1) % MCU_REG_MAX; +} + +static void mcu_match(void *priv, int dir) +{ + struct mcu_ctx *ctx = priv; + + if (dir == I2C_SLAVE_WRITE) + ctx->set_idx = 1; +} + +#define CMD_POWER_OFF 0x02 +#define CMD_RESET 0x03 // drag reset pin +#define CMD_REBOOT 0x07 // power off - power on +#define CMD_UPDATE 0x08 + +void mcu_process(void) +{ + if (mcu_ctx.cmd == 0) + return; + + i2c_peripheral_disable(I2C1); + nvic_disable_irq(NVIC_I2C1_IRQ); + switch (mcu_ctx.cmd) { + case CMD_POWER_OFF: + eeprom_log_power_off_reason(EEPROM_POWER_OFF_REASON_POWER_OFF); + power_off(); + wdt_reset(); + sm7_power_off_flag = 1; + break; + case CMD_RESET: + eeprom_log_power_off_reason(EEPROM_POWER_OFF_REASON_RESET); + chip_reset(); + wdt_reset(); + break; + case CMD_REBOOT: + eeprom_log_power_off_reason(EEPROM_POWER_OFF_REASON_REBOOT); + chip_popd_reset_early(); + set_needpoweron(); + wdt_reset(); + break; + case CMD_UPDATE: + nvic_enable_irq(NVIC_I2C1_IRQ); + i2c_upgrade_start(); + break; + default: + break; + } + mcu_ctx.cmd = 0; + mcu_ctx.cmd_tmp = 0; + i2c_peripheral_enable(I2C1); + nvic_enable_irq(NVIC_I2C1_IRQ); +} + +static inline uint16_t eeprom_offset(struct mcu_ctx *ctx) +{ + uint16_t offset_base = ctx->eeprom_offset_l | + (ctx->eeprom_offset_h << 8); + uint16_t offset_off = + ctx->idx - REG_EEPROM_DATA; + return offset_base + offset_off; +} + +static void mcu_write(void *priv, volatile uint8_t data) +{ + struct mcu_ctx *ctx = priv; + + if (ctx->set_idx) { + idx_set(ctx, data); + ctx->set_idx = 0; + return; + } + + switch (ctx->idx) { + case REG_CMD: + ctx->cmd_tmp = data; + break; + case REG_INT_STATUS1: + mcu_clear_interrupt(0, data); + break; + case REG_INT_STATUS2: + if (data & TEST_INT) + mcu_raise_interrupt(1, TEST_INT); + break; + case REG_INT_MASK1: + mcu_set_int_mask(0, data); + break; + case REG_INT_MASK2: + mcu_set_int_mask(1, data); + break; + case REG_GP0: + ctx->gp0 = data; + break; + case REG_EEPROM_OFFSET_LO: + ctx->eeprom_offset_l = data; + break; + case REG_EEPROM_OFFSET_HI: + ctx->eeprom_offset_h = data; + break; + case REG_EEPROM_DATA ... + (REG_EEPROM_DATA + MCU_EEPROM_DATA_MAX - 1): + eeprom_write_byte_protected(eeprom_offset(ctx), data); + break; + case REG_EEPROM_LOCK: + eeprom_lock_code(data); + break; + case REG_TPU_POWER_CONTROL: + tpu_power_setup(data); + break; + case REG_CRITICAL_ACTIONS: + ctx->critical_action = data; + break; + case REG_REPOWERON_TEMP: + ctx->repoweron_temp = data; + break; + case REG_CTRITICAL_TEMP: + ctx->critical_temp = data; + break; + default: + break; + } + + idx_inc(ctx); +} + +static uint8_t mcu_read(void *priv) +{ + struct mcu_ctx *ctx = priv; + uint8_t ret = 0; + + switch (ctx->idx) { + case REG_BOARD_TYPE: + ret = get_board_type(); + break; + case REG_SW_VER: + ret = get_firmware_version(); + break; + case REG_HW_VER: + ret = get_hardware_version(); + break; + case REG_CMD: + ret = 0; + break; + case REG_BM1686_TMP: + ret = get_soc_temp(); + break; + case REG_BOARD_TMP: + ret = get_ntc_tmp(); + break; + case REG_INT_STATUS1: + ret = ctx->int_status[0]; + break; + case REG_INT_STATUS2: + ret = ctx->int_status[1]; + break; + case REG_INT_MASK1: + ret = ctx->int_mask[0]; + break; + case REG_INT_MASK2: + ret = ctx->int_mask[1]; + break; + case REG_SOC_RST_TIMES: + ret = chip_reset_times() & 0xff; + break; + case REG_UPTIME_LO: + ctx->tmp = chip_uptime(); + ret = ctx->tmp & 0xff; + break; + case REG_UPTIME_HI: + ret = (ctx->tmp >> 8) & 0xff; + break; + case REG_GP0: + ret = ctx->gp0; + break; + case REG_DDR: + ret = get_ddr_type(); + break; + case REG_PWR_GOOD: + ret = 1; + break; + case REG_MODE_FLAG: + ret = get_work_mode(); + break; + case REG_POWER_LO: + ctx->tmp = get_current() * 12; + ret = ctx->tmp & 0xff; + break; + case REG_POWER_HI: + ret = (ctx->tmp >> 8) & 0xff; + break; + case REG_CURRENT_LO: + ctx->tmp = get_current(); + ret = ctx->tmp & 0xff; + break; + case REG_CURRENT_HI: + ret = (ctx->tmp >> 8) & 0xff; + break; + case REG_STAGE: + ret = get_stage(); + break; + case REG_EEPROM_OFFSET_LO: + ret = ctx->eeprom_offset_l; + break; + case REG_EEPROM_OFFSET_HI: + ret = ctx->eeprom_offset_h; + break; + case REG_EEPROM_DATA ... + (REG_EEPROM_DATA + MCU_EEPROM_DATA_MAX - 1): + ret = eeprom_read_byte(eeprom_offset(ctx)); + break; + case REG_EEPROM_LOCK: + ret = eeprom_get_lock_status(); + break; + case REG_TPU_POWER_CONTROL: + ret = tpu_get_power_status(); + break; + case REG_CRITICAL_ACTIONS: + ret = ctx->critical_action; + break; + case REG_REPOWERON_TEMP: + ret = ctx->repoweron_temp; + break; + case REG_CTRITICAL_TEMP: + ret = ctx->critical_temp; + break; + default: + ret = 0xff; + break; + } + + idx_inc(ctx); + return ret; +} + +static void mcu_stop(void *priv) +{ + struct mcu_ctx *ctx = priv; + ctx->cmd = ctx->cmd_tmp; +} + +static void mcu_reset(void *priv) +{ + struct mcu_ctx *ctx = priv; + memset(ctx, 0x00, sizeof(*ctx)); +} + +static struct i2c_slave_op slave = { + .addr = 0x17, /* mcu common slave address */ + .mask = 0x00, + .match = mcu_match, + .write = mcu_write, + .read = mcu_read, + .stop = mcu_stop, + .reset = mcu_reset, + .priv = &mcu_ctx, +}; + +void mcu_init(struct i2c_slave_ctx *i2c_slave_ctx) +{ + mcu_ctx.critical_action = CRITICAL_ACTION_POWERDOWN; + mcu_ctx.critical_temp = 120; + mcu_ctx.repoweron_temp = 85; + loop_add(mcu_process); + slave.addr = 0x17; + i2c_slave_register(i2c_slave_ctx, &slave); +} + +void mcu_test_init(struct i2c_slave_ctx *i2c_slave_ctx) +{ + slave.addr = 0x38; + i2c_slave_register(i2c_slave_ctx, &slave); +} + +uint8_t get_critical_action(void) +{ + return mcu_ctx.critical_action; +} + +uint8_t get_critical_temp(void) +{ + return mcu_ctx.critical_temp; +} + +uint8_t get_repoweron_temp(void) +{ + return mcu_ctx.repoweron_temp; +} diff --git a/SM7CUSTV1/i2c-slaves/mcu.h b/SM7CUSTV1/i2c-slaves/mcu.h new file mode 100644 index 00000000..d992da94 --- /dev/null +++ b/SM7CUSTV1/i2c-slaves/mcu.h @@ -0,0 +1,25 @@ +#ifndef __MCU_H__ +#define __MCU_H__ + +#include +#include + +#define MCU_INT_OVER_TEMP_ALERT BIT(0) +#define MCU_INT_OVER_TEMP_POWEROFF BIT(1) +#define MCU_INT_POWERON_ERR BIT(2) +#define MCU_INT_WDT_RST BIT(3) +#define MCU_INT_RESET_OP BIT(4) +#define MCU_INT_TEST_INTR BIT(7) + +#define CRITICAL_ACTION_POWERDOWN 2 +#define CRITICAL_ACTION_REBOOT 1 + +void mcu_init(struct i2c_slave_ctx *i2c_slave_ctx); +void mcu_raise_interrupt(uint8_t reg_idx, uint8_t interrupts); +void mcu_test_init(struct i2c_slave_ctx *i2c_slave_ctx); +void mcu_process(void); +uint8_t get_critical_action(void); +uint8_t get_critical_temp(void); +uint8_t get_repoweron_temp(void); + +#endif diff --git a/SM7CUSTV1/i2c-slaves/pic.c b/SM7CUSTV1/i2c-slaves/pic.c new file mode 100644 index 00000000..0472b0d2 --- /dev/null +++ b/SM7CUSTV1/i2c-slaves/pic.c @@ -0,0 +1,112 @@ +#include +#include +#include +#include + +#define PIC_ADDR 0x24 +#define PIC_I2C I2C2 +/* smbus timeout, count in ms */ +#define PIC_SMBTO 1 + +#define ERROR_RETRY 10 + +static int is_pic_available; + +int pic_available(void) +{ + return is_pic_available; +} + +int pic_probe(void) +{ + uint8_t tmp; + int err; + + err = i2c_master_smbus_read_byte(PIC_I2C, PIC_ADDR, PIC_SMBTO, + PIC_REG_BOARD_TYPE, &tmp); + + return is_pic_available = (err == 0); +} + +int pic_write(uint8_t reg, uint8_t val) +{ + int err; + int i = 0; + + nvic_disable_irq(NVIC_I2C1_IRQ); + + do { + err = i2c_master_smbus_write_byte( + PIC_I2C, PIC_ADDR, PIC_SMBTO, reg, val); + ++i; + } while (err && i <= ERROR_RETRY); + + nvic_enable_irq(NVIC_I2C1_IRQ); + + return err ? -1 : 0; +} + + +int pic_read(uint8_t reg) +{ + uint8_t tmp; + int err; + int i = 0; + + nvic_disable_irq(NVIC_I2C1_IRQ); + + do { + err = i2c_master_smbus_read_byte(PIC_I2C, PIC_ADDR, PIC_SMBTO, + reg, &tmp); + ++i; + } while (err && i <= ERROR_RETRY); + + nvic_enable_irq(NVIC_I2C1_IRQ); + + return err ? -1 : tmp; +} + + +static struct pic_ctx { + int set_idx; + uint8_t idx; +} pic_ctx; + +static void pic_i2c_slave_match(void *priv, int dir) +{ + if (dir == I2C_SLAVE_WRITE) + pic_ctx.set_idx = 1; +} + +static void pic_i2c_slave_write(void *priv, uint8_t data) +{ + if (pic_ctx.set_idx) { + pic_ctx.idx = data; + pic_ctx.set_idx = 0; + return; + } + pic_write(pic_ctx.idx, data); + + ++pic_ctx.idx; +} + +static uint8_t pic_i2c_slave_read(void *priv) +{ + int err; + + err = pic_read(pic_ctx.idx); + ++pic_ctx.idx; + return err < 0 ? 0 : err; +} + +static struct i2c_slave_op slave = { + .addr = 0x6e, /* pic common slave address */ + .match = pic_i2c_slave_match, + .write = pic_i2c_slave_write, + .read = pic_i2c_slave_read, +}; + +void pic_init(struct i2c_slave_ctx *i2c) +{ + i2c_slave_register(i2c, &slave); +} diff --git a/SM7CUSTV1/i2c-slaves/pic.h b/SM7CUSTV1/i2c-slaves/pic.h new file mode 100644 index 00000000..5b417319 --- /dev/null +++ b/SM7CUSTV1/i2c-slaves/pic.h @@ -0,0 +1,30 @@ +#ifndef __PIC_H__ +#define __PIC_H__ + +#include + +/* PIC function definition */ +#define PIC_REG_BOARD_TYPE 0 +#define PIC_REG_SW_VERSION 1 +#define PIC_REG_HW_VERSION 2 +#define PIC_REG_CTRL 3 +#define PIC_REG_SOC_TEMP 4 +#define PIC_REG_HEATER_CTRL 5 +#define PIC_REG_REQUEST 6 + +#define PIC_BOARD_TYPE_SE5 3 +#define PIC_CMD_REBOOT 7 +#define PIC_CMD_POWER_OFF 2 + +#define PIC_REQ_NONE 0 +#define PIC_REQ_POWER_OFF 1 +#define PIC_REQ_REBOOT 2 +#define PIC_REQ_FACTORY_RESET 3 + +int pic_available(void); +int pic_probe(void); +int pic_write(uint8_t reg, uint8_t val); +int pic_read(uint8_t reg); +void pic_init(struct i2c_slave_ctx *i2c); + +#endif diff --git a/SM7CUSTV1/i2c-slaves/slt.c b/SM7CUSTV1/i2c-slaves/slt.c new file mode 100644 index 00000000..06970104 --- /dev/null +++ b/SM7CUSTV1/i2c-slaves/slt.c @@ -0,0 +1,93 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include +#include + +#define SLT_REG_LEN 64 +#define SLT_REG_MAX 64 + +struct slt_ctx { + int set_idx; + int idx; + uint8_t reg[SLT_REG_LEN]; +}; + +static struct slt_ctx slt_ctx; + +static inline void idx_set(struct slt_ctx *ctx, uint8_t idx) +{ + ctx->idx = idx % SLT_REG_MAX; +} + +static inline void idx_inc(struct slt_ctx *ctx) +{ + ctx->idx = (ctx->idx + 1) % SLT_REG_MAX; +} + +static void slt_match(void *priv, int dir) +{ + struct slt_ctx *ctx = priv; + + if (dir == I2C_SLAVE_WRITE) + ctx->set_idx = 1; +} + +static void slt_write(void *priv, volatile uint8_t data) +{ + struct slt_ctx *ctx = priv; + + if (ctx->set_idx) { + idx_set(ctx, data); + ctx->set_idx = 0; + return; + } + + ctx->reg[ctx->idx] = data; + + idx_inc(ctx); +} + +static uint8_t slt_read(void *priv) +{ + struct slt_ctx *ctx = priv; + uint8_t ret = 0; + + ret = ctx->reg[ctx->idx]; + + idx_inc(ctx); + return ret; +} + +static struct i2c_slave_op slave = { + .addr = 0x6f, /* mcu common slave address */ + .match = slt_match, + .write = slt_write, + .read = slt_read, + .priv = &slt_ctx, +}; + +void slt_init(struct i2c_slave_ctx *i2c_slave_ctx) +{ + i2c_slave_register(i2c_slave_ctx, &slave); +} + +void slt_reset(void) +{ + memset(&slt_ctx, 0, sizeof(struct slt_ctx)); +} + +uint16_t get_slt_result(void) +{ + return (slt_ctx.reg[1] << 8) | slt_ctx.reg[0]; +} diff --git a/SM7CUSTV1/i2c-slaves/slt.h b/SM7CUSTV1/i2c-slaves/slt.h new file mode 100644 index 00000000..6ca560c4 --- /dev/null +++ b/SM7CUSTV1/i2c-slaves/slt.h @@ -0,0 +1,7 @@ +#ifndef __SLT_H__ +#define __SLT_H__ + +void slt_init(struct i2c_slave_ctx *i2c_slave_ctx); +void slt_reset(void); +uint16_t get_slt_result(void); +#endif \ No newline at end of file diff --git a/SM7CUSTV1/i2c-slaves/tca6416a.c b/SM7CUSTV1/i2c-slaves/tca6416a.c new file mode 100644 index 00000000..d4c22031 --- /dev/null +++ b/SM7CUSTV1/i2c-slaves/tca6416a.c @@ -0,0 +1,166 @@ +#include +#include +#include +#include +#include + +#define TCA6416A_ADDR 0x20 + +#define TCA6416A_I2C I2C2 + +/* in ms */ +#define TCA6416A_SMBTO (1) + +static int is_tca6416a_available; +static uint32_t dummy_tca6416a_regmap[TCA6416A_REG_MAX]; + +int tca6416a_available(void) +{ + return is_tca6416a_available; +} + +/* true if 6416 is active */ +int tca6416a_probe(void) +{ + int err; + uint8_t tmp; + + err = i2c_master_smbus_read_byte( + TCA6416A_I2C, TCA6416A_ADDR, TCA6416A_SMBTO, + TCA6416A_P0_CFG, &tmp); + + return is_tca6416a_available = (err == 0); +} + +int tca6416a_write(uint8_t reg, uint8_t val) +{ + int err; + + if (is_tca6416a_available) { + nvic_disable_irq(NVIC_I2C1_IRQ); + err = i2c_master_smbus_write_byte( + TCA6416A_I2C, TCA6416A_ADDR, TCA6416A_SMBTO, reg, val); + nvic_enable_irq(NVIC_I2C1_IRQ); + } else { + dummy_tca6416a_regmap[reg & TCA6416A_REG_MASK] = val; + err = 0; + } + + return err; +} + +int tca6416a_read(uint8_t reg) +{ + uint8_t tmp; + int err; + + if (is_tca6416a_available) { + nvic_disable_irq(NVIC_I2C1_IRQ); + err = i2c_master_smbus_read_byte( + TCA6416A_I2C, TCA6416A_ADDR, TCA6416A_SMBTO, + reg, &tmp); + nvic_enable_irq(NVIC_I2C1_IRQ); + } else { + tmp = dummy_tca6416a_regmap[reg & TCA6416A_REG_MASK]; + err = 0; + } + + return err ? -1 : tmp; +} + +int tca6416a_get(uint8_t port, uint8_t pin) +{ + uint8_t reg; + int val; + + reg = TCA6416A_P0_IN + (port ? 1 : 0); + val = tca6416a_read(reg); + return val < 0 ? val : (val & (1 << pin)); +} + +void tca6416a_set(uint8_t port, uint8_t pin) +{ + uint8_t reg; + uint8_t val; + + reg = TCA6416A_P0_OUT + (port ? 1 : 0); + val = tca6416a_read(reg); + val |= (1 << pin); + tca6416a_write(reg, val); +} + +void tca6416a_clr(uint8_t port, uint8_t pin) +{ + uint8_t reg; + uint8_t val; + + reg = TCA6416A_P0_OUT + (port ? 1 : 0); + val = tca6416a_read(reg); + val &= ~(1 << pin); + tca6416a_write(reg, val); +} + +static struct { + int set_idx; + int idx; + int temp; +} gpioex_ctx; + +static void tca6416a_i2c_slave_match(void *priv, int dir) +{ + if (dir == I2C_SLAVE_WRITE) + gpioex_ctx.set_idx = 1; +} + +static void tca6416a_i2c_slave_write(void *priv, uint8_t data) +{ + if (gpioex_ctx.set_idx) { + gpioex_ctx.idx = data & TCA6416A_REG_MASK; + gpioex_ctx.set_idx = 0; + return; + } + //debug("write reg:%d, data:%x\n",gpioex_ctx.idx,data); + switch (gpioex_ctx.idx) { + case TCA6416A_P0_IN: + case TCA6416A_P1_IN: + case TCA6416A_P0_POL: + case TCA6416A_P1_POL: + case TCA6416A_P0_CFG: + case TCA6416A_P1_CFG: + /* no effect and donot change pin config */ + return; + case TCA6416A_P0_OUT: + case TCA6416A_P1_OUT: + /* output value is free for user */ + break; + default: + return; + } + + tca6416a_write(gpioex_ctx.idx, data); + + gpioex_ctx.idx = (gpioex_ctx.idx + 1) & TCA6416A_REG_MASK; +} + +static uint8_t tca6416a_i2c_slave_read(void *priv) +{ + int err; + + err = tca6416a_read(gpioex_ctx.idx); + //debug("read reg:%d, data:%x\n",gpioex_ctx.idx,err); + gpioex_ctx.idx = (gpioex_ctx.idx + 1) % 8; + return err < 0 ? 0 : err; +} + +static struct i2c_slave_op slave = { + .addr = 0x6c, + .match = tca6416a_i2c_slave_match, + .write = tca6416a_i2c_slave_write, + .read = tca6416a_i2c_slave_read, +}; + +int tca6416a_init(struct i2c_slave_ctx *i2c) +{ + return i2c_slave_register(i2c, &slave); +} + diff --git a/SM7CUSTV1/i2c-slaves/tca6416a.h b/SM7CUSTV1/i2c-slaves/tca6416a.h new file mode 100644 index 00000000..437e8aaf --- /dev/null +++ b/SM7CUSTV1/i2c-slaves/tca6416a.h @@ -0,0 +1,26 @@ +#ifndef __TCA6416A_H__ +#define __TCA6416A_H__ + +#include + +#define TCA6416A_P0_IN 0 +#define TCA6416A_P1_IN 1 +#define TCA6416A_P0_OUT 2 +#define TCA6416A_P1_OUT 3 +#define TCA6416A_P0_POL 4 +#define TCA6416A_P1_POL 5 +#define TCA6416A_P0_CFG 6 +#define TCA6416A_P1_CFG 7 +#define TCA6416A_REG_MAX 8 +#define TCA6416A_REG_MASK (TCA6416A_REG_MAX - 1) + +int tca6416a_probe(void); +int tca6416a_write(uint8_t reg, uint8_t val); +int tca6416a_read(uint8_t reg); +int tca6416a_get(uint8_t port, uint8_t pin); +void tca6416a_set(uint8_t port, uint8_t pin); +void tca6416a_clr(uint8_t port, uint8_t pin); +int tca6416a_available(void); +int tca6416a_init(struct i2c_slave_ctx *i2c); + +#endif diff --git a/SM7CUSTV1/i2c-slaves/tmp451.c b/SM7CUSTV1/i2c-slaves/tmp451.c new file mode 100644 index 00000000..0cc09253 --- /dev/null +++ b/SM7CUSTV1/i2c-slaves/tmp451.c @@ -0,0 +1,287 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define TMP451_REG_MAX (23) + +#define PTRNA (-1) /* operation not apply */ +#define PORNA (-1) /* power-on reset value not apply */ + +struct tmp451_reg { + const int16_t rptr; /* pointer read */ + const int16_t wptr; /* pointer write */ + const int16_t por; /* power-on reset */ + uint8_t value; /* current value */ +}; + +static struct tmp451_ctx { + int set_ptr; + int soc, board; /* soc and board temperature */ + int critical; /* critical temp */ + int overtemp; + volatile uint8_t *rptr, *wptr; + struct tmp451_reg map[TMP451_REG_MAX]; +} tmp451_ctx = { + .map = { + {0x00, PTRNA, 0x00}, + {0x01, PTRNA, 0x00}, + {0x02, PTRNA, PORNA}, + {0x03, 0x09, 0x04}, /* enable extended mode by default */ + {0x04, 0x0a, 0x08}, + {0x05, 0x0b, 0x55}, + {0x06, 0x0c, 0x00}, + {0x07, 0x0d, 0x55}, + {0x08, 0x0e, 0x00}, + {PTRNA, 0x0f, PORNA}, + {0x10, PTRNA, 0x00}, + {0x11, 0x11, 0x00}, + {0x12, 0x12, 0x00}, + {0x13, 0x13, 0x00}, + {0x14, 0x14, 0x00}, + {0x15, PTRNA, 0x00}, + {0x19, 0x19, 0x6c}, + {0x20, 0x20, 0x55}, + {0x21, 0x21, 0x0a}, + {0x22, 0x22, 0x01}, + {0x23, 0x23, 0x00}, + {0x24, 0x24, 0x00}, + {0xfe, PTRNA, 0x55}, + }, +}; + +static void software_reset(void) +{ + struct tmp451_reg *p; + for (p = tmp451_ctx.map; p != tmp451_ctx.map + TMP451_REG_MAX; ++p) + if (p->por == PORNA) + p->value = 0; + else + p->value = p->por; + tmp451_ctx.set_ptr = 0; + tmp451_ctx.rptr = tmp451_ctx.wptr = &(tmp451_ctx.map[0].value); +} + +static void tmp451_match(void *priv, int dir) +{ + if (dir == I2C_SLAVE_WRITE) + tmp451_ctx.set_ptr = 1; +} + +static void tmp451_write(void *priv, uint8_t data) +{ + if (tmp451_ctx.set_ptr) { + tmp451_ctx.set_ptr = 0; + switch (data){ + case 0: + tmp451_ctx.rptr = &(tmp451_ctx.map[0].value); + tmp451_ctx.wptr = NULL; + return; + case 1: + tmp451_ctx.rptr = &(tmp451_ctx.map[1].value); + tmp451_ctx.wptr = NULL; + return; + } + + struct tmp451_reg *p; + for (p = tmp451_ctx.map; p != tmp451_ctx.map + TMP451_REG_MAX; + ++p) { + if (p->rptr == data) { + tmp451_ctx.rptr = &p->value; + if (p->rptr == p->wptr) + tmp451_ctx.wptr = tmp451_ctx.rptr; + return; + } + if (p->wptr == data) { + tmp451_ctx.rptr = NULL; + tmp451_ctx.wptr = &p->value; + return; + } + } + tmp451_ctx.rptr = NULL; + tmp451_ctx.wptr = NULL; + return; + } + if (tmp451_ctx.wptr) { + *(tmp451_ctx.wptr) = data; + return; + } + // error handling +} + +static uint8_t real_temp_to_reg(int temp) +{ + int is_ex_mode = tmp451_ctx.map[3].value & (1 << 2); + uint8_t reg; + + if (is_ex_mode) { + if (temp < -64) + temp = -64; + else if (temp > 191) + temp = 191; + + reg = temp + 64; + } else { + if (temp < 0) + reg = 0; + else if (temp > 127) + reg = 127; + else + reg = temp; + } + return reg; +} + +static uint8_t tmp451_read(void *priv) +{ + volatile uint8_t * volatile rptr = tmp451_ctx.rptr; + + if (rptr == &(tmp451_ctx.map[0].value)) { + /* board */ + return real_temp_to_reg(tmp451_ctx.board); + } else if (rptr == &(tmp451_ctx.map[1].value)) { + /* soc */ + return real_temp_to_reg(tmp451_ctx.soc); + } else if (rptr) { + return *(tmp451_ctx.rptr); + } + + // error handling + return 0; +} + +static struct i2c_slave_op tmp451_slave = { + .addr = 0x6b, /* tmp451 common slave address */ + .match = tmp451_match, + .write = tmp451_write, + .read = tmp451_read, +}; + +#define TMP451_COLLECT_INTERVAL 2000 +#define TMP451_OVERTEMP_MAX 5 + +#define I2C I2C2 +#define SMBTO 1 +#define TMP451_SLAVE_ADDR (0x4c) + +#define TMP451_ALERT (0x22) +#define TMP451_SMBTO_MASK (1 << 7) + +#define TMP451_CONFIG_RD_ADDR (0x03) +#define TMP451_CONFIG_WR_ADDR (0x09) +#define TMP451_RANGE_MASK (1 << 2) + +/* local temperature */ +#define TMP451_LT (0) +/* remote temperature */ +#define TMP451_RT (1) + +static unsigned long last_time; + +static void tmp451_update_temp(void) +{ + uint8_t tmp; + + i2c_master_smbus_read_byte(I2C, TMP451_SLAVE_ADDR, SMBTO, + TMP451_LT, &tmp); + tmp451_ctx.board = (int)tmp - 64; + + i2c_master_smbus_read_byte(I2C, TMP451_SLAVE_ADDR, SMBTO, + TMP451_RT, &tmp); + tmp451_ctx.soc = (int)tmp - 64; + + set_soc_temp(tmp451_ctx.soc - 5); + set_board_temp(tmp451_ctx.board); + +} + +void tmp451_get_temp(int *board, int *soc) +{ + tmp451_update_temp(); + *board = tmp451_ctx.board; + *soc = tmp451_ctx.soc - 5; +} + +static void tmp451_process(void) +{ + unsigned long current_time = tick_get(); + int soc, board; + + if (current_time - last_time < TMP451_COLLECT_INTERVAL) + return; + + last_time = current_time; + + tmp451_get_temp(&board, &soc); + printf("board temp is:%d, soc temp is:%d \n",board, soc); + + if (get_needpoweron_satus() == 1) { + if (soc < get_repoweron_temp() && board < 80) { + chip_popd_reset_end(); + clr_needpoweron(); + } + } + + if (!chip_is_enabled()) { + tmp451_ctx.overtemp = 0; + return; + } + + if (soc > get_critical_temp()) { + ++tmp451_ctx.overtemp; + if (tmp451_ctx.overtemp > TMP451_OVERTEMP_MAX) { + chip_disable(); + power_off(); + tmp451_ctx.overtemp = 0; + printf("temp is over, board will"); + if (get_critical_action() == CRITICAL_ACTION_REBOOT) { + set_needpoweron(); + printf("reboot\n"); + } else { + printf("poweroff\n"); + } + + } + } +} + +void tmp451_init(struct i2c_slave_ctx *i2c_slave_ctx) +{ + uint8_t tmp; + + + /* enable smbus timeout */ + i2c_master_smbus_read_byte(I2C, TMP451_SLAVE_ADDR, SMBTO, + TMP451_ALERT, &tmp); + tmp |= TMP451_SMBTO_MASK; + i2c_master_smbus_write_byte(I2C, TMP451_SLAVE_ADDR, + SMBTO, TMP451_ALERT, tmp); + + /* enable extended mode */ + i2c_master_smbus_read_byte(I2C, TMP451_SLAVE_ADDR, SMBTO, + TMP451_CONFIG_RD_ADDR, &tmp); + tmp |= TMP451_RANGE_MASK; + i2c_master_smbus_write_byte(I2C, TMP451_SLAVE_ADDR, SMBTO, + TMP451_CONFIG_WR_ADDR, tmp); + + /* wait untill next conversion, tmp451 default conversion rate is 16, so + * it takes at most 62.5ms till next conversion + */ + mdelay(65); + + tmp451_update_temp(); + + last_time = tick_get(); + software_reset(); + i2c_slave_register(i2c_slave_ctx, &tmp451_slave); + loop_add(tmp451_process); +} + diff --git a/SM7CUSTV1/i2c-slaves/tmp451.h b/SM7CUSTV1/i2c-slaves/tmp451.h new file mode 100644 index 00000000..729e2e03 --- /dev/null +++ b/SM7CUSTV1/i2c-slaves/tmp451.h @@ -0,0 +1,7 @@ +#ifndef __TMP451_H__ +#define __TMP451_H__ + +void tmp451_init(struct i2c_slave_ctx *i2c_slave_ctx); +void tmp451_get_temp(int *board, int *soc); + +#endif /* DS1307_H_ */ diff --git a/SM7CUSTV1/i2c-slaves/wdt.c b/SM7CUSTV1/i2c-slaves/wdt.c new file mode 100644 index 00000000..f2f5b5e3 --- /dev/null +++ b/SM7CUSTV1/i2c-slaves/wdt.c @@ -0,0 +1,165 @@ +/* + * wdt.c + * + * Created on: Apr 25, 2019 + * Author: weic + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include + +/* magic number for different type of watchdogs, no need now */ +/* this byte is used to handle some different software implementations of wdt */ +#define WDT_MAGIC_REG (0) +/* write 1 to this register will start watchdog, 0 to stop */ +/* read return register value */ +#define WDT_ENABLE_REG (1) +/* write to this register will result in reloading timeout to counter */ +#define WDT_RELOAD_REG (2) +/* offset 3 is reserved */ +/* write to this register */ +#define WDT_TIMEOUT_REG (4) +#define WDT_COUNTER_REG (8) +#define WDT_REG_MAX (12) + +static struct wdt_ctx { + int set_idx; + int idx; + int enable; + uint32_t timeout; /* get from timer when addr match and read command */ + /* counter count down, ( from timeout to 0) */ + uint32_t counter; /* get from timer when addr match and read command */ + uint32_t timeout_shadow; + uint32_t counter_shadow; + uint32_t clock; /* real clock frequency */ +} wdt_ctx; + +static void wdt_match(void *priv, int dir) +{ + if (dir == I2C_SLAVE_WRITE) { + wdt_ctx.set_idx = 1; + } else { + /* when read request received, update shadow register */ + wdt_ctx.timeout_shadow = wdt_ctx.timeout; + wdt_ctx.counter_shadow = wdt_ctx.counter; + } +} + +static inline void idx_set(uint8_t idx) +{ + wdt_ctx.idx = idx % WDT_REG_MAX; +} +static inline void idx_inc(void) +{ + wdt_ctx.idx = (wdt_ctx.idx + 1) % WDT_REG_MAX; +} + +static void wdt_write(void *priv, uint8_t data) +{ + int offset; + + if (wdt_ctx.set_idx) { + idx_set(data); + wdt_ctx.set_idx = 0; + return; + } + switch (wdt_ctx.idx) { + case WDT_ENABLE_REG: + wdt_ctx.enable = data; + break; + case WDT_TIMEOUT_REG ... (WDT_TIMEOUT_REG + 3): + offset = wdt_ctx.idx - WDT_TIMEOUT_REG; + ((uint8_t *)&(wdt_ctx.timeout_shadow))[offset] = data; + break; + case WDT_RELOAD_REG: + wdt_ctx.counter = wdt_ctx.timeout; + break; + } + idx_inc(); +} + +static uint8_t wdt_read(void *priv) +{ + uint8_t ret = 0; + int offset; + + switch (wdt_ctx.idx) { + case WDT_ENABLE_REG: + ret = wdt_ctx.enable; + break; + case WDT_TIMEOUT_REG ... (WDT_TIMEOUT_REG + 3): + offset = wdt_ctx.idx - WDT_TIMEOUT_REG; + ret = ((uint8_t *)&(wdt_ctx.timeout_shadow))[offset]; + break; + case WDT_COUNTER_REG ... (WDT_COUNTER_REG + 3): + offset = wdt_ctx.idx - WDT_COUNTER_REG; + ret = ((uint8_t *)&(wdt_ctx.counter_shadow))[offset]; + break; + } + idx_inc(); + return ret; +} + +static void wdt_stop(void *priv) +{ + wdt_ctx.timeout = wdt_ctx.timeout_shadow; +} + +static struct i2c_slave_op slave = { + .addr = 0x69, /* wdt common slave address */ + .match = wdt_match, + .write = wdt_write, + .read = wdt_read, + .stop = wdt_stop, +}; + +void wdt_reset(void) +{ + __disable_irq(); + memset(&wdt_ctx, 0, sizeof(wdt_ctx)); +// wdt_ctx.clock = (37 * 1000) / 128; + wdt_ctx.counter = wdt_ctx.counter_shadow = + wdt_ctx.timeout = wdt_ctx.timeout_shadow = 0xffffffff; + __enable_irq(); +} + +void wdt_process(void) +{ + if (wdt_ctx.enable && wdt_ctx.counter == 0) { + chip_disable(); + eeprom_log_power_off_reason(EEPROM_POWER_OFF_REASON_WATCHDOG); + mcu_raise_interrupt(1, MCU_INT_WDT_RST); + wdt_reset(); /* reset to initial state */ + //if (get_board_type() == SM5ME) + //se5_reset_board(); + //else + chip_reset(); + } +} + +static void wdt_isr(void) +{ + if (wdt_ctx.enable && wdt_ctx.counter > 0) + --wdt_ctx.counter; + + return; +} + +void wdt_init(struct i2c_slave_ctx *i2c) +{ + wdt_reset(); + + loop_add(wdt_process); + tick_register_task(wdt_isr, 1000); + i2c_slave_register(i2c, &slave); +} + diff --git a/SM7CUSTV1/i2c-slaves/wdt.h b/SM7CUSTV1/i2c-slaves/wdt.h new file mode 100644 index 00000000..58d8fc09 --- /dev/null +++ b/SM7CUSTV1/i2c-slaves/wdt.h @@ -0,0 +1,17 @@ +/* + * wdt.h + * + * Created on: Apr 25, 2019 + * Author: weic + */ + +#ifndef WDT_H_ +#define WDT_H_ + +#include + +void wdt_init(struct i2c_slave_ctx *i2c); +void wdt_isr(void); +void wdt_reset(void); + +#endif /* WDT_H_ */ diff --git a/SM7CUSTV1/i2c_master.c b/SM7CUSTV1/i2c_master.c new file mode 100644 index 00000000..cd18ebfe --- /dev/null +++ b/SM7CUSTV1/i2c_master.c @@ -0,0 +1,150 @@ +#include +#include +#include +#include +#include + +int i2c_master_init(int i2c) +{ + i2c_reset(i2c); + i2c_peripheral_disable(i2c); + //configure ANFOFF DNF[3:0] in CR1 + i2c_enable_analog_filter(i2c); + i2c_set_digital_filter(i2c, 0); + + i2c_set_speed(i2c, i2c_speed_sm_100k, rcc_apb1_frequency / 1000 / 1000); + + //configure No-Stretch CR1 (only relevant in slave mode) + i2c_enable_stretching(i2c); + //addressing mode + i2c_set_7bit_addr_mode(i2c); + i2c_peripheral_enable(i2c); + return 0; +} + +int i2c_master_destroy(int i2c) +{ + i2c_peripheral_disable(i2c); + return 0; +} + +int i2c_transfer7_timeout(uint32_t i2c, uint8_t addr, unsigned int timeout, + uint8_t *w, size_t wn, + uint8_t *r, size_t rn) +{ + timer_start(timeout * 1000); + + /* waiting for busy is unnecessary. read the RM */ + if (wn) { + i2c_set_7bit_address(i2c, addr); + i2c_set_write_transfer_dir(i2c); + i2c_set_bytes_to_transfer(i2c, wn); + if (rn) { + i2c_disable_autoend(i2c); + } else { + i2c_enable_autoend(i2c); + } + i2c_send_start(i2c); + + while (wn--) { + bool wait = true; + while (wait) { + if (i2c_transmit_int_status(i2c)) { + wait = false; + } + if (timer_is_timeout()) + goto i2c_timeout; + while (i2c_nack(i2c)) + if (timer_is_timeout()) + goto i2c_timeout; + } + i2c_send_data(i2c, *w++); + } + /* not entirely sure this is really necessary. + * RM implies it will stall until it can write out the later bits + */ + if (rn) { + while (!i2c_transfer_complete(i2c)) + if (timer_is_timeout()) + goto i2c_timeout; + } + } + + if (rn) { + /* Setting transfer properties */ + i2c_set_7bit_address(i2c, addr); + i2c_set_read_transfer_dir(i2c); + i2c_set_bytes_to_transfer(i2c, rn); + /* start transfer */ + i2c_send_start(i2c); + /* important to do it afterwards to do a proper repeated start! */ + i2c_enable_autoend(i2c); + + for (size_t i = 0; i < rn; i++) { + while (i2c_received_data(i2c) == 0) + if (timer_is_timeout()) + goto i2c_timeout; + r[i] = i2c_get_data(i2c); + } + } + + /* wait stop condition */ + while (i2c_busy(i2c)) + if (timer_is_timeout()) + goto i2c_timeout; + + timer_stop(); + + return 0; +i2c_timeout: + i2c_peripheral_disable(i2c); + asm volatile ("nop; nop; nop; nop"); + i2c_peripheral_enable(i2c); + return -1; +} + +int i2c_master_trans(int i2c, unsigned char addr, unsigned long timeout, + void *w, unsigned int wn, + void *r, unsigned int rn) +{ + return i2c_transfer7_timeout(i2c, addr, timeout, w, wn, r, rn); +} + +int i2c_master_smbus_read_byte(int i2c, unsigned char addr, + unsigned long timeout, + unsigned char cmd, unsigned char *data) +{ + return i2c_transfer7_timeout(i2c, addr, timeout, &cmd, 1, data, 1); +} + +int i2c_master_smbus_write_byte(int i2c, unsigned char addr, + unsigned long timeout, + unsigned char cmd, unsigned char data) +{ + unsigned char tmp[2]; + + tmp[0] = cmd; + tmp[1] = data; + return i2c_transfer7_timeout(i2c, addr, timeout, tmp, 2, NULL, 0); +} + +int i2c_master_smbus_write(int i2c, unsigned char addr, + unsigned long timeout, unsigned char data) +{ + return i2c_transfer7_timeout(i2c, addr, timeout, &data, 1, NULL, 0); +} + +int i2c_master_smbus_read(int i2c, unsigned char addr, + unsigned long timeout, unsigned char *data) +{ + return i2c_transfer7_timeout(i2c, addr, timeout, NULL, 0, data, 1); +} + +int i2c_master_smbus_read_word(int i2c, unsigned char addr, + unsigned long timeout, + unsigned char cmd, uint16_t *data) +{ + return i2c_transfer7_timeout(i2c, addr, timeout, + &cmd, 1, (uint8_t *)data, 2); +} + diff --git a/SM7CUSTV1/i2c_master.h b/SM7CUSTV1/i2c_master.h new file mode 100644 index 00000000..e9bc234e --- /dev/null +++ b/SM7CUSTV1/i2c_master.h @@ -0,0 +1,26 @@ +#ifndef __I2C_MASTER_H__ +#define __I2C_MASTER_H__ + +#include +/* use I2C1 I2C2 ... as function first parameter */ + +int i2c_master_init(int i2c); +int i2c_master_destroy(int i2c); +int i2c_master_trans(int i2c, unsigned char addr, unsigned long timeout, + void *w, unsigned int wn, void *r, unsigned int rn); +int i2c_master_smbus_read_byte(int i2c, unsigned char addr, + unsigned long timeout, + unsigned char cmd, unsigned char *data); +int i2c_master_smbus_write_byte(int i2c, unsigned char addr, + unsigned long timeout, + unsigned char cmd, unsigned char data); +int i2c_master_smbus_write(int i2c, unsigned char addr, + unsigned long timeout, unsigned char data); +int i2c_master_smbus_read(int i2c, unsigned char addr, + unsigned long timeout, unsigned char *data); + +int i2c_master_smbus_read_word(int i2c, unsigned char addr, + unsigned long timeout, + unsigned char cmd, uint16_t *data); + +#endif diff --git a/SM7CUSTV1/i2c_slave.c b/SM7CUSTV1/i2c_slave.c new file mode 100644 index 00000000..a9a09917 --- /dev/null +++ b/SM7CUSTV1/i2c_slave.c @@ -0,0 +1,320 @@ +#include +#include +#include + +struct i2c_reg { + uint32_t cr1; + uint32_t cr2; + uint32_t oar1; + uint32_t oar2; + uint32_t timingr; + uint32_t timeoutr; + uint32_t isr; + uint32_t icr; + uint32_t pecr; + uint32_t rxdr; + uint32_t txdr; +}; + +struct i2c_isr_op; +typedef void (*isr_cb)(struct i2c_slave_ctx *ctx); +typedef void (*isr_clr)(struct i2c_slave_ctx *ctx, struct i2c_isr_op *isr_op); + +struct i2c_isr_op { + isr_cb cb; + isr_clr clr; + int bit; +}; + +#define CR1_SBC (1 << 16) +#define CR1_RXDMAEN (1 << 15) +#define CR1_TXDMAEN (1 << 14) + +#define CR1_NOSTRETCH (1 << 17) +#define CR1_ERRIE (1 << 7) +#define CR1_TCIE (1 << 6) +#define CR1_STOPIE (1 << 5) +#define CR1_NACKIE (1 << 4) +#define CR1_ADDRIE (1 << 3) +#define CR1_RXIE (1 << 2) +#define CR1_TXIE (1 << 1) + +#define CR1_IES_MASK (0xfe) + +#define CR1_PE (1 << 0) + +#define ISR_ADDCODE_SHIFT (17) +#define ISR_ADDCODE_MASK (0x7f << ISR_ADDCODE_SHIFT) +#define ISR_DIR_SHIFT (16) +#define ISR_DIR_MASK (1 << ISR_DIR_SHIFT) +#define ISR_DIR_WRITE I2C_SLAVE_WRITE +#define ISR_DIR_READ I2C_SLAVE_READ +#define ISR_BUSY_SHIFT (15) +#define ISR_STOPF (0x1UL << 5) +#define ISR_NACKF (0x1UL << 4) +#define ISR_BUSY (0x1 << ISR_BUSY_SHIFT) +#define ISR_TXE (1) + +static unsigned int i2c_intr_disable(struct i2c_slave_ctx *ctx) +{ + unsigned int old = ctx->reg->cr1; + ctx->reg->cr1 &= ~CR1_IES_MASK; + return old; +} + +static void i2c_intr_restore(struct i2c_slave_ctx *ctx, unsigned int old) +{ + ctx->reg->cr1 |= old & CR1_IES_MASK; +} + +#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0])) + +#define ISR_OP_DEFAULT(name) \ +void isr_##name##_cb(struct i2c_slave_ctx *ctx) {} \ +void isr_##name##_clr(struct i2c_slave_ctx *ctx, \ + struct i2c_isr_op *isr_op) \ +{ \ + ctx->reg->icr |= 1 << isr_op->bit; \ +} + +//ISR_OP_DEFAULT(rxne) +//ISR_OP_DEFAULT(txis) +//ISR_OP_DEFAULT(stopf) +ISR_OP_DEFAULT(tcr) +ISR_OP_DEFAULT(tc) +//ISR_OP_DEFAULT(addr) +//ISR_OP_DEFAULT(nackf) +ISR_OP_DEFAULT(berr) +ISR_OP_DEFAULT(arlo) +ISR_OP_DEFAULT(ovr) +ISR_OP_DEFAULT(pecerr) +ISR_OP_DEFAULT(timeout) +ISR_OP_DEFAULT(alert) + +void isr_nackf_cb(struct i2c_slave_ctx *ctx) +{ + if (ctx->slave && ctx->slave->nack) + ctx->slave->nack(ctx->slave->priv); +} +void isr_nackf_clr(struct i2c_slave_ctx *ctx, struct i2c_isr_op *isr_op) +{ + ctx->reg->icr |= 1 << isr_op->bit; + ctx->reg->txdr = 0x00U; + /* This bit can be written to 1 by software in order to flush + * the transmit data register I2C_TXDR. + */ + ctx->reg->isr |= ISR_TXE; +} + +void isr_rxne_clr(struct i2c_slave_ctx *ctx, struct i2c_isr_op *isr_op) +{ + /* do nothing, read rxdr will clear this bit */ +} + +void isr_rxne_cb(struct i2c_slave_ctx *ctx) +{ + /* this will clear rxne bit */ + uint8_t data = ctx->reg->rxdr; + + if (ctx->slave && ctx->slave->write) + ctx->slave->write(ctx->slave->priv, data); +} + +void isr_txis_cb(struct i2c_slave_ctx *ctx) +{ + ctx->reg->cr1 &=~CR1_TXIE; /*Disable transmit IT*/ + if (ctx->slave && ctx->slave->read) + ctx->reg->txdr = ctx->slave->read(ctx->slave->priv); + else + ctx->reg->txdr = 0; +} + +void isr_txis_clr(struct i2c_slave_ctx *ctx, struct i2c_isr_op *isr_op) +{ + /* this bit will auto clear when txdr write to some data */ +} + +void isr_stopf_cb(struct i2c_slave_ctx *ctx) +{ + /* This bit can be written to 1 by software in order to flush the + * transmit data register I2C_TXDR. + */ + ctx->reg->isr |= ISR_TXE; + if (ctx->slave && ctx->slave->stop) + ctx->slave->stop(ctx->slave->priv); +} + +void isr_stopf_clr(struct i2c_slave_ctx *ctx, struct i2c_isr_op *isr_op) +{ + ctx->reg->icr |= 1 << isr_op->bit; +} + +static inline struct i2c_slave_op *find_slave(struct i2c_slave_ctx *ctx, + unsigned int addr) +{ + int i; + struct i2c_slave_op *slave; + unsigned int mask; + + for (i = 0; i < ARRAY_SIZE(ctx->slave_list); ++i) { + slave = ctx->slave_list[i]; + if (slave == NULL) + continue; + mask = ~slave->mask; + if ((slave->addr & mask) == (addr & mask)) + return *(ctx->slave_list + i); + } + return NULL; +} + +void isr_addr_cb(struct i2c_slave_ctx *ctx) +{ + unsigned int isr = ctx->reg->isr; + unsigned int addr = (isr & ISR_ADDCODE_MASK) >> ISR_ADDCODE_SHIFT; + unsigned int dir = (isr & ISR_DIR_MASK) >> ISR_DIR_SHIFT; + + ctx->dir = dir; + ctx->slave = find_slave(ctx, addr); + if (ctx->slave) { + if (ctx->slave->match) + ctx->slave->match(ctx->slave->priv, dir); + if (dir == I2C_SLAVE_READ && ctx->slave->read) { + ctx->reg->cr1 |= CR1_TXIE; /*Set transmit IT*/ + ctx->reg->txdr = ctx->slave->read(ctx->slave->priv); + } + } +} + +void isr_addr_clr(struct i2c_slave_ctx *ctx, struct i2c_isr_op *isr_op) +{ + ctx->reg->icr |= 1 << isr_op->bit; +} + +struct i2c_isr_op i2c_isr_table[] = { + {isr_rxne_cb, isr_rxne_clr, 2}, + {isr_txis_cb, isr_txis_clr, 1}, + {isr_stopf_cb, isr_stopf_clr, 5}, + {isr_tcr_cb, isr_tcr_clr, 7}, + {isr_tc_cb, isr_tc_clr, 6}, + {isr_addr_cb, isr_addr_clr, 3}, + {isr_nackf_cb, isr_nackf_clr, 4}, + {isr_berr_cb, isr_berr_clr, 8}, + {isr_arlo_cb, isr_arlo_clr, 9}, + {isr_ovr_cb, isr_ovr_clr, 10}, + {isr_pecerr_cb, isr_pecerr_clr, 11}, + {isr_timeout_cb, isr_timeout_clr, 12}, + {isr_alert_cb, isr_alert_clr, 13}, +}; + +#define ISR_TXE_SHIFT 0 +#define ISR_TXIS_SHIFT 1 +#define ISR_RXNE_SHIFT 2 +#define ISR_ADDR_SHIFT 3 +#define ISR_NACK_SHIFT 4 +#define ISR_STOP_SHIFT 5 + +void i2c_slave_isr(struct i2c_slave_ctx *ctx) +{ + unsigned int old; + unsigned int sts; + int i, j, isr; + int p[6] = { + ISR_TXE_SHIFT, ISR_TXIS_SHIFT, ISR_RXNE_SHIFT, + ISR_NACK_SHIFT, ISR_STOP_SHIFT, ISR_ADDR_SHIFT, + }; + + old = i2c_intr_disable(ctx); + sts = ctx->reg->isr & ctx->isr_irq_mask; + + for (i = 0; i < 6; ++i) { + isr = p[i]; + if ((sts >> isr) & 1) { + for (j = 0; j < ARRAY_SIZE(i2c_isr_table); ++j) { + if (i2c_isr_table[j].bit == isr) { + if (i2c_isr_table[j].cb) + i2c_isr_table[j].cb(ctx); + if (i2c_isr_table[j].clr) + i2c_isr_table[j].clr(ctx, + i2c_isr_table + j); + } + } + } + } + + i2c_intr_restore(ctx, old); +} + +int i2c_slave_init(struct i2c_slave_ctx *ctx, void *reg, + int oa1, int oa2, int oa2mask) +{ + int i; + + ctx->reg = reg; + ctx->isr_irq_mask = 0; + ctx->dir = I2C_SLAVE_WRITE; + /* oa1 enable, 7 bit mode, 7 bit address */ + ctx->reg->oar1 = 0; + if (oa1 > 0) + ctx->reg->oar1 = (1 << 15) | ((oa1 & 0x7f) << 1); + + /* oa2 enable, oa2 address mask, 7 bit address */ + ctx->reg->oar2 = 0; + if (oa2 > 0) + ctx->reg->oar2 = (1 << 15) | ((oa2 & 0x7f) << 1) + | ((oa2mask & 7) << 8); + + for (i = 0; i < ARRAY_SIZE(i2c_isr_table); ++i) + ctx->isr_irq_mask |= (1 << i2c_isr_table[i].bit); + return 0; +} + +int i2c_slave_register(struct i2c_slave_ctx *ctx, struct i2c_slave_op *slave) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(ctx->slave_list); ++i) { + if (ctx->slave_list[i] == NULL) { + ctx->slave_list[i] = slave; + return 0; + } + } + return -1; +} + +int i2c_slave_start(struct i2c_slave_ctx *ctx) +{ + ctx->slave = NULL; + ctx->reg->cr1 |= CR1_PE; + /* enable error, address match, rx and tx isr, stop */ + ctx->reg->cr1 |= CR1_ADDRIE | CR1_RXIE | CR1_TXIE | + CR1_STOPIE | CR1_NACKIE; + return 0; +} + +int i2c_slave_stop(struct i2c_slave_ctx *ctx) +{ + ctx->slave = NULL; + ctx->reg->cr1 &= ~CR1_PE; + /* enable error, address match, rx and tx isr, stop */ + ctx->reg->cr1 &= ~(CR1_ADDRIE | CR1_RXIE | CR1_TXIE | + CR1_STOPIE | CR1_NACKIE); + return 0; +} + +int i2c_slave_reset(struct i2c_slave_ctx *ctx) +{ + struct i2c_slave_op *op; + int i; + + ctx->reg->cr1 &= ~CR1_PE; + + for (i = 0; i < ARRAY_SIZE(ctx->slave_list); ++i) { + op = ctx->slave_list[i]; + if (op && op->reset) + op->reset(op->priv); + } + + ctx->reg->cr1 |= CR1_PE; + return 0; +} + diff --git a/SM7CUSTV1/i2c_slave.h b/SM7CUSTV1/i2c_slave.h new file mode 100644 index 00000000..eb12181e --- /dev/null +++ b/SM7CUSTV1/i2c_slave.h @@ -0,0 +1,43 @@ +#ifndef __I2C_SLAVE_H__ +#define __I2C_SLAVE_H__ + +#include + +#define I2C_SLAVE_MAX (8) + +#define I2C_SLAVE_WRITE (0) +#define I2C_SLAVE_READ (1) + +struct i2c_reg; + +struct i2c_slave_op { + uint8_t addr; + uint8_t mask; + + void (*match)(void *priv, int dir); + uint8_t (*read)(void *priv); + void (*write)(void *priv, uint8_t data); + void (*stop)(void *priv); + void (*nack)(void *priv); + void (*reset)(void *priv); + + void *priv; +}; + +struct i2c_slave_ctx { + int dir; + int id; + unsigned int isr_irq_mask; + volatile struct i2c_reg *reg; + struct i2c_slave_op *slave_list[I2C_SLAVE_MAX]; + struct i2c_slave_op *slave; /* current slave */ +}; + +int i2c_slave_init(struct i2c_slave_ctx *ctx, void *reg, int oa1, int oa2, int oa2mask); +int i2c_slave_register(struct i2c_slave_ctx *ctx, struct i2c_slave_op *slave); +int i2c_slave_start(struct i2c_slave_ctx *ctx); +int i2c_slave_reset(struct i2c_slave_ctx *ctx); +void i2c_slave_isr(struct i2c_slave_ctx *ctx); +int i2c_slave_stop(struct i2c_slave_ctx *ctx); + +#endif diff --git a/SM7CUSTV1/info.h b/SM7CUSTV1/info.h new file mode 100644 index 00000000..5c9fa256 --- /dev/null +++ b/SM7CUSTV1/info.h @@ -0,0 +1,19 @@ +#ifndef __INFO_H__ +#define __INFO_H__ + +#define DATA_EEPROM_BASE (0x08080000) +#define DATA_EEPROM_BANK_SIZE (3 * 1024) +#define DATA_EEPROM_BANK1 (DATA_EEPROM_BASE) +#define DATA_EEPROM_BANK2 (DATA_EEPROM_BANK1 + DATA_EEPROM_BANK_SIZE) + +#define MCU_INFO_CELL_SIZE (32) + +#define MCU_INFO_BASE ((volatile unsigned char *)(DATA_EEPROM_BANK2)) +#define MCU_INFO_MAC0 (MCU_INFO_BASE + MCU_INFO_CELL_SIZE * 0) +#define MCU_INFO_MAC1 (MCU_INFO_BASE + MCU_INFO_CELL_SIZE * 1) +#define MCU_INFO_SN (MCU_INFO_BASE + MCU_INFO_CELL_SIZE * 2) +#define MCU_INFO_PROJ (MCU_INFO_BASE + MCU_INFO_CELL_SIZE * 3) + +extern int stage; + +#endif diff --git a/SM7CUSTV1/loop.c b/SM7CUSTV1/loop.c new file mode 100644 index 00000000..ae3fcbd6 --- /dev/null +++ b/SM7CUSTV1/loop.c @@ -0,0 +1,23 @@ +#include +#include + +static struct loop { + int num; + loop_entry entry[MAIN_LOOP_ENTRY_MAX]; +} loop_ctx; + +void loop_add(loop_entry entry) +{ + loop_ctx.entry[loop_ctx.num] = entry; + ++loop_ctx.num; +} + +void loop_start(void) +{ + int i; + + while (true) { + for (i = 0; i < loop_ctx.num; ++i) + loop_ctx.entry[i](); + } +} diff --git a/SM7CUSTV1/loop.h b/SM7CUSTV1/loop.h new file mode 100644 index 00000000..4f18d866 --- /dev/null +++ b/SM7CUSTV1/loop.h @@ -0,0 +1,10 @@ +#ifndef __LOOP_H__ +#define __LOOP_H__ + +#define MAIN_LOOP_ENTRY_MAX 16 +typedef void (*loop_entry)(void); + +void loop_add(loop_entry entry); +void loop_start(void); + +#endif diff --git a/SM7CUSTV1/main.c b/SM7CUSTV1/main.c new file mode 100644 index 00000000..dba98f5c --- /dev/null +++ b/SM7CUSTV1/main.c @@ -0,0 +1,136 @@ +/** + * @file main.c + * @author chao.wei + * @brief application logical start + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +//#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static struct i2c_slave_ctx i2c1_slave_ctx; +static struct i2c_slave_ctx i2c2_slave_ctx; + +int main(void) +{ + clock_init(); + system_init(); + + debug("\nBITMAIN SOPHON SM7CUSTV1\n"); + timer_udelay(50*1000); + debug("firmware build time:%s-%s\n", __DATE__, __TIME__); + +#ifndef STANDALONE + if (get_stage() == RUN_STAGE_LOADER && check_app() == 0) + app_start(); +#endif + + led_init(); + + i2c_master_init(I2C1); + i2c_master_init(I2C2); + timer_udelay(1000); + + pic_probe(); + + timer_udelay(50*1000); + power_init(); + gpio_set(EN_12V_SYS_PORT, EN_12V_SYS_PIN); + timer_udelay(1000); + mp5475_init(); + power_on(); + chip_init(); + + tca6416a_probe(); + debug("tca6416a:%d \n",tca6416a_available()); + + set_board_type(SM7CUSTV1); + + debug("%s %s working at ", + get_board_type_name(), + get_stage() == RUN_STAGE_LOADER ? "loader" : "application"); + if (get_work_mode() == WORK_MODE_SOC) + debug("soc mode\n"); + else if (get_work_mode() == WORK_MODE_PCIE) + debug("pcie mode\n"); + else if (get_work_mode() == WORK_MODE_MIXED) + debug("mix mode\n"); + else + debug("unkown mode\n"); + + nvic_enable_irq(NVIC_I2C1_IRQ); + i2c_slave_init(&i2c1_slave_ctx, (void *)I2C1_BASE, + I2C1_OA1, I2C1_OA2, I2C1_OA2_MASK); + + mon_init(); + mon_print_init(); + + mcu_init(&i2c1_slave_ctx); + eeprom_init(&i2c1_slave_ctx); + wdt_init(&i2c1_slave_ctx); + slt_init(&i2c1_slave_ctx); + + if (tca6416a_available()) + tca6416a_init(&i2c1_slave_ctx); + + if (pic_available()) { + kbd_init(&i2c1_slave_ctx); + pic_init(&i2c1_slave_ctx); + } + + tmp451_init(&i2c1_slave_ctx); + + /* start i2c slaves */ + i2c_slave_start(&i2c1_slave_ctx); + + if (get_work_mode() == WORK_MODE_SOC) + chip_enable(); + else + pcie_init(); + + sm7_init(); + + rst_key_init(); + console_add(); + /* never return */ + loop_start(); + + return 0; +} + +void i2c1_isr(void) +{ + i2c_slave_isr(&i2c1_slave_ctx); +} + +void i2c2_isr(void) +{ + i2c_slave_isr(&i2c2_slave_ctx); +} diff --git a/SM7CUSTV1/mon.c b/SM7CUSTV1/mon.c new file mode 100644 index 00000000..cb91dcb6 --- /dev/null +++ b/SM7CUSTV1/mon.c @@ -0,0 +1,212 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +/* filter depth 256, acquire interval 10ms + * so current value is an average of past (256 * 10)ms + */ + +/* in ms */ +#define ACQUIRE_INTERVAL 10 + +/* #define FILTER_DISABLE */ + +#define FILTER_DEPTH_SHIFT 8 +#define FILTER_DEPTH (1 << FILTER_DEPTH_SHIFT) +#define FILTER_DEPTH_MASK (FILTER_DEPTH - 1) + +#define PCB_ADC_CHANNEL 0 +#define BOM_ADC_CHANNEL 1 +#define I12V_ADC_CHANNEL 4 +#define NTCTMP_ADC_CHANNEL 6 + +struct filter { + unsigned short data[FILTER_DEPTH]; + unsigned long total; + unsigned long value; + int p; +}; + +static unsigned long filter_init(struct filter *f, unsigned long d) +{ + int i; + + f->p = 0; + f->total = 0; + for (i = 0; i < FILTER_DEPTH; ++i) { + f->data[i] = d; + f->total += d; + } + return d; +} + +static unsigned long filter_in(struct filter *f, unsigned long d) +{ + f->total -= f->data[f->p]; + f->total += d; + f->data[f->p] = d; + f->p = (f->p + 1) & FILTER_DEPTH_MASK; + f->value = f->total >> FILTER_DEPTH_SHIFT; + +#ifdef FILTER_DISABLE + return d; +#else + return f->value; +#endif +} + +static struct filter i12v; +static unsigned int pcb_ver; +static unsigned int bom_ver; +static int ntc_tmp; + +uint16_t get_current(void) +{ + return i12v.value; +} + +uint8_t get_pcb_version(void) +{ + return pcb_ver; +} + +uint8_t get_bom_version(void) +{ + return bom_ver; +} + +uint8_t get_hardware_version(void) +{ + return (pcb_ver << 4) | bom_ver; +} + +static unsigned long adc_read(void) +{ + ADC_CR(ADC1) |= ADC_CR_ADSTART; + /* software triggered, busy status */ + while (ADC_CR(ADC1) & ADC_CR_ADSTART) + ; + + return ADC_DR(ADC1); +} + +/* see config.xlsx, sheet adv2ver */ +const static unsigned short version_table[] = { + 372, 745, 1117, 1489, 1862, 2234, 2607, 2979, 3351, 3724, 4096 +}; + +const static unsigned short tmp_table[] = { + 28,31,34,38,42,46,50,55,60,66,72,78,85,92,100,108,117,126,136, + 147,158,170,183,196,210,225,241,258,276,295,315,336,358,381,405, + 430,456,483,511,540,571,603,636,670,705,741,778,817,857,898,940, + 983,1027,1072,1118,1165,1212,1260,1309,1358,1408,1458,1509,1560, + 1612,1664,1716,1768,1820,1872,1924,1976,2027,2078,2129,2179,2229, + 2278,2327,2375,2422,2469,2515,2560,2604,2647,2690,2732,2773,2813, + 2852,2890,2927,2963,2998,3033,3067,3100,3132,3163,3193,3222,3250, + 3277,3304,3330,3355,3379,3403,3426,3448,3469,3490,3510,3529,3548, + 3566,3583,3600,3616,3632,3647,3662,3676,3690,3703,3716,3728,3740, + 3752,3763,3774,3784,3794,3804,3813,3822,3831,3840,3848,3856,3864, + 3871,3878,3885,3892,3899,3905,3911,3917,3923,3928,3933,3938,3943, + 3948,3953,3958,3962,3966,3970,3974,3978,3982,3986,3989,3992,3995, + 3998,4001,4004,4007,4010 +}; + +static int adc2ver(unsigned short adc) +{ + int i; + for (i = 0; i < ARRAY_SIZE(version_table); ++i) + if (adc < version_table[i]) + return i; + return i; +} + +static uint16_t adc2current(unsigned short adc) +{ + /* step 1: real-voltage = 3.3 * adc / 2^12 /100 + * 3.3v: stm32 vcc + * 100: 100 times op-amp + * 2^12: stm32 ADC resolution 12bit + * step 2: current = real-voltage / 0.005 + * 0.005: 5mO resistor + * step 3: convert ampere to mili-ampere + */ + + /* + *I_12V = (adc * 3.3) / (4096*100*0.005) + */ + return 3300UL * adc / 2048; +} + +static void adc2tmp(unsigned short adc) +{ + int i = 0; + for (i = 0; i < ARRAY_SIZE(tmp_table); ) { + if (adc > tmp_table[i]) + i++; + else + break; + } + + ntc_tmp = i - 50; +} + +int get_ntc_tmp(void) +{ + return ntc_tmp; +} + +static unsigned long current_time; +static unsigned long last_time; + +void mon_process(void) +{ + current_time = tick_get(); + if (current_time - last_time >= ACQUIRE_INTERVAL) { + filter_in(&i12v, adc2current(adc_read())); + last_time = current_time; + } +} + +void mon_init(void) +{ + /* 0: PCB version + * 1: BOM version + * 4: 12V current + * 6: ntc monitor + */ + uint8_t channels[] = {PCB_ADC_CHANNEL, BOM_ADC_CHANNEL,\ + I12V_ADC_CHANNEL, NTCTMP_ADC_CHANNEL}; + + /* init adc and dma */ + adc_power_off(ADC1); + adc_set_clk_source(ADC1, ADC_CFGR2_CKMODE_PCLK_DIV2); + adc_calibrate(ADC1); + adc_set_single_conversion_mode(ADC1); + adc_enable_discontinuous_mode(ADC1); + adc_set_right_aligned(ADC1); + adc_set_resolution(ADC1, 0); + adc_set_regular_sequence(ADC1, ARRAY_SIZE(channels), channels); + /* set conversion speed to fastest */ + adc_set_sample_time_on_all_channels(ADC1, ADC_SMPTIME_160DOT5); + adc_power_on(ADC1); + + pcb_ver = adc2ver(adc_read()); + bom_ver = adc2ver(adc_read()); + + last_time = tick_get(); + filter_init(&i12v, adc_read()); + + adc2tmp(adc_read()); + + /* donnot get version again */ + channels[0] = I12V_ADC_CHANNEL; + adc_set_regular_sequence(ADC1, 1, channels); + + loop_add(mon_process); +} + diff --git a/SM7CUSTV1/mon.h b/SM7CUSTV1/mon.h new file mode 100644 index 00000000..3064aa85 --- /dev/null +++ b/SM7CUSTV1/mon.h @@ -0,0 +1,12 @@ +#ifndef __MON_H__ +#define __MON_H__ + +void mon_init(void); +void mon_process(void); +uint16_t get_current(void); +uint8_t get_pcb_version(void); +uint8_t get_bom_version(void); +uint8_t get_hardware_version(void); +int get_ntc_tmp(void); + +#endif diff --git a/SM7CUSTV1/mon_print.c b/SM7CUSTV1/mon_print.c new file mode 100644 index 00000000..5e7880f3 --- /dev/null +++ b/SM7CUSTV1/mon_print.c @@ -0,0 +1,35 @@ +#include +#include +#include +#include +#include +#include +#include +static int mon_print_handle; + +void mon_print_fun(void) +{ + printf("board tmp = %d(C), soc tmp = %d(C), i12v = %d(mA)\n",\ + get_board_temp(), get_soc_temp(), get_current()); + + for (int i = 0; i < 4; i++){ + printf("buck%c:%lu(mV) ", 'A' + i, mp5475_output_voltage(i)); + } + + printf("mp5475 tmp = %d(C)\n", mp5475_get_tmp()); +} + +void mon_print_init(void) +{ + mon_print_handle = tick_register_task(mon_print_fun, 0); + if (mon_print_handle == -1) + debug("mon print task register failed\n"); +} + +void enable_mon_print_task(int second) +{ + if (second == 0) + tick_set_task_interval(mon_print_handle, 60000); + else + tick_set_task_interval(mon_print_handle, second*1000); +} diff --git a/SM7CUSTV1/mon_print.h b/SM7CUSTV1/mon_print.h new file mode 100644 index 00000000..b9340839 --- /dev/null +++ b/SM7CUSTV1/mon_print.h @@ -0,0 +1,8 @@ +#ifndef __MON_PRINT_H__ +#define __MON_PRINT_H__ + +void enable_mon_print_task(int second); +void mon_print_init(void); +void mon_print_fun(void); + +#endif \ No newline at end of file diff --git a/SM7CUSTV1/mp5475.c b/SM7CUSTV1/mp5475.c new file mode 100644 index 00000000..59b6f8c1 --- /dev/null +++ b/SM7CUSTV1/mp5475.c @@ -0,0 +1,93 @@ +#include +#include +#include +#include + +#define MP5475_SLAVE_ADDR 0x60 +#define I2C I2C2 + +#define MP5475_ENABLE_REG_DEFAULT_VALUE (1 << 7 | 1 << 5) +#define MP5475_TMP_REG 0x57 + +static uint8_t mp5475_enable_reg_value = MP5475_ENABLE_REG_DEFAULT_VALUE; + +static inline int mp5475_read_byte(unsigned char cmd) +{ + unsigned char tmp; + while (i2c_master_smbus_read_byte(I2C, MP5475_SLAVE_ADDR, + 1, cmd, &tmp)); + ; + return tmp; +} + +static inline int mp5475_write_byte(unsigned char cmd, + unsigned char data) +{ + while (i2c_master_smbus_write_byte(I2C, MP5475_SLAVE_ADDR, + 1, cmd, data)); + ; + return 0; +} + +int mp5475_buck_on(unsigned int buck) +{ + mp5475_enable_reg_value |= (1 << 5) >> buck; + mp5475_write_byte(0x40, mp5475_enable_reg_value); + return 0; +} + +void mp5475_buck_off(unsigned int buck) +{ +#ifdef CLOSEPMIC + mp5475_enable_reg_value &= ~((1 << 5) >> buck); + mp5475_write_byte(0x40, mp5475_enable_reg_value); +#endif +} + +int mp5475_voltage_config(unsigned int buck, unsigned int voltage) +{ + unsigned int reg_h = 0x13 + 8 * buck; + unsigned int reg_l = 0x14 + 8 * buck; + unsigned int value = voltage / 2; + unsigned int val_h = (value >> 8) & 0x03; + unsigned int val_l = value & 0xff; + + mp5475_write_byte(reg_h, val_h); + mp5475_write_byte(reg_l, val_l); + return 0; +} + +unsigned long mp5475_output_current(unsigned int buck) +{ + unsigned int reg = 0x59 + 2 * buck; + + return mp5475_read_byte(reg) * 50; +} + +unsigned long mp5475_output_voltage(unsigned int buck) +{ + unsigned int reg = 0x5a + 2 * buck; + + return mp5475_read_byte(reg) * 25; +} + +int mp5475_get_tmp(void) +{ + return mp5475_read_byte(MP5475_TMP_REG) - 50; +} + +int mp5475_init(void) +{ + /* enable system enable, disable buck 1, 2, 3, 4 */ + mp5475_write_byte(0x40, mp5475_enable_reg_value); + mp5475_voltage_config(0, 1800); + mp5475_voltage_config(1, 1100); + mp5475_voltage_config(2, 600); + mp5475_voltage_config(3, 810); + return 0; +} + +void mp5475_destroy(void) +{ +} + diff --git a/SM7CUSTV1/mp5475.h b/SM7CUSTV1/mp5475.h new file mode 100644 index 00000000..9af6dca0 --- /dev/null +++ b/SM7CUSTV1/mp5475.h @@ -0,0 +1,13 @@ +#ifndef __MP5475_H__ +#define __MP5475_H__ + +int mp5475_init(void); +void mp5475_destroy(void); +int mp5475_buck_on(unsigned int buck); +void mp5475_buck_off(unsigned int buck); +int mp5475_voltage_config(unsigned int buck, unsigned int voltage); +unsigned long mp5475_output_current(unsigned int buck); +unsigned long mp5475_output_voltage(unsigned int buck); +int mp5475_get_tmp(void); + +#endif diff --git a/SM7CUSTV1/pcie.c b/SM7CUSTV1/pcie.c new file mode 100644 index 00000000..03570458 --- /dev/null +++ b/SM7CUSTV1/pcie.c @@ -0,0 +1,89 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +static volatile int is_chip_ready; +static int pcie_task; + +/* practical value, 2048 cycle used 1.2ms */ +#define DEBOUNCE_COUNT 512 + +void pcie_reset_isr(void) +{ + unsigned int i; + unsigned int hi = 0; + unsigned int lo = 0; + + for (i = 0; i < DEBOUNCE_COUNT; ++i) { + if (gpio_get(PCIE_RESET_PORT, PCIE_RESET_PIN)) + ++hi; + else + ++lo; + } + + if (hi > lo) { + if (is_chip_ready) + chip_enable(); + debug("pcie e-reset raising edge\n"); + } else { + is_chip_ready = false; + chip_disable(); + tick_set_task_interval(pcie_task, 30); + wdt_reset(); + debug("pcie e-reset falling edge\n"); + } + + exti_reset_request(PCIE_RESET_EXTI); +} + +void exti4_15_isr(void) +{ + if (exti_get_flag_status(PCIE_RESET_EXTI)) + pcie_reset_isr(); + + if (exti_get_flag_status(RESET_KEY_EXTI)) + rst_key_isr(); +} + +static void pcie_process(void) +{ + /* one shot task */ + tick_set_task_interval(pcie_task, 0); + is_chip_ready = true; + if (gpio_get(PCIE_RESET_PORT, PCIE_RESET_PIN)) + chip_enable(); +} + +void pcie_init(void) +{ + is_chip_ready = true; + exti_select_source(PCIE_RESET_EXTI, PCIE_RESET_PORT); + exti_set_trigger(PCIE_RESET_EXTI, EXTI_TRIGGER_BOTH); + exti_enable_request(PCIE_RESET_EXTI); + nvic_enable_irq(PCIE_RESET_NVIC); + + if (gpio_get(PCIE_RESET_PORT, PCIE_RESET_PIN)) + chip_enable(); + + pcie_task = tick_register_task(pcie_process, 0); +} + +void pcie_destroy(void) +{ + nvic_disable_irq(PCIE_RESET_NVIC); + nvic_clear_pending_irq(PCIE_RESET_NVIC); + exti_disable_request(PCIE_RESET_EXTI); + exti_reset_request(PCIE_RESET_EXTI); + is_chip_ready = 0; +} + +void set_chip_states(int state) +{ + is_chip_ready = state; +} diff --git a/SM7CUSTV1/pcie.h b/SM7CUSTV1/pcie.h new file mode 100644 index 00000000..523d25a0 --- /dev/null +++ b/SM7CUSTV1/pcie.h @@ -0,0 +1,8 @@ +#ifndef __PCIE_H__ +#define __PCIE_H__ + +void pcie_init(void); +void pcie_destroy(void); +void set_chip_states(int state); + +#endif diff --git a/SM7CUSTV1/pin.c b/SM7CUSTV1/pin.c new file mode 100644 index 00000000..54f6302c --- /dev/null +++ b/SM7CUSTV1/pin.c @@ -0,0 +1,140 @@ +/* THIS IS AUTO GENERATED CODE */ + +#include + +void pin_init(void) +{ + /* port A configuration */ + /* output data, default output state */ + GPIO_ODR(GPIOA) = 0; + /* output type, push-pull or open-drain */ + GPIO_OTYPER(GPIOA) = 0; + /* output speed, low, medium, high, very high */ + // PA8 PA9 PA10 PA11 PA12 PA15 config Low speed --> PA7 8 9 12 + GPIO_OSPEEDR(GPIOA) = + (GPIO_OSPEEDR(GPIOA) & ~0x030fc000) | (GPIO_OSPEED_LOW << (7 * 2)) | + (GPIO_OSPEED_LOW << (8 * 2)) | (GPIO_OSPEED_LOW << (9 * 2)) | + (GPIO_OSPEED_LOW << (12 * 2)); + + /* pull-up pull-down */ + // PA0 PA1 PA2 PA3 PA4 PA5 PA6 No pull-up --> PA0 PA1 PA2 PA3 7 + // PA8 PA9 PA10 PA11 PA12 PA15 Pull-down --> PA5 8 9 11 12 15 + GPIO_PUPDR(GPIOA) = + (GPIO_PUPDR(GPIOA) & ~0xc0fffcff) | (GPIO_PUPD_NONE << (0 * 2)) | + (GPIO_PUPD_NONE << (1 * 2)) | (GPIO_PUPD_NONE << (2 * 2)) | + (GPIO_PUPD_NONE << (3 * 2)) | (GPIO_PUPD_NONE << (5 * 2)) | + (GPIO_PUPD_NONE << (7 * 2)) | (GPIO_PUPD_PULLDOWN << (8 * 2)) | + (GPIO_PUPD_PULLDOWN << (9 * 2)) | (GPIO_PUPD_NONE << (10 * 2)) | + (GPIO_PUPD_NONE << (11 * 2))| (GPIO_PUPD_PULLDOWN << (12 * 2)) | + (GPIO_PUPD_PULLUP << (15 * 2)); + /* af, alternative function selection */ + // PA2 PA3 enable AF4 + GPIO_AFRL(GPIOA) = + (GPIO_AFRL(GPIOA) & ~0x0000ff00) | (GPIO_AF4 << (2 * 4)) | + (GPIO_AF4 << (3 * 4)); + /* AFRH reset state */ + /* mode, input, output, alternate function or analog */ + // Analog mode: PA0 PA1 PA4 PA6 --> PA0 1 + // Alternate function mode: PA2 PA3 --> NO CHANGE + // Input mode: PA5 PA7 PA11 --> PA5 PA7 10 11 15 + // output mode: PA8 PA9 PA10 PA12 PA15 --> PA 8 9 12 + GPIO_MODER(GPIOA) = + (GPIO_MODER(GPIOA) & ~0xc3fff3ff) | (GPIO_MODE_ANALOG << (0 * 2)) | + (GPIO_MODE_ANALOG << (1 * 2)) | (GPIO_MODE_AF << (2 * 2)) | + (GPIO_MODE_AF << (3 * 2)) | (GPIO_MODE_INPUT << (5 * 2)) | + (GPIO_MODE_INPUT << (7 * 2)) | (GPIO_MODE_OUTPUT << (8 * 2)) | + (GPIO_MODE_OUTPUT << (9 * 2)) | (GPIO_MODE_INPUT << (10 * 2)) | + (GPIO_MODE_INPUT << (11 * 2)) | (GPIO_MODE_OUTPUT << (12 * 2)) | + (GPIO_MODE_INPUT << (15 * 2)); + + /* port B configuration */ + /* output data, default output state */ + GPIO_ODR(GPIOB) = 0; + /* output type, push-pull or open-drain */ + GPIO_OTYPER(GPIOB) = + (GPIO_OTYPE_OD << 6) | (GPIO_OTYPE_OD << 7) | (GPIO_OTYPE_OD << 10) + | (GPIO_OTYPE_OD << 11); + /* output speed, low, medium, high, very high */ + GPIO_OSPEEDR(GPIOB) = + (GPIO_OSPEEDR(GPIOB) & ~0x0ffcffff) | (GPIO_OSPEED_LOW << (0 * 2)) | + (GPIO_OSPEED_LOW << (1 * 2)) | (GPIO_OSPEED_LOW << (2 * 2)) | + (GPIO_OSPEED_LOW << (3 * 2)) | (GPIO_OSPEED_LOW << (4 * 2)) | + (GPIO_OSPEED_LOW << (5 * 2)) | (GPIO_OSPEED_HIGH << (6 * 2)) | + (GPIO_OSPEED_HIGH << (7 * 2)) | (GPIO_OSPEED_LOW << (9 * 2)) | + (GPIO_OSPEED_HIGH << (10 * 2)) | (GPIO_OSPEED_HIGH << (11 * 2)) | + (GPIO_OSPEED_LOW << (12 * 2)) | (GPIO_OSPEED_LOW << (13 * 2)); + /* pull-up pull-down */ + GPIO_PUPDR(GPIOB) = + (GPIO_PUPDR(GPIOB) & ~0xffffffff) | (GPIO_PUPD_PULLDOWN << (0 * 2)) + | (GPIO_PUPD_PULLDOWN << (1 * 2)) | (GPIO_PUPD_NONE << (2 * 2)) + | (GPIO_PUPD_NONE << (3 * 2)) | (GPIO_PUPD_PULLDOWN << (4 * 2)) + | (GPIO_PUPD_PULLDOWN << (5 * 2)) | (GPIO_PUPD_NONE << (6 * 2)) | + (GPIO_PUPD_NONE << (7 * 2)) | (GPIO_PUPD_NONE << (8 * 2)) | + (GPIO_PUPD_PULLDOWN << (9 * 2)) | (GPIO_PUPD_NONE << (10 * 2)) | + (GPIO_PUPD_NONE << (11 * 2)) | (GPIO_PUPD_NONE << (12 * 2)) | + (GPIO_PUPD_PULLUP << (13 * 2)) | (GPIO_PUPD_PULLUP << (14 * 2)) | + (GPIO_PUPD_PULLUP << (15 * 2)); + /* af, alternative function selection */ + GPIO_AFRL(GPIOB) = + (GPIO_AFRL(GPIOB) & ~0xff000000) | (GPIO_AF1 << (6 * 4)) | + (GPIO_AF1 << (7 * 4)); + GPIO_AFRH(GPIOB) = + (GPIO_AFRH(GPIOB) & ~0x0000ff00) | (GPIO_AF6 << ((10 - 8) * 4)) | + (GPIO_AF6 << ((11 - 8) * 4)); + /* mode, input, output, alternate function or analog */ + // GPIO_MODE_INPUT: PB8 12 15 --> PB2 3 12 15(INT) + // GPIO_MODE_OUTPUT: PB0 1 2 3 4 5 9 13 14 --> PB0 1 4 5 9 13 + // GPIO_MODE_AF: PB6 7 10 11 --> NO CHANGE + GPIO_MODER(GPIOB) = + (GPIO_MODER(GPIOB) & ~0xcffcffff) | (GPIO_MODE_OUTPUT << (0 * 2)) | + (GPIO_MODE_OUTPUT << (1 * 2)) | (GPIO_MODE_INPUT << (2 * 2)) | + (GPIO_MODE_INPUT << (3 * 2)) | (GPIO_MODE_OUTPUT << (4 * 2)) | + (GPIO_MODE_OUTPUT << (5 * 2)) | (GPIO_MODE_AF << (6 * 2)) | + (GPIO_MODE_AF << (7 * 2)) | (GPIO_MODE_OUTPUT << (9 * 2)) | + (GPIO_MODE_AF << (10 * 2)) | (GPIO_MODE_AF << (11 * 2)) | + (GPIO_MODE_INPUT << (12 * 2)) | (GPIO_MODE_OUTPUT << (13 * 2)) | + (GPIO_MODE_INPUT << (15 * 2)); + + /* port C configuration */ + /* output data, default output state */ + GPIO_ODR(GPIOC) = 0; + /* output type, push-pull or open-drain */ + GPIO_OTYPER(GPIOC) = 0; + /* output speed, low, medium, high, very high */ + GPIO_OSPEEDR(GPIOC) = + (GPIO_OSPEEDR(GPIOC) & ~0xfc000000) | (GPIO_OSPEED_LOW << (13 * 2)) + | (GPIO_OSPEED_LOW << (14 * 2)) | (GPIO_OSPEED_LOW << (15 * 2)); + /* pull-up pull-down */ + GPIO_PUPDR(GPIOC) = + (GPIO_PUPDR(GPIOC) & ~0xfc000000) | (GPIO_PUPD_NONE << (13 * 2)) | + (GPIO_PUPD_NONE << (14 * 2)) | (GPIO_PUPD_NONE << (15 * 2)); + /* af, alternative function selection */ + /* AFRL reset state */ + /* AFRH reset state */ + /* mode, input, output, alternate function or analog */ + GPIO_MODER(GPIOC) = + (GPIO_MODER(GPIOC) & ~0xfc000000) | (GPIO_MODE_OUTPUT << (13 * 2)) | + (GPIO_MODE_OUTPUT << (14 * 2)) | (GPIO_MODE_INPUT << (15 * 2)); + + /* port H configuration */ + /* output data, default output state */ + GPIO_ODR(GPIOH) = 0; + /* output type, push-pull or open-drain */ + GPIO_OTYPER(GPIOH) = 0; + /* output speed, low, medium, high, very high */ + /* reset state */ + /* pull-up pull-down */ + GPIO_PUPDR(GPIOH) = + (GPIO_PUPDR(GPIOH) & ~0x0000000f) | (GPIO_PUPD_NONE << (0 * 2)) | + (GPIO_PUPD_NONE << (1 * 2)); + /* af, alternative function selection */ + /* AFRL reset state */ + /* AFRH reset state */ + /* mode, input, output, alternate function or analog */ + GPIO_MODER(GPIOH) = + (GPIO_MODER(GPIOH) & ~0x0000000f) | (GPIO_MODE_INPUT << (0 * 2)) | + (GPIO_MODE_INPUT << (1 * 2)); + +} + +/* AUTO GENERATED CODE END */ diff --git a/SM7CUSTV1/pin.h b/SM7CUSTV1/pin.h new file mode 100644 index 00000000..fc8ea80a --- /dev/null +++ b/SM7CUSTV1/pin.h @@ -0,0 +1,150 @@ +/* THIS IS AUTO GENERATED CODE */ + +#ifndef __PIN_H__ +#define __PIN_H__ + +#include +#include + +/* port A definition */ +#define PCB_VER0_PORT GPIOA +#define PCB_VER0_PIN GPIO0 +#define PCB_VER0_EXTI EXTI0 +#define BOM_VER0_PORT GPIOA +#define BOM_VER0_PIN GPIO1 +#define BOM_VER0_EXTI EXTI1 +#define MCU_UART1_TX_PORT GPIOA +#define MCU_UART1_TX_PIN GPIO2 +#define MCU_UART1_TX_EXTI EXTI2 +#define MCU_UART1_RX_PORT GPIOA +#define MCU_UART1_RX_PIN GPIO3 +#define MCU_UART1_RX_EXTI EXTI3 +//#define CURRENT_IN_PORT GPIOA +//#define CURRENT_IN_PIN GPIO4 +//#define CURRENT_IN_EXTI EXTI4 +#define PG_VDD_TPU_PORT GPIOA +#define PG_VDD_TPU_PIN GPIO5 +#define PG_VDD_TPU_EXTI EXTI5 +//#define NTC_MON_PORT GPIOA +//#define NTC_MON_PIN GPIO6 +//#define NTC_MON_EXTI EXTI6 +#define PCIEE_RST_MCU_PORT GPIOA +#define PCIEE_RST_MCU_PIN GPIO7 +#define PCIEE_RST_MCU_EXTI EXTI7 +#define STATUS_LED1_PORT GPIOA +#define STATUS_LED1_PIN GPIO8 +#define STATUS_LED1_EXTI EXTI8 +#define EN_VQPS18_PORT GPIOA +#define EN_VQPS18_PIN GPIO9 +#define EN_VQPS18_EXTI EXTI9 +#define P08_PWR_GOOD_PORT GPIOA +#define P08_PWR_GOOD_PIN GPIO10 +#define P08_PWR_GOOD_EXTI EXTI10 + +#define MCU_INT_PORT GPIOA +#define MCU_INT_PIN GPIO11 +#define MCU_INT_EXTI EXTI11 +//#define GPIO1_MCU_PORT GPIOA +//#define GPIO1_MCU_PIN GPIO11 +//#define GPIO1_MCU_EXTI EXTI11 + +#define SYS_RST_X_PORT GPIOA +#define SYS_RST_X_PIN GPIO12 +#define SYS_RST_X_EXTI EXTI12 +#define SWDIO_PORT GPIOA +#define SWDIO_PIN GPIO13 +#define SWDIO_EXTI EXTI13 +#define SWDCLK_PORT GPIOA +#define SWDCLK_PIN GPIO14 +#define SWDCLK_EXTI EXTI14 + +//#define DDR_PWR_GOOD_PORT GPIOA +//#define DDR_PWR_GOOD_PIN GPIO15 +//#define DDR_PWR_GOOD_EXTI EXTI15 +#define DDR_PG_MCU_PORT GPIOA +#define DDR_PG_MCU_PIN GPIO15 +#define DDR_PG_MCU_EXTI EXTI15 + + +/* port B definition */ +#define EN_VDDIO33_PORT GPIOB +#define EN_VDDIO33_PIN GPIO0 +#define EN_VDDIO33_EXTI EXTI0 +#define EN_VDD_PCIE_VP_PORT GPIOB +#define EN_VDD_PCIE_VP_PIN GPIO1 +#define EN_VDD_PCIE_VP_EXTI EXTI1 +#define GPIO2_PORT GPIOB +#define GPIO2_PIN GPIO2 +#define GPIO2_EXTI EXTI2 +#define GPIO3_PORT GPIOB +#define GPIO3_PIN GPIO3 +#define GPIO3_EXTI EXTI3 +#define EN_VDDIO18_PORT GPIOB +#define EN_VDDIO18_PIN GPIO4 +#define EN_VDDIO18_EXTI EXTI4 +#define EN_VDD_TPU_PORT GPIOB +#define EN_VDD_TPU_PIN GPIO5 +#define EN_VDD_TPU_EXTI EXTI5 +#define I2C1_SCL_PORT GPIOB +#define I2C1_SCL_PIN GPIO6 +#define I2C1_SCL_EXTI EXTI6 +#define I2C1_SDA_PORT GPIOB +#define I2C1_SDA_PIN GPIO7 +#define I2C1_SDA_EXTI EXTI7 +//#define PG_3P3V_PORT GPIOB +//#define PG_3P3V_PIN GPIO8 +//#define PG_3P3V_EXTI EXTI8 +#define EN_VDDC_PORT GPIOB +#define EN_VDDC_PIN GPIO9 +#define EN_VDDC_EXTI EXTI9 +#define PMIC_SCL_PORT GPIOB +#define PMIC_SCL_PIN GPIO10 +#define PMIC_SCL_EXTI EXTI10 +#define PMIC_SDA_PORT GPIOB +#define PMIC_SDA_PIN GPIO11 +#define PMIC_SDA_EXTI EXTI11 +#define RESET_KEY_PORT GPIOB +#define RESET_KEY_PIN GPIO12 +#define RESET_KEY_EXTI EXTI12 +#define EN_12V_SYS_PORT GPIOB +#define EN_12V_SYS_PIN GPIO13 +#define EN_12V_SYS_EXTI EXTI13 +//#define EN_VDD_PHY_PORT GPIOB +//#define EN_VDD_PHY_PIN GPIO14 +//#define EN_VDD_PHY_EXTI EXTI14 + +//#define PMEB_PORT GPIOB +//#define PMEB_PIN GPIO15 +//#define PMEB_EXTI EXTI15 +#define MCU_TCA6416_INT_PORT GPIOB +#define MCU_TCA6416_INT_PIN GPIO15 +#define MCU_TCA6416_INT_EXTI EXTI15 + + +/* port C definition */ +//#define MCU_LED_PORT GPIOC +//#define MCU_LED_PIN GPIO13 +//#define MCU_LED_EXTI EXTI13 +#define STATUS_LED0_PORT GPIOC +#define STATUS_LED0_PIN GPIO13 +#define STATUS_LED0_EXTI EXTI13 + +#define VDDC_SEL_PORT GPIOC +#define VDDC_SEL_PIN GPIO14 +#define VDDC_SEL_EXTI EXTI14 +#define PG_VDDC_PORT GPIOC +#define PG_VDDC_PIN GPIO15 +#define PG_VDDC_EXTI EXTI15 + +/* port H definition */ +#define PMIC_INT_PORT GPIOH +#define PMIC_INT_PIN GPIO0 +#define PMIC_INT_EXTI EXTI0 +#define PG_VDD_PHY_PORT GPIOH +#define PG_VDD_PHY_PIN GPIO1 +#define PG_VDD_PHY_EXTI EXTI1 + +void pin_init(void); + +#endif +/* AUTO GENERATED CODE END */ diff --git a/SM7CUSTV1/power.c b/SM7CUSTV1/power.c new file mode 100644 index 00000000..f4da55c8 --- /dev/null +++ b/SM7CUSTV1/power.c @@ -0,0 +1,224 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/* in us */ +#define NODE_CHECK_TIMEOUT 4000 + +static int node_check(struct power_node const *node) +{ + int err = 0; + uint32_t port = node->param[0]; + uint16_t pin = node->param[1]; + + timer_start(NODE_CHECK_TIMEOUT); + + while (gpio_get(port, pin) == 0) { + if (timer_is_timeout()) { + err = -1; + break; + } + } + timer_stop(); + + return err; +} + +static int node_on(struct power_node *node) +{ + int err = 0; + + debug("%s ", node->name); + + if (node->type == NODE_TYPE_ENABLE) { + gpio_set(node->param[0], node->param[1]); + } else if (node->type == NODE_TYPE_CHECK) { + err = node_check(node); + } else { + power_on_func func = (power_on_func)node->param[0]; + if (func) + err = func(); + } + + debug("[%c]\n", err ? 'X' : 'O'); + + if (err) { + node->status = POWER_STATUS_ERR; + } else { + node->status = POWER_STATUS_ON; + if (node->delay) + timer_udelay(node->delay); + } + + return err; +} + +static void node_off(struct power_node *node) +{ + debug("%s\n", node->name); + + if (!strcmp(node->name, "VDD-1.8V")) { + printf("not cler %s\n", node->name); + return; + } + + if (!strcmp(node->name, "EN_12V_SYS")) { + printf("not cler %s\n", node->name); + return; + } + + + /* skip check nodes */ + if (node->type == NODE_TYPE_ENABLE) { + gpio_clear(node->param[0], node->param[1]); + } else if (node->type == NODE_TYPE_FUNCTION) { + power_off_func func = (power_off_func)node->param[1]; + if (func) + func(); + } + node->status = POWER_STATUS_OFF; +} + +int node_seqon(struct power_node *node, unsigned int num) +{ + int err, i; + + err = 0; + + for (i = 0; i < num; ++i) { + err = node_on(node + i); + if (err) + break; + } + + /* donot power off */ +#if 0 + if (err) { + --i; + while (i >= 0) { + node_off(node + i); + --i; + } + } +#endif + return err; +} + +void node_seqoff(struct power_node *node, unsigned int num) +{ + int i; + + for (i = num - 1; i >= 0; --i) + node_off(node + i); +} + +int power_on(void) +{ + int err = node_seqon(board_power_nodes, ARRAY_SIZE(board_power_nodes)); + + if (err) { + led_set_frequency(5); + } else { + led_set_frequency(1); + } + + return err; +} + +void power_off(void) +{ + node_seqoff(board_power_nodes, ARRAY_SIZE(board_power_nodes)); + led_set_frequency(LED_FREQ_ALWAYS_OFF); +} + +void power_init(void) +{ + led_set_frequency(LED_FREQ_ALWAYS_OFF); +} + +int power_node_on(const char *name) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(board_power_nodes); i++) { + if (!strcmp((board_power_nodes + i)->name, name)) + return node_on(board_power_nodes + i); + } + + return -1; +} + +int power_nodes_on(const char **name, int num) +{ + int i; + + for (i = 0; i < num; i++) { + if (power_node_on(name[i])) + return -1; + } + + return 0; +} + +void power_node_off(const char *name) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(board_power_nodes); i++) { + if (!strcmp((board_power_nodes + i)->name, name)) + return node_off(board_power_nodes + i); + } +} + +void power_nodes_off(const char **name, int num) +{ + int i; + + for (i = 0; i < num; i++) + power_node_off(name[i]); +} + +int power_node_status(const char *name) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(board_power_nodes); i++) { + if (!strcmp((board_power_nodes + i)->name, name)) + return (board_power_nodes + i)->status; + } + + return -1; +} + +int power_nodes_status(const char **name, int num) +{ + int i; + + for (i = 0; i < num; i++) { + if (power_node_status(name[i]) != POWER_STATUS_ON) + return POWER_STATUS_OFF; + } + + return POWER_STATUS_ON; +} + +int cmd_get_node_status() +{ + int i = 0; + + for (i = 0; i < ARRAY_SIZE(board_power_nodes); i++){ + uart_puts((board_power_nodes + i)->name); + if ((board_power_nodes+i)->status == POWER_STATUS_ON) + uart_puts(" [O]\n"); + else + uart_puts(" [X]\n"); + } + + return 0; +} diff --git a/SM7CUSTV1/power.h b/SM7CUSTV1/power.h new file mode 100644 index 00000000..232b6bbe --- /dev/null +++ b/SM7CUSTV1/power.h @@ -0,0 +1,39 @@ +#ifndef __POWER_H__ +#define __POWER_H__ + +enum { + NODE_TYPE_ENABLE, + NODE_TYPE_CHECK, + NODE_TYPE_FUNCTION, + NODE_TYPE_INVALID, +}; + +enum { + POWER_STATUS_OFF, + POWER_STATUS_ON, + POWER_STATUS_ERR, +}; + +struct power_node { + char *name; + int type; + int status; + unsigned int delay; + unsigned long param[2]; +}; + +typedef int (*power_on_func)(void); +typedef int (*power_off_func)(void); + +void power_init(void); +int power_on(void); +void power_off(void); +int power_node_on(const char *name); +int power_nodes_on(const char **name, int num); +void power_node_off(const char *name); +void power_nodes_off(const char **name, int num); +int power_node_status(const char *name); +int power_nodes_status(const char **name, int num); +int cmd_get_node_status(); + +#endif diff --git a/SM7CUSTV1/project.h b/SM7CUSTV1/project.h new file mode 100644 index 00000000..9a36e03a --- /dev/null +++ b/SM7CUSTV1/project.h @@ -0,0 +1,21 @@ +#ifndef __PROJECT_H__ +#define __PROJECT_H__ + +#define EVB 0 +#define SA5 1 +#define SC5 2 +#define SE5 3 +#define SM5P 4 +#define SM5S 5 +#define SA6 6 + +#define SC5PLUS 7 +#define SC5H 8 +#define SC5PRO 9 +#define SM5ME 10 +#define SM5MP 11 +#define SM5MS 12 +#define SM5MA 13 + +#define SM7CUSTV1 0x3a +#endif diff --git a/SM7CUSTV1/rst_key.c b/SM7CUSTV1/rst_key.c new file mode 100644 index 00000000..54ee3acf --- /dev/null +++ b/SM7CUSTV1/rst_key.c @@ -0,0 +1,46 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define DEBOUNCE_COUNT 512 + +void rst_key_init(void) +{ + exti_select_source(RESET_KEY_EXTI, RESET_KEY_PORT); + exti_set_trigger(RESET_KEY_EXTI, EXTI_TRIGGER_BOTH); + exti_enable_request(RESET_KEY_EXTI); + nvic_enable_irq(RST_KEY_NVIC); +} + +void rst_key_isr(void) +{ + unsigned int i; + unsigned int hi = 0; + unsigned int lo = 0; + + for (i = 0; i < DEBOUNCE_COUNT; ++i) { + if (gpio_get(RESET_KEY_PORT, RESET_KEY_PIN)) + ++hi; + else + ++lo; + } + + if (hi > lo) { + set_chip_states(true); + chip_enable(); + debug("rst key gpio level high\n"); + } else { + set_chip_states(false); + chip_disable(); + wdt_reset(); + debug("rst key gpio level low\n"); + } + + exti_reset_request(RESET_KEY_EXTI); +} diff --git a/SM7CUSTV1/rst_key.h b/SM7CUSTV1/rst_key.h new file mode 100644 index 00000000..34c3736d --- /dev/null +++ b/SM7CUSTV1/rst_key.h @@ -0,0 +1,9 @@ +#ifndef __RST_KEY___ +#define __RST_KEY__ + +#define RST_KEY_NVIC NVIC_EXTI4_15_IRQ + +void rst_key_init(void); +void rst_key_isr(void); + +#endif \ No newline at end of file diff --git a/SM7CUSTV1/sm7.c b/SM7CUSTV1/sm7.c new file mode 100644 index 00000000..5c489cd8 --- /dev/null +++ b/SM7CUSTV1/sm7.c @@ -0,0 +1,174 @@ +#include +#include +#include +#include +#include +#include +#include +#include + +/* count in ms */ +#define SM7_POWER_OFF_DELAY 3000 +#define SM7_POWER_ON_DELAY 500 + +/* gpio expandtion(tca6416a) config */ +/* port 0 */ + +#define POWER_ENABLE_PORT 0 +#define POWER_ENABLE_PIN 0 +#define POWER_ENABLE_DEFAULT 0 + +#define WIFI_RST_PORT 0 +#define WIFI_RST_PIN 1 +#define WIFI_RST_DEFAULT 1 + + +#define LED1_PORT 0 +#define LED1_PIN 3 +#define LED1_DEFAULT 1 + +#define LED2_PORT 0 +#define LED2_PIN 4 +#define LED2_DEFAULT 0 + +#define LTE_RST_PORT 0 +#define LTE_RST_PIN 7 +#define LTE_RST_DEFAULT 0 + +/* input */ +#define POWER_BUTTON_PORT 0 +#define POWER_BUTTON_PIN 5 + +#define P0_CFG (1 << POWER_BUTTON_PIN) +#define P0_OUT ((POWER_ENABLE_DEFAULT << POWER_ENABLE_PIN) | \ + (LED1_DEFAULT << LED1_PIN) | (LED2_DEFAULT << LED2_PIN) | \ + (WIFI_RST_DEFAULT << WIFI_RST_PIN) | (LTE_RST_DEFAULT << LTE_RST_PIN)) +#define P0_POL 0 + + +/* port 1 */ +#define LTE_ENABLE_PORT 1 +#define LTE_ENABLE_PIN 0 +#define LTE_ENABLE_DEFAULT 1 + +/* input */ +#define POWER_STATUS_PORT 1 +#define POWER_STATUS_PIN 1 + +#define P1_CFG (1 << POWER_STATUS_PIN) +#define P1_OUT (LTE_ENABLE_DEFAULT << LTE_ENABLE_PIN) +#define P1_POL 0 + +static const struct { + uint8_t port, pin; +} sm7_leds[] = { + {LED1_PORT, LED1_PIN}, + {LED2_PORT, LED2_PIN} +}; + +int sm7_led_on(int led) +{ + if (led >= ARRAY_SIZE(sm7_leds)) + return -1; + tca6416a_set(sm7_leds[led].port, sm7_leds[led].pin); + return 0; +} + +int sm7_led_off(int led) +{ + if (led >= ARRAY_SIZE(sm7_leds)) + return -1; + tca6416a_clr(sm7_leds[led].port, sm7_leds[led].pin); + return 0; +} + +int sm7_12v_on() +{ + tca6416a_set(POWER_ENABLE_PORT, POWER_ENABLE_PIN); + return 0; +} +int sm7_12v_off() +{ + tca6416a_clr(POWER_ENABLE_PORT, POWER_ENABLE_PIN); + return 0; +} + +static uint32_t sm7_timer_start; +static uint8_t sm7_power_on_flag = 0; +static uint8_t sm7_power_on_release = 1; +uint8_t sm7_power_off_flag = 0; + +static void sm7_process_power_on(void) +{ + sm7_power_on_flag = 1; + debug("sm7_12v_on!\n"); + sm7_led_on(1); + sm7_12v_on(); + i2c_peripheral_enable(I2C1); +} + +static void sm7_process_power_off(void) +{ + sm7_power_on_flag = 0; + debug("sm7_12v_off!\n"); + sm7_led_off(1); + mdelay(1000); + sm7_12v_off(); + mdelay(1000); + debug("sm7_12v_off end!\n"); + //i2c_peripheral_enable(I2C1); +} + +static void sm7_process(void) +{ + int err; + // test start +// int temp; +// temp = tca6416a_read(TCA6416A_P0_OUT); +// debug("TCA6416A_P0_OUT is:0x%x\n",temp); + // test end + if (sm7_power_off_flag==1){ + sm7_power_off_flag = 0; + sm7_process_power_off(); + } + + err = tca6416a_get(POWER_BUTTON_PORT, POWER_BUTTON_PIN); + if (err < 0) + return; + + if (err) { + if (sm7_timer_start == 0) + sm7_timer_start = tick_get(); + else { + if ( (sm7_power_on_release)&&(sm7_power_on_flag == 0 ? (tick_get() - sm7_timer_start > SM7_POWER_ON_DELAY): (tick_get() - sm7_timer_start > SM7_POWER_OFF_DELAY)) ) + { + i2c_peripheral_disable(I2C1); + sm7_power_on_release = 0; + if(sm7_power_on_flag == 0) + { + sm7_process_power_on(); + } + else + { + sm7_process_power_off(); + } + } + } + } else { + sm7_timer_start = 0; + sm7_power_on_release = 1; + } +} + +void sm7_init(void) +{ + tca6416a_write(TCA6416A_P0_OUT, P0_OUT); + tca6416a_write(TCA6416A_P1_OUT, P1_OUT); + tca6416a_write(TCA6416A_P0_CFG, P0_CFG); + tca6416a_write(TCA6416A_P1_CFG, P1_CFG); + tca6416a_write(TCA6416A_P0_POL, P0_POL); + tca6416a_write(TCA6416A_P1_POL, P1_POL); + + loop_add(sm7_process); +} + diff --git a/SM7CUSTV1/sm7.h b/SM7CUSTV1/sm7.h new file mode 100644 index 00000000..3305da72 --- /dev/null +++ b/SM7CUSTV1/sm7.h @@ -0,0 +1,11 @@ +#ifndef __SM7_H__ +#define __SM7_H__ + +void sm7_init(); +int sm7_led_on(); +int sm7_led_off(); +int sm7_12v_on(); +int sm7_12v_off(); + +#endif + diff --git a/SM7CUSTV1/system.c b/SM7CUSTV1/system.c new file mode 100644 index 00000000..ef4da095 --- /dev/null +++ b/SM7CUSTV1/system.c @@ -0,0 +1,201 @@ +/** + * @file main.c + * @author chao.wei + * @brief application logical start + */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define AHB_FREQ (32 * 1000 * 1000) +#define APB1_FREQ AHB_FREQ +#define APB2_FREQ AHB_FREQ + +static unsigned long heap_start; +static unsigned long heap_end; + +static void __attribute__((unused)) +system_usart2_init(void) +{ + /* usart 2 */ + rcc_periph_clock_enable(RCC_USART2); + + usart_set_baudrate(USART2, USART2_BAUDRATE); + usart_set_databits(USART2, 8); + usart_set_stopbits(USART2, USART_STOPBITS_1); + usart_set_parity(USART2, USART_PARITY_NONE); + usart_set_flow_control(USART2, USART_FLOWCONTROL_NONE); + usart_set_mode(USART2, USART_MODE_TX_RX); + usart_disable_overrun_detection(USART2); + usart_enable(USART2); + +} + +void system_init(void) +{ + /* we may load this to a place other than default reset address */ + /* so relocated vtor -- vector table offset register */ + SCB_VTOR = (uint32_t)&vector_table; + + /* enable all gpio power and clock */ + rcc_periph_clock_enable(RCC_GPIOA); + rcc_periph_clock_enable(RCC_GPIOB); + rcc_periph_clock_enable(RCC_GPIOC); + + /* i2c1, i2c2 */ + rcc_periph_clock_enable(RCC_I2C1); + rcc_periph_clock_enable(RCC_I2C2); + + /* for external interrupts */ + /* enable PCIE RESET PIN interrupt */ + rcc_periph_clock_enable(RCC_SYSCFG); + + /* for ADC */ + rcc_periph_clock_enable(RCC_ADC1); + + pin_init(); + +//#ifdef DEBUG + system_usart2_init(); +//#endif + + tick_init(); + timer_setup(); +} + +void clock_init(void) +{ + if (rcc_is_osc_ready(RCC_HSI16)) { + /* we have set it up before */ + rcc_ahb_frequency = AHB_FREQ; + rcc_apb1_frequency = APB1_FREQ; + rcc_apb2_frequency = APB2_FREQ; + } else { + struct rcc_clock_scale clk = { + .pll_mul = RCC_CFGR_PLLMUL_MUL4, + .pll_div = RCC_CFGR_PLLDIV_DIV2, + .pll_source = RCC_CFGR_PLLSRC_HSI16_CLK, + .flash_waitstates = FLASH_ACR_LATENCY_1WS, + .voltage_scale = PWR_SCALE1, + .hpre = RCC_CFGR_HPRE_NODIV, + .ppre1 = RCC_CFGR_PPRE1_NODIV, + .ppre2 = RCC_CFGR_PPRE2_NODIV, + .ahb_frequency = AHB_FREQ, + .apb1_frequency = APB1_FREQ, + .apb2_frequency = APB2_FREQ, + .msi_range = 0, /* ignored by driver */ + }; + + rcc_clock_setup_pll(&clk); + } +} + +int std_read(void) +{ + if (!usart_is_recv_ready(STD_UART)) + return -1; + return usart_recv(STD_UART); +} + +int __io_putchar(int c) +{ + if (c == '\n') + usart_send_blocking(STD_UART, '\r'); + usart_send_blocking(STD_UART, c); + return c; +} + +int puts(const char *s) +{ + int i; + + for (i = 0; *s; ++s, ++i) + __io_putchar(*s); + + __io_putchar('\n'); + + return i; +} + +//int _write(int fd, char *pBuffer, int size) +//{ +// for (int i = 0; i < size; i++) +// { +// usart_send_blocking(STD_UART, pBuffer[i]); +// } +// return size; +//} + +int printf(const char *fmt, ...) +{ + va_list ap; + char p[128], pch; + int len; + char *q; + + va_start(ap, fmt); + len = vsnprintf(p, sizeof(p), fmt, ap); + va_end(ap); + + pch = 0; + + for (q = p; *q; ++q) { + /* insert \r to \n if we have not send \r out before \n */ + if (*q == '\n' && pch != '\r') + __io_putchar('\r'); + __io_putchar(*q); + pch = *q; + } + + return len; +} + +void *_sbrk(unsigned long inc) +{ + void *last; + + if (heap_start == 0) { + heap_start = (unsigned long)&_ebss; + heap_end = heap_start; + } + last = (void *)heap_end; + heap_end += inc; + return last; +} + +void uart_putc(int c) +{ + usart_send_blocking(STD_UART, c); +} + +int uart_getc(void) +{ + if (usart_is_recv_ready(STD_UART)) + return usart_recv(STD_UART); + return -1; +} + +int uart_puts(const char *s) +{ + int i; + + for (i = 0; s[i]; ++i) { + if (s[i] == '\n') + usart_send_blocking(STD_UART, '\r'); + usart_send_blocking(STD_UART, s[i]); + } + + return i; +} diff --git a/SM7CUSTV1/system.h b/SM7CUSTV1/system.h new file mode 100644 index 00000000..07603308 --- /dev/null +++ b/SM7CUSTV1/system.h @@ -0,0 +1,20 @@ +#ifndef __SYSTEM_H__ +#define __SYSTEM_H__ + +#include + +#define DEFAULT_BAUDRATE 115200 + +#define USART2_BAUDRATE DEFAULT_BAUDRATE + +#define STD_UART USART2 + +void system_init(void); +void clock_init(void); +int std_read(void); +void uart_putc(int c); +int uart_getc(void); +int uart_puts(const char *s); + + +#endif diff --git a/SM7CUSTV1/target.ldi b/SM7CUSTV1/target.ldi new file mode 100644 index 00000000..b3b84971 --- /dev/null +++ b/SM7CUSTV1/target.ldi @@ -0,0 +1,11 @@ +/* Define memory regions. */ +MEMORY +{ + rom (rx) : ORIGIN = ROM_START, LENGTH = ROM_SIZE + ram (rwx) : ORIGIN = RAM_START, LENGTH = RAM_SIZE + eep (r) : ORIGIN = 0x08080000, LENGTH = 2K +} + +/* Include the common ld script. */ +INCLUDE cortex-m-generic.ld + diff --git a/SM7CUSTV1/tick.c b/SM7CUSTV1/tick.c new file mode 100644 index 00000000..a9a6f7eb --- /dev/null +++ b/SM7CUSTV1/tick.c @@ -0,0 +1,75 @@ +#include +#include +#include +#include + +#define TICK_TASK_MAX 8 + +/* software system tick in ms */ +static volatile unsigned long tick; +static volatile int task_num; +static volatile struct { + unsigned long tick; + unsigned long interval; + void (*func)(void); +} task[TICK_TASK_MAX]; + +void tick_init(void) +{ + systick_counter_disable(); + systick_clear(); + systick_set_frequency(1000, rcc_ahb_frequency); + systick_interrupt_enable(); + systick_counter_enable(); +} + +unsigned long tick_get(void) +{ + return tick; +} + +int tick_register_task(void (*func)(void), unsigned long interval) +{ + if (task_num >= ARRAY_SIZE(task)) + return -1; + + task[task_num].tick = 0; + task[task_num].interval = interval; + task[task_num].func = func; + ++task_num; + return task_num - 1; +} + +void tick_set_task_interval(int handle, unsigned long interval) +{ + __disable_irq(); + task[handle].interval = interval; + task[handle].tick = 0; + __enable_irq(); +} + +void mdelay(unsigned long ms) +{ + unsigned long cur = tick; + /* make sure, wait time is larger than the given one */ + while (tick - cur <= ms) + ; +} + +/* overwrite the default one */ +void sys_tick_handler(void) +{ + int i; + + ++tick; + + for (i = 0; i < task_num; ++i) { + if (task[i].interval == 0) + continue; + ++task[i].tick; + if (task[i].tick >= task[i].interval) { + task[i].func(); + task[i].tick = 0; + } + } +} diff --git a/SM7CUSTV1/tick.h b/SM7CUSTV1/tick.h new file mode 100644 index 00000000..7e400ff4 --- /dev/null +++ b/SM7CUSTV1/tick.h @@ -0,0 +1,10 @@ +#ifndef __TICK_H__ +#define __TICK_H__ + +void tick_init(void); +void mdelay(unsigned long ms); +unsigned long tick_get(void); +int tick_register_task(void (*func)(void), unsigned long interval); +void tick_set_task_interval(int handle, unsigned long interval); + +#endif diff --git a/SM7CUSTV1/timer.c b/SM7CUSTV1/timer.c new file mode 100644 index 00000000..0c7646b5 --- /dev/null +++ b/SM7CUSTV1/timer.c @@ -0,0 +1,109 @@ +#include +#include +#include +#include +#include +#include + +unsigned long tim6_cnt; + +int timer_setup(void) +{ + rcc_periph_clock_enable(RCC_TIM6); + timer_disable_counter(TIM6); + + return 0; +} + +void timer_start(unsigned long us) +{ + timer_disable_counter(TIM6); + +#if 0 + uint32_t div, cnt; + uint64_t clk = (uint64_t)us * rcc_apb1_frequency / 1000000; + + if (clk > 0xffff) { + div = (clk / 0xffff); + cnt = clk - (div * 0xffff); + } + else { + div = 1; + cnt = clk; + } + timer_set_prescaler(TIM6, div - 1); + timer_set_period(TIM6, cnt); +#else + /* set to about 1M Hz */ + timer_set_prescaler(TIM6, 32 - 1); + timer_set_period(TIM6, us); +#endif + timer_one_shot_mode(TIM6); + timer_generate_event(TIM6, TIM_EGR_UG); + + timer_enable_counter(TIM6); +} + +void timer_stop(void) +{ + timer_disable_counter(TIM6); +} + +int timer_is_timeout(void) +{ + int timeout = (TIM_CR1(TIM6) & TIM_CR1_CEN) == 0; + + if (timeout) + timer_stop(); + + return timeout; +} + +void tim6_dac_isr(void) +{ + debug("tim6 isr %lu\n", (unsigned long)tick_get()); + ++tim6_cnt; + timer_clear_flag(TIM6, TIM_SR_UIF); +} + +void timer_mdelay(unsigned long ms) +{ + if (ms == 0) + return; + + timer_start(ms * 1000); + while (!timer_is_timeout()) + ; +} + +void timer_udelay(unsigned long us) +{ + if (us == 0) + return; + + timer_start(us); + while (!timer_is_timeout()) + ; +} + +void timer_test(void) +{ +#if 0 + nvic_enable_irq(NVIC_TIM6_DAC_IRQ); + timer_enable_irq(TIM6, TIM_DIER_UIE); + timer_start(1 * 1000 * 1000); + debug("apb1 frequency %ld\n", rcc_apb1_frequency); +#else + unsigned long i; + + debug("start timer\n"); + for (i = 0; i < 60; ++i) { + timer_start(1 * 1000 * 1000); + while (!timer_is_timeout()) + ; + // timer_stop(); + debug("%ld seconds\n", i); + } +#endif +} + diff --git a/SM7CUSTV1/timer.h b/SM7CUSTV1/timer.h new file mode 100644 index 00000000..478e6dfe --- /dev/null +++ b/SM7CUSTV1/timer.h @@ -0,0 +1,13 @@ +#ifndef __TIMER_H__ +#define __TIMER_H__ + +int timer_setup(void); +void timer_start(unsigned long us); +unsigned long timer_counter(void); +void timer_stop(void); +void timer_test(void); +void timer_mdelay(unsigned long ms); +void timer_udelay(unsigned long us); +int timer_is_timeout(void); + +#endif diff --git a/SM7CUSTV1/upgrade.c b/SM7CUSTV1/upgrade.c new file mode 100644 index 00000000..9d80a1a0 --- /dev/null +++ b/SM7CUSTV1/upgrade.c @@ -0,0 +1,175 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +struct efie { + uint32_t offset; + uint32_t length; + uint8_t checksum[16]; + uint8_t is_checked; + uint8_t type; + uint8_t padding[102]; +} __packed; + +static void upgrade_start(unsigned int type); +static struct efie *find_efie(uint32_t type); + +void uart_upgrade_start(void) +{ + upgrade_start(RUN_STAGE_UART_UPGRADER); +} + +void i2c_upgrade_start(void) +{ + upgrade_start(RUN_STAGE_UPGRADER); +} + +static void upgrade_start(unsigned int type) +{ + typedef void (*upgrade_entry)(uint32_t project); + struct efie *efie = find_efie(type); + + if (efie == NULL) + return; + + /* disable sys tick */ + systick_counter_disable(); + /* disable i2c1 and i2c2 */ + i2c_master_destroy(I2C1); + i2c_master_destroy(I2C2); + + if (get_work_mode() == WORK_MODE_PCIE || + get_work_mode() == WORK_MODE_MIXED) + pcie_destroy(); + + /* disable all interrupt */ + cm_disable_interrupts(); + + /* working in thumb mode, we should add 1 to destination */ + /* thumb instruction pc should be even number */ + upgrade_entry entry = (upgrade_entry) + (efie->offset + MEMMAP_FLASH_START + 1); + entry(get_board_type()); +} + +void app_start(void) +{ + unsigned long app_start, app_entry, app_stack; + struct efie *app_efie; + + app_efie = find_efie(RUN_STAGE_APP); + + app_start = app_efie->offset + MEMMAP_FLASH_START; + app_entry = *(volatile uint32_t *)(app_start + 4); + app_stack = *(volatile uint32_t*)app_start; + + asm volatile ("mov sp, %0" ::"r"(app_stack)); + + typedef void (*app_entry_t)(void); + app_entry_t entry = (void *)app_entry; + entry(); +} + +static struct efie *find_efie(uint32_t type) +{ + struct efie *p; + + for (p = (void *)MEMMAP_EFIT_START; + (unsigned long)p < MEMMAP_EFIT_END; + ++p) { + if (p->type == type) + return p; + } + return NULL; +} + +int get_stage(void) +{ + register uint32_t pc; + asm volatile ("mov %0, pc" : "=r" (pc)); + if (pc < MEMMAP_LOADER_END) + return RUN_STAGE_LOADER; + else + return RUN_STAGE_APP; +} + +static void checksum(void *out, void *in, unsigned long len) +{ + uint32_t *src = in; + char *init = "*BITMAIN-SOPHON*"; + uint32_t result[4]; + memcpy(result, init, sizeof(result)); + + unsigned long block = len >> 4; + unsigned long left = len & 0xf; + unsigned long i, j; + + for (i = 0; i < block; ++i, src += 4) { + for (j = 0; j < 4; ++j) { + result[j] ^= src[j]; + } + } + + for (i = 0; i < left; ++i) { + ((uint8_t *)result)[i] ^= ((uint8_t *)src)[i]; + } + memcpy(out, result, sizeof(result)); +} + +/* + * 0 means success, app is complete upgraded + * -1 means failed, app is broken + */ +int check_app(void) +{ + void *checksum_start; + unsigned long checksum_len; + uint8_t *expected_checksum, calculated_checksum[16]; + struct efie *app_efie; + + app_efie = find_efie(RUN_STAGE_APP); + + if (app_efie->is_checked) + return 0; + + /* get application efie */ + checksum_start = (void *)(app_efie->offset + MEMMAP_FLASH_START); + checksum_len = app_efie->length; + expected_checksum = app_efie->checksum; + if ((unsigned long)checksum_start < MEMMAP_FLASH_START || + (unsigned long)checksum_start >= MEMMAP_FLASH_END) { + return -1; + } + /* we know stm32 address is 32bit long, + * a 64bit var can handle overflow. ^_^ + */ + uint64_t checksum_end = (unsigned long)checksum_start + checksum_len; + + if (checksum_end > MEMMAP_FLASH_END) { + return -1; + } + + checksum(calculated_checksum, checksum_start, checksum_len); + if (memcmp(expected_checksum, calculated_checksum, 16)) + /* failed */ + return -1; + + /* looks good */ + flash_clear_error(); + struct efie app_efie_backup; + + memcpy(&app_efie_backup, app_efie, sizeof(app_efie_backup)); + + /* mark app as checked */ + app_efie_backup.is_checked = 1; + flash_program_page((unsigned long)app_efie, &app_efie_backup); + + return 0; +} diff --git a/SM7CUSTV1/upgrade.h b/SM7CUSTV1/upgrade.h new file mode 100644 index 00000000..a56666dc --- /dev/null +++ b/SM7CUSTV1/upgrade.h @@ -0,0 +1,29 @@ +#ifndef __UPGRADE_H__ +#define __UPGRADE_H__ + +#include + +#define MEMMAP_FLASH_START FLASH_MEM_ADDR +#define MEMMAP_FLASH_SIZE (64 * 1024) +#define MEMMAP_FLASH_END (MEMMAP_FLASH_START + MEMMAP_FLASH_SIZE) + +#define MEMMAP_LOADER_START MEMMAP_FLASH_START +#define MEMMAP_LOADER_SIZE (28 * 1024) +#define MEMMAP_LOADER_END (MEMMAP_LOADER_START + MEMMAP_LOADER_SIZE) + +#define MEMMAP_EFIT_START MEMMAP_LOADER_END +#define MEMMAP_EFIT_SIZE (4 * 1024) +#define MEMMAP_EFIT_END (MEMMAP_EFIT_START + MEMMAP_EFIT_SIZE) + +#define RUN_STAGE_APP 0 +#define RUN_STAGE_LOADER 1 +#define RUN_STAGE_UPGRADER 2 +#define RUN_STAGE_UART_UPGRADER 3 + +int check_app(void); +int get_stage(void); +void i2c_upgrade_start(void); +void uart_upgrade_start(void); +void app_start(void); + +#endif diff --git a/build/sm7custv1-layout.xml b/build/sm7custv1-layout.xml new file mode 100644 index 00000000..9cbbb326 --- /dev/null +++ b/build/sm7custv1-layout.xml @@ -0,0 +1,27 @@ + + + SM7CUSTV1 + 0x10000 + + 0x7000 + 4096 + + + application + 0 + ../SM7CUSTV1/build/SM7CUSTV1_APP.bin + 0x8000 + + + i2c-upgrader + 2 + ../upgrader/upgrader.bin + 0xf000 + + + loader + 1 + ../SM7CUSTV1/build/SM7CUSTV1_LOADER.bin + 0x0000 + + diff --git a/build/sm7custv1.mak b/build/sm7custv1.mak new file mode 100644 index 00000000..7ae20b4b --- /dev/null +++ b/build/sm7custv1.mak @@ -0,0 +1,30 @@ +APP_ROOT = $(TOP)/SM7CUSTV1 +UPGRADER_ROOT = $(TOP)/upgrader +TOOLS = $(TOP)/tools +PACK_ROOT = $(TOOLS)/pack +PACK = $(PACK_ROOT)/pack +UTILROOT = $(TOOLS)/util +UPGRADE = $(UTILROOT)/mcu-util + +$(TARGET): FORCE + $(Q)rm -rf $(OUTPUT) + $(Q)mkdir -p $(OUTPUT) + $(Q)cd $(APP_ROOT) && make clean && make + $(Q)cd $(UPGRADER_ROOT) && make distclean && make + $(Q)cd $(PACK_ROOT) && make distclean && make + $(Q)cd $(UTILROOT) && make clean && make && cd - && cp $(UPGRADE) $(OUTPUT)/mcu-util-amd64 + $(Q)cd $(UTILROOT) && make clean && make CROSS_COMPILE=$(AARCH64_CROSS_COMPILE) && cd - && cp $(UPGRADE) $(OUTPUT)/mcu-util-aarch64 + $(Q)$(PACK) sm7custv1-layout.xml $@ $(E) && mv $@ $(OUTPUT)/ + +clean: FORCE + $(Q)cd $(APP_ROOT) && make clean + $(Q)cd $(UPGRADER_ROOT) && make distclean + $(Q)cd $(PACK_ROOT) && make distclean + $(Q)cd $(UTILROOT) && make clean + $(Q)cd $(UTILROOT) && make clean + +distclean: clean + $(Q)rm -rf $(OUTPUT) + +burn: FORCE + st-flash write $(OUTPUT)/$(TARGET) 0x08000000 diff --git a/tools/pack/common.c b/tools/pack/common.c index 2a391b0d..4dfd5474 100644 --- a/tools/pack/common.c +++ b/tools/pack/common.c @@ -136,6 +136,7 @@ struct { {"SE5LITE", {SE5LITE}}, {"SC7PRO", {SC7PRO}}, {"BM1684XEVB", {BM1684XEVB}}, + {"SM7CUSTV1", {SM7CUSTV1}}, {"SG2042EVB", {SG2042EVB}}, {"SG2042REVB", {SG2042REVB}}, {"SG2042X4", {SG2042X4}}, diff --git a/tools/pack/project.h b/tools/pack/project.h index e9a4be18..b5ad8353 100644 --- a/tools/pack/project.h +++ b/tools/pack/project.h @@ -34,6 +34,7 @@ #define SM7M_MP_1_2 0X37 #define SE7Q 0x38 +#define SM7CUSTV1 0x3a #define ATHENA2EVB 0x40 #define ATHENA2ACP 0x41 diff --git a/tools/util/project.h b/tools/util/project.h index c45665b3..2906eae2 100644 --- a/tools/util/project.h +++ b/tools/util/project.h @@ -35,6 +35,7 @@ #define SM7M_MP_1_2 0X37 #define SE7Q 0x38 +#define SM7CUSTV1 0x3a #define ATHENA2EVB 0x40 #define ATHENA2ACP 0x41 diff --git a/tools/util/stm32l0_util.c b/tools/util/stm32l0_util.c index 74242f11..c1566608 100644 --- a/tools/util/stm32l0_util.c +++ b/tools/util/stm32l0_util.c @@ -83,6 +83,7 @@ static struct { {"SM5MINI", {SM5ME, SM5MP, SM5MS, SM5MA, SM5SE6M, -1} }, {"SE5LITE", {SE5LITE, -1}}, {"BM1684XEVB", {BM1684XEVB, BM1684XEVB, -1}}, + {"SM7CUSTV1", {SM7CUSTV1, SM7CUSTV1, -1}}, {"SM7MINI", {SM7M, -1}}, {"SM7MQY", {SM7MQY, SE7Q, -1}}, {"SE7", {SE7, -1}}, diff --git a/upgrader/main.c b/upgrader/main.c index 9fdc2455..25e234e4 100644 --- a/upgrader/main.c +++ b/upgrader/main.c @@ -65,6 +65,7 @@ static inline void led_init(void) case SM7M_MP_1_1: case SE7: case SM7MSE6M: + case SM7CUSTV1: MCU_LED_PORT = GPIOC; MCU_LED_PIN = GPIO_PIN_13; break; diff --git a/upgrader/project.h b/upgrader/project.h index 6e3b974f..a5289a59 100644 --- a/upgrader/project.h +++ b/upgrader/project.h @@ -35,6 +35,7 @@ #define SM7M_MP_1_2 0X37 #define SE7Q 0x38 +#define SM7CUSTV1 0x3a #define ATHENA2EVB 0x40 #define ATHENA2ACP 0x41 diff --git a/upgrader/upgrader.c b/upgrader/upgrader.c index aa9a0a0c..8ce9118c 100644 --- a/upgrader/upgrader.c +++ b/upgrader/upgrader.c @@ -282,6 +282,7 @@ void upgrader_init(void) case SM7M_MP_1_1: case SE7: case SM7MSE6M: + case SM7CUSTV1: i2c1_init(0x17, 0x00); break; default: