Compare commits

...

10 Commits
v0.2 ... master

Author SHA1 Message Date
e1a77fc1ca
v0.5 fix patch 2025-06-01 12:29:31 +02:00
efab6c2ff3
RTC working prototype
- Removed IWDG (need to migrate to WWDG for RTC working)
- Power registers to ask for next power state
- Stop mode instead of complete power shutdown
2025-05-25 19:43:16 +02:00
4d93c9d2e2
Implement RTC alarm registers
- minors fix
- alarm management WIP
2025-05-21 13:33:29 +02:00
fb2b213392
RTC simple registers interface
Only R/W time/date in BCD format (for read mode only)
2025-05-13 16:37:18 +02:00
8985f3d3a3
Add some debug assembly 2025-05-12 20:10:16 +02:00
b6aae3384e
Last final registers implementation
- Add FEE to linker script
- Debug PrintPMU
- systick overflow check
2025-05-09 19:34:21 +02:00
4f003168c4
Upgraded I2C receive handler 2025-05-08 20:21:45 +02:00
c8351f0124
New I2C registers IRQ mechanism
Compatibility mode added
2025-05-08 19:32:18 +02:00
7e58a74f5a
Added reset and shutdown registers 2025-05-06 21:34:32 +02:00
f6d7a83f1b
Added version and type registers
More code clean up...
2025-05-06 21:04:10 +02:00
25 changed files with 2017 additions and 1714 deletions

View File

@ -14,11 +14,11 @@
#define XPOWERS_AXP2101_IC_TYPE (0x03)
//#define XPOWERS_AXP2101_DATA_BUFFER1 (0x04)
//#define XPOWERS_AXP2101_DATA_BUFFER2 (0x05)
//#define XPOWERS_AXP2101_DATA_BUFFER3 (0x06)
//#define XPOWERS_AXP2101_DATA_BUFFER4 (0x07)
//#define XPOWERS_AXP2101_DATA_BUFFER_SIZE (4u)
#define XPOWERS_AXP2101_DATA_BUFFER1 (0x04)
#define XPOWERS_AXP2101_DATA_BUFFER2 (0x05)
#define XPOWERS_AXP2101_DATA_BUFFER3 (0x06)
#define XPOWERS_AXP2101_DATA_BUFFER4 (0x07)
#define XPOWERS_AXP2101_DATA_BUFFER_SIZE (4u)
#define XPOWERS_AXP2101_COMMON_CONFIG (0x10)
//#define XPOWERS_AXP2101_BATFET_CTRL (0x12)
@ -49,16 +49,16 @@
//#define XPOWERS_AXP2101_FAST_PWRON_CTRL (0x2B)
#define XPOWERS_AXP2101_ADC_CHANNEL_CTRL (0x30)
//#define XPOWERS_AXP2101_ADC_DATA_RELUST0 (0x34)
//#define XPOWERS_AXP2101_ADC_DATA_RELUST1 (0x35)
//#define XPOWERS_AXP2101_ADC_DATA_RELUST2 (0x36)
//#define XPOWERS_AXP2101_ADC_DATA_RELUST3 (0x37)
//#define XPOWERS_AXP2101_ADC_DATA_RELUST4 (0x38)
//#define XPOWERS_AXP2101_ADC_DATA_RELUST5 (0x39)
//#define XPOWERS_AXP2101_ADC_DATA_RELUST6 (0x3A)
//#define XPOWERS_AXP2101_ADC_DATA_RELUST7 (0x3B)
//#define XPOWERS_AXP2101_ADC_DATA_RELUST8 (0x3C)
//#define XPOWERS_AXP2101_ADC_DATA_RELUST9 (0x3D)
#define XPOWERS_AXP2101_ADC_DATA_RELUST0 (0x34)
#define XPOWERS_AXP2101_ADC_DATA_RELUST1 (0x35)
#define XPOWERS_AXP2101_ADC_DATA_RELUST2 (0x36)
#define XPOWERS_AXP2101_ADC_DATA_RELUST3 (0x37)
#define XPOWERS_AXP2101_ADC_DATA_RELUST4 (0x38)
#define XPOWERS_AXP2101_ADC_DATA_RELUST5 (0x39)
#define XPOWERS_AXP2101_ADC_DATA_RELUST6 (0x3A)
#define XPOWERS_AXP2101_ADC_DATA_RELUST7 (0x3B)
#define XPOWERS_AXP2101_ADC_DATA_RELUST8 (0x3C)
#define XPOWERS_AXP2101_ADC_DATA_RELUST9 (0x3D)
/*
* ------------------ Interrupt registers ---------------------
@ -266,6 +266,15 @@ typedef enum __xpowers_chg_led_mode {
XPOWERS_CHG_LED_CTRL_CHG, // The charging indicator is controlled by the charger
} xpowers_chg_led_mode_t;
typedef enum {
XPOWERS_AXP2101_CHG_TRI_STATE, //tri_charge
XPOWERS_AXP2101_CHG_PRE_STATE, //pre_charge
XPOWERS_AXP2101_CHG_CC_STATE, //constant charge
XPOWERS_AXP2101_CHG_CV_STATE, //constant voltage
XPOWERS_AXP2101_CHG_DONE_STATE, //charge done
XPOWERS_AXP2101_CHG_STOP_STATE, //not charge
} xpowers_chg_status_t;
/*
* ------------- axp2101 interrupt control mask -------------
*/
@ -315,8 +324,8 @@ uint8_t AXP2101_isDropWarningLevel1Irq(void);
uint8_t AXP2101_isVbusRemoveIrq(void);
uint8_t AXP2101_isBatInsertIrq(void);
uint8_t AXP2101_isBatRemoveIrq(void);
uint8_t AXP2101_isPekeyShortPressIrq(void);
uint8_t AXP2101_isPekeyLongPressIrq(void);
uint8_t AXP2101_isPkeyShortPressIrq(void);
uint8_t AXP2101_isPkeyLongPressIrq(void);
uint8_t AXP2101_isBatChargeDoneIrq(void);
uint8_t AXP2101_isBatChargeStartIrq(void);
@ -325,9 +334,18 @@ uint32_t AXP2101_setLowBatShutdownThreshold(uint8_t opt);
uint32_t AXP2101_setSysPowerDownVoltage(uint16_t value);
uint32_t AXP2101_setChargingLedMode(uint8_t mode);
int8_t AXP2101_readDataBuffer(uint8_t *data, uint8_t size);
uint8_t AXP2101_isBatteryConnect(void);
uint8_t AXP2101_isCharging(void);
uint8_t AXP2101_isDischarge(void);
uint8_t AXP2101_isStandby(void);
uint8_t AXP2101_isVbusGood(void);
uint8_t AXP2101_isVbusIn(void);
uint32_t AXP2101_getIrqStatus(uint32_t* out_value);
uint32_t AXP2101_getBatteryPercent(uint8_t* out_value);
xpowers_chg_status_t AXP2101_getChargerStatus(void);
uint16_t AXP2101_getBattVoltage(void);
uint16_t AXP2101_getVbusVoltage(void);
uint16_t AXP2101_getSystemVoltage(void);
#endif /* AXP2101_H_ */

View File

@ -1,3 +1,4 @@
#include "stm32f1xx_hal.h"
//EEPROM emulation library for STM32F1XX with HAL-Driver
//V2.0
@ -6,8 +7,12 @@
#ifndef __EEPROM_H
#define __EEPROM_H
//includes
#include "stm32f1xx_hal.h"
//---------------------------------------------Datas registration--------------------------------------------
#define EEPROM_VAR_ID (0) // 16b: Init ID: 0xCA1C
#define EEPROM_VAR_CFG (1) // 16b: CFG(15:8) + INT_CFG(7:0) reg
#define EEPROM_VAR_KBD (2) // 32b: DEB(15:0) + 0x00 + FRQ(7:0) regs
#define EEPROM_VAR_BCKL (3) // 16b: LCD(15:8) + KBD(7:0) backlight step indice
//-------------------------------------------library configuration-------------------------------------------

View File

@ -1,26 +1,22 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file hal_interface.h
* @brief Central access to STM32-HAL definitions and
* related functions.
******************************************************************************
* @attention
*
* Copyright (c) 2025 C.ARE (JackCarterSmith).
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
*
******************************************************************************
*
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __MAIN_H
#define __MAIN_H
#ifdef __cplusplus
extern "C" {
#endif
/* Includes ------------------------------------------------------------------*/
#include "stm32f1xx_hal.h"
#include "stm32f1xx_ll_iwdg.h"
#include "stm32f1xx_ll_rcc.h"
@ -31,48 +27,17 @@ extern "C" {
#include "stm32f1xx_ll_utils.h"
#include "stm32f1xx_ll_pwr.h"
#include "stm32f1xx_ll_dma.h"
#include "stm32f1xx_ll_rtc.h"
#include "stm32f1xx_ll_gpio.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
#include "stm32f1xx_ll_tim.h"
/* USER CODE END Includes */
/* Exported types ------------------------------------------------------------*/
/* USER CODE BEGIN ET */
#ifndef HAL_INTERFACE_H_
#define HAL_INTERFACE_H_
/* USER CODE END ET */
#ifdef __cplusplus
extern "C" {
#endif
/* Exported constants --------------------------------------------------------*/
/* USER CODE BEGIN EC */
extern TIM_HandleTypeDef htim1;
extern TIM_HandleTypeDef htim3;
extern I2C_HandleTypeDef hi2c2;
extern volatile uint32_t systicks_counter;
extern volatile uint8_t pmu_irq;
extern uint8_t io_matrix[9];
extern uint8_t js_bits;
/* USER CODE END EC */
/* Exported macro ------------------------------------------------------------*/
/* USER CODE BEGIN EM */
/* USER CODE END EM */
void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim);
/* Exported functions prototypes ---------------------------------------------*/
void Error_Handler(void);
/* USER CODE BEGIN EFP */
__STATIC_INLINE uint32_t uptime_ms(void) { return systicks_counter; }
void flash_one_time(uint32_t ts, uint8_t restore_status);
/* USER CODE END EFP */
/* Private defines -----------------------------------------------------------*/
// HAL GPIO pins definition --------------------------------------------------------
#define SYS_LED_Pin LL_GPIO_PIN_13
#define SYS_LED_GPIO_Port GPIOC
#define COL_1_Pin LL_GPIO_PIN_0
@ -136,10 +101,15 @@ void flash_one_time(uint32_t ts, uint8_t restore_status);
#define PICO_EN_GPIO_Port GPIOA
#define SP_AMP_EN_Pin LL_GPIO_PIN_14
#define SP_AMP_EN_GPIO_Port GPIOA
#ifdef UART_PICO_INTERFACE
#define PICO_UART_TX_Pin LL_GPIO_PIN_10
#define PICO_UART_TX_GPIO_Port GPIOC
#define PICO_UART_RX_Pin LL_GPIO_PIN_11
#define PICO_UART_RX_GPIO_Port GPIOC
#else
#define PICO_IRQ_Pin LL_GPIO_PIN_10
#define PICO_IRQ_GPIO_Port GPIOC
#endif
#define HP_DET_Pin LL_GPIO_PIN_12
#define HP_DET_GPIO_Port GPIOC
#define KEY_4_Pin LL_GPIO_PIN_3
@ -157,15 +127,55 @@ void flash_one_time(uint32_t ts, uint8_t restore_status);
#define PICO_SDA_Pin LL_GPIO_PIN_9
#define PICO_SDA_GPIO_Port GPIOB
/* USER CODE BEGIN Private defines */
#define EEPROM_VAR_ID (0) // 16b: Init ID: 0xCA1C
#define EEPROM_VAR_CFG (1) // 16b: 0x00 + CFG reg
#define EEPROM_VAR_KBD (2) // 16b: DEB + FRQ regs
#define EEPROM_VAR_BCKL (3) // 16b: LCD + KBD backlight step indice
/* USER CODE END Private defines */
// Structure definition ---------------------------------------------------------------
typedef union {
uint32_t raw;
RTC_TimeTypeDef _s;
} RTC_TimeTypeDef_u;
typedef union {
uint32_t raw;
RTC_DateTypeDef _s;
} RTC_DateTypeDef_u;
// Global variables definition --------------------------------------------------------
extern volatile uint32_t systicks_counter;
extern volatile uint8_t pmu_irq;
extern volatile uint8_t stop_mode_active;
extern volatile RTC_TimeTypeDef_u rtc_alarm_time;
extern volatile RTC_DateTypeDef_u rtc_alarm_date;
// Global functions definition --------------------------------------------------------
void SystemClock_Config(void);
HAL_StatusTypeDef HAL_Interface_init(void);
__STATIC_INLINE uint32_t uptime_ms(void) { return systicks_counter; }
void flash_one_time(uint32_t ts, uint8_t restore_status);
void Error_Handler(void);
#ifdef USE_FULL_ASSERT
/**
* @brief The assert_param macro is used for function's parameters check.
* @param expr If expr is false, it calls assert_failed function
* which reports the name of the source file and the source
* line number of the call that failed.
* If expr is true, it returns no value.
* @retval None
*/
#define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__))
/* Exported functions ------------------------------------------------------- */
void assert_failed(uint8_t *file, uint32_t line);
#else
#define assert_param(expr) ((void)0U)
#endif /* USE_FULL_ASSERT */
#ifdef __cplusplus
}
#endif
#endif /* __MAIN_H */
#endif /* HAL_INTERFACE_H_ */

View File

@ -1,5 +1,4 @@
#include "stm32f1xx_hal.h"
#include "main.h"
#ifndef KEYBOARD_H_
#define KEYBOARD_H_
@ -74,14 +73,18 @@ enum key_state {
#define KEY_F10 0x90
extern uint8_t io_matrix[9];
extern uint8_t js_bits;
typedef void (*key_callback)(char, enum key_state);
typedef void (*lock_callback)(uint8_t, uint8_t);
void keyboard_set_key_callback(key_callback callback);
void keyboard_set_lock_callback(lock_callback callback);
uint8_t keyboard_get_capslock(void);
uint8_t keyboard_get_numlock(void);
uint16_t keyboard_get_hold_period(void);
void keyboard_set_hold_period(uint16_t);
void keyboard_process(void);

View File

@ -4,45 +4,74 @@
#ifndef REGS_H_
#define REGS_H_
enum reg_id
{
REG_ID_VER = 0x01, // fw version
enum reg_id {
REG_ID_TYP = 0x00, //!< firmware type (0=official, others=custom)
REG_ID_VER = 0x01, //!< fw version (7:4=Major, 3:0=Minor)
#ifdef I2C_REGS_COMPAT
REG_ID_CFG = 0x02, // config
REG_ID_INT = 0x03, // interrupt status
REG_ID_KEY = 0x04, // key status
REG_ID_BKL = 0x05, // backlight steps (0-9)
REG_ID_DEB = 0x06, // debounce cfg
REG_ID_FRQ = 0x07, // poll freq cfg
REG_ID_RST = 0x08, // reset
REG_ID_PWR_CTRL = 0x08, // Power control (0: idle, 1: pico reset, 2: system reset, 3: reserved, 4: sleep, 5: full-shutdown)
REG_ID_FIF = 0x09, // fifo
REG_ID_BK2 = 0x0A, // keyboard backlight (0-9)
REG_ID_BAT = 0x0B, // battery
REG_ID_C64_MTX = 0x0C,// read c64 matrix
REG_ID_C64_JS = 0x0D, // joystick io bits
REG_ID_LAST,
REG_ID_INT_CFG = 0x0E, // IRQ config
REG_ID_RTC_CFG = 0x0F, // RTC general config
REG_ID_RTC_DATE = 0x10, // RTC date
REG_ID_RTC_TIME = 0x11, // RTC time
REG_ID_RTC_ALARM_DATE = 0x12, // RTC alarm date
REG_ID_RTC_ALARM_TIME = 0x13, // RTC alarm time
#else
REG_ID_CFG = 0x02, //!< config
REG_ID_INT_CFG = 0x03, //!< IRQ config
REG_ID_INT = 0x04, //!< interrupt status
REG_ID_BKL = 0x05, //!< backlight steps (0-9)
REG_ID_BK2 = 0x06, //!< keyboard backlight (0-9)
REG_ID_DEB = 0x07, //!< debounce cfg (time in ms)
REG_ID_FRQ = 0x08, //!< poll freq cfg (time in ms)
REG_ID_PWR_CTRL = 0x09, //!< Power control (0: idle, 1: pico reset, 2: system reset, 3: reserved, 4: sleep, 5: full-shutdown)
REG_ID_RTC_CFG = 0x0A, //!< RTC general config
REG_ID_RTC_DATE = 0x0B, //!< RTC date
REG_ID_RTC_TIME = 0x0C, //!< RTC time
REG_ID_RTC_ALARM_DATE = 0x0D, //!< RTC alarm date
REG_ID_RTC_ALARM_TIME = 0x0E, //!< RTC alarm time
REG_ID_KEY = 0x10, //!< key status
REG_ID_FIF = 0x11, //!< fifo
REG_ID_C64_MTX = 0x12, //!< read c64 matrix
REG_ID_C64_JS = 0x13, //!< joystick io bits
REG_ID_BAT = 0x30, //!< battery
#endif
REG_ID_LAST
};
#define CFG_OVERFLOW_ON (1 << 0) //When a FIFO overflow happens, should the new entry still be pushed, overwriting the oldest one. If 0 then new entry is lost.
#define CFG_OVERFLOW_INT (1 << 1) //Should an interrupt be generated when a FIFO overflow happens
#define CFG_CAPSLOCK_INT (1 << 2) //Should an interrupt be generated when Caps Lock is toggled.
#define CFG_NUMLOCK_INT (1 << 3) //Should an interrupt be generated when Num Lock is toggled.
#define CFG_KEY_INT (1 << 4)
#define CFG_PANIC_INT (1 << 5)
#define CFG_REPORT_MODS (1 << 6) // Should Alt, Sym and Shifts be reported as well
#define CFG_USE_MODS (1 << 7) // Should Alt, Sym and Shifts modify the keys reported
#define CFG_OVERFLOW_ON (1 << 0) //When a FIFO overflow happens, should the new entry still be pushed, overwriting the oldest one. If 0 then new entry is lost.
#define CFG_REPORT_MODS (1 << 6) // Should Alt, Sym and Shifts be reported as well
#define CFG_USE_MODS (1 << 7) // Should Alt, Sym and Shifts modify the keys reported
// CFG_STICKY_MODS // Pressing and releasing a mod affects next key pressed
#define INT_OVERFLOW (1 << 0)
#define INT_CAPSLOCK (1 << 1)
#define INT_NUMLOCK (1 << 2)
#define INT_KEY (1 << 3)
#define INT_PANIC (1 << 4)
#define INT_OVERFLOW (1 << 0)
#define INT_CAPSLOCK (1 << 1)
#define INT_NUMLOCK (1 << 2)
#define INT_KEY (1 << 3)
#define INT_PANIC (1 << 4)
#define KEY_CAPSLOCK (1 << 5)
#define KEY_NUMLOCK (1 << 6)
#define KEY_COUNT_MASK 0x1F //0x1F == 31
#define KEY_CAPSLOCK (1 << 5)
#define KEY_NUMLOCK (1 << 6)
#define KEY_COUNT_MASK 0x1F //0x1F == 31
//#define VER_VAL ((VERSION_MAJOR << 4) | (VERSION_MINOR << 0))
#define RTC_CFG_RUN_ALARM (1 << 0) // b0: Set the RTC alarm active.
#define RTC_CFG_REARM (1 << 1) // b1: If set, the RTC alarm will rearm for the next day trigger (if RTC_CFG_DATE_ALARM is set, repeat every day after the target date is reached)
#define RTC_CFG_DATE_ALARM (1 << 2) // b2: If set, check when alarm trig for the precise date, otherwise return to normal behavior (or sleep if wake-up)
#define RTC_CFG_PBTN_ALARM_IGNORE (1 << 3) // b3: If unset, override the power button shutdown behavior to keep the STM32 "alive" for the RTC to operate.
//#define RTC_CFG_SLEEP_MODE (1 << 4) // 0 = normal sleep (pico is shutdown, STM32 enter in low power state ~1.2mA); 1 = deep sleep (pico is shutdown, STM32 enter a stop state ~24uA)
uint8_t reg_get_value(enum reg_id reg);

15
Core/Inc/rtc.h Normal file
View File

@ -0,0 +1,15 @@
#include "stm32f1xx_hal.h"
#ifndef RTC_H_
#define RTC_H_
void i2cs_fill_buffer_RTC_date(uint8_t* const buff, const volatile RTC_DateTypeDef* const date_s);
void i2cs_fill_buffer_RTC_time(uint8_t* const buff, const volatile RTC_TimeTypeDef* const time_s);
void i2cs_RTC_date_from_buffer(volatile RTC_DateTypeDef* const date_s, const uint8_t* const buff);
void i2cs_RTC_time_from_buffer(volatile RTC_TimeTypeDef* const time_s, const uint8_t* const buff);
uint32_t rtc_run_alarm(void);
uint32_t rtc_stop_alarm(void);
#endif /* RTC_H_ */

View File

@ -1,53 +0,0 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file stm32_assert.h
* @author MCD Application Team
* @brief STM32 assert file.
******************************************************************************
* @attention
*
* Copyright (c) 2018 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Define to prevent recursive inclusion -------------------------------------*/
#ifndef __STM32_ASSERT_H
#define __STM32_ASSERT_H
#ifdef __cplusplus
extern "C" {
#endif
/* Exported types ------------------------------------------------------------*/
/* Exported constants --------------------------------------------------------*/
/* Includes ------------------------------------------------------------------*/
/* Exported macro ------------------------------------------------------------*/
#ifdef USE_FULL_ASSERT
/**
* @brief The assert_param macro is used for function's parameters check.
* @param expr If expr is false, it calls assert_failed function
* which reports the name of the source file and the source
* line number of the call that failed.
* If expr is true, it returns no value.
* @retval None
*/
#define assert_param(expr) ((expr) ? (void)0U : assert_failed((uint8_t *)__FILE__, __LINE__))
/* Exported functions ------------------------------------------------------- */
void assert_failed(uint8_t *file, uint32_t line);
#else
#define assert_param(expr) ((void)0U)
#endif /* USE_FULL_ASSERT */
#ifdef __cplusplus
}
#endif
#endif /* __STM32_ASSERT_H */

View File

@ -57,7 +57,7 @@
/*#define HAL_HCD_MODULE_ENABLED */
/*#define HAL_PWR_MODULE_ENABLED */
/*#define HAL_RCC_MODULE_ENABLED */
/*#define HAL_RTC_MODULE_ENABLED */
#define HAL_RTC_MODULE_ENABLED
/*#define HAL_SD_MODULE_ENABLED */
/*#define HAL_MMC_MODULE_ENABLED */
/*#define HAL_SDRAM_MODULE_ENABLED */

View File

@ -59,8 +59,13 @@ void EXTI9_5_IRQHandler(void);
void TIM2_IRQHandler(void);
void I2C1_EV_IRQHandler(void);
void I2C1_ER_IRQHandler(void);
#ifdef DEBUG
void USART1_IRQHandler(void);
#endif
#ifdef UART_PICO_INTERFACE
void USART3_IRQHandler(void);
#endif
void RTC_Alarm_IRQHandler(void);
/* USER CODE BEGIN EFP */
/* USER CODE END EFP */

7
Core/Inc/version.h Normal file
View File

@ -0,0 +1,7 @@
#ifndef VERSION_H_
#define VERSION_H_
#define VERSION_MAJOR (0)
#define VERSION_MINOR (5)
#endif /* VERSION_H_ */

View File

@ -1,14 +1,47 @@
#include "axp2101.h"
#include "main.h"
#include "stm32_assert.h"
#include "hal_interface.h"
#define AXP2101_DEV_I2C_ID 0x68
extern I2C_HandleTypeDef hi2c2;
static uint8_t statusRegister[XPOWERS_AXP2101_INTSTS_CNT] = {0};
static uint8_t intRegister[XPOWERS_AXP2101_INTSTS_CNT] = {0};
__STATIC_INLINE int8_t readRegister(uint8_t reg, uint8_t *buf, uint8_t length) {
HAL_StatusTypeDef status;
status = HAL_I2C_Mem_Read(&hi2c2, AXP2101_DEV_I2C_ID, reg, length, buf, 1, 60);
if (status != HAL_OK)
return -1;
return 0;
}
__STATIC_INLINE uint16_t readRegisterH6L8(uint8_t highReg, uint8_t lowReg) {
uint8_t h6;
uint8_t l8;
int8_t h6_s = readRegister(highReg, &h6, 1);
int8_t l8_s = readRegister(lowReg, &l8, 1);
if (h6_s == -1 || l8_s == -1)
return 0;
return ((h6 & 0x3F) << 8) | l8;
}
__STATIC_INLINE uint16_t readRegisterH5L8(uint8_t highReg, uint8_t lowReg) {
uint8_t h5;
uint8_t l8;
int8_t h5_s = readRegister(highReg, &h5, 1);
int8_t l8_s = readRegister(lowReg, &l8, 1);
if (h5_s == -1 || l8_s == -1)
return 0;
return ((h5 & 0x1F) << 8) | l8;
}
__STATIC_INLINE uint8_t clrRegisterBit(uint8_t registers, uint8_t bit) {
uint8_t reg_value = 0;
HAL_StatusTypeDef status;
@ -140,14 +173,14 @@ uint8_t AXP2101_isBatRemoveIrq(void) {
return 0;
}
uint8_t AXP2101_isPekeyShortPressIrq(void) {
uint8_t AXP2101_isPkeyShortPressIrq(void) {
uint8_t mask = XPOWERS_AXP2101_PKEY_SHORT_IRQ >> 8;
if (intRegister[1] & mask)
return ((statusRegister[1] & mask) == mask);
return 0;
}
uint8_t AXP2101_isPekeyLongPressIrq(void) {
uint8_t AXP2101_isPkeyLongPressIrq(void) {
uint8_t mask = XPOWERS_AXP2101_PKEY_LONG_IRQ >> 8;
if (intRegister[1] & mask)
return ((statusRegister[1] & mask) == mask);
@ -278,6 +311,12 @@ uint32_t AXP2101_setLowBatShutdownThreshold(uint8_t opt) {
}
int8_t AXP2101_readDataBuffer(uint8_t *data, uint8_t size) {
if (size > XPOWERS_AXP2101_DATA_BUFFER_SIZE)
return -1;
return readRegister(XPOWERS_AXP2101_DATA_BUFFER1, data, size);
}
uint8_t AXP2101_isBatteryConnect(void) {
return getRegisterBit(XPOWERS_AXP2101_STATUS1, 3);
}
@ -290,6 +329,26 @@ uint8_t AXP2101_isCharging(void) {
return (reg_value >> 5) == 0x01;
}
uint8_t AXP2101_isDischarge(void) {
uint8_t res = 0;
readRegister(XPOWERS_AXP2101_STATUS2, &res, 1);
return (res >> 5) == 0x02;
}
uint8_t AXP2101_isStandby(void) {
uint8_t res = 0;
readRegister(XPOWERS_AXP2101_STATUS2, &res, 1);
return (res >> 5) == 0x00;
}
uint8_t AXP2101_isVbusGood(void) {
return getRegisterBit(XPOWERS_AXP2101_STATUS1, 5);
}
uint8_t AXP2101_isVbusIn(void) {
return getRegisterBit(XPOWERS_AXP2101_STATUS2, 3) == 0 && AXP2101_isVbusGood();
}
uint32_t AXP2101_getIrqStatus(uint32_t* out_value) {
HAL_StatusTypeDef status = HAL_OK;
@ -311,3 +370,30 @@ uint32_t AXP2101_getBatteryPercent(uint8_t* out_value) {
return HAL_I2C_Mem_Read(&hi2c2, AXP2101_DEV_I2C_ID, XPOWERS_AXP2101_BAT_PERCENT_DATA, 1, out_value, 1, 60);
}
xpowers_chg_status_t AXP2101_getChargerStatus(void) {
uint8_t val = 0;
int8_t status = readRegister(XPOWERS_AXP2101_STATUS2, &val, 1);
if (status == -1)
return XPOWERS_AXP2101_CHG_STOP_STATE;
val &= 0x07;
return (xpowers_chg_status_t)val;
}
uint16_t AXP2101_getBattVoltage(void) {
if (!AXP2101_isBatteryConnect()) {
return 0;
}
return readRegisterH5L8(XPOWERS_AXP2101_ADC_DATA_RELUST0, XPOWERS_AXP2101_ADC_DATA_RELUST1);
}
uint16_t AXP2101_getVbusVoltage(void) {
if (!AXP2101_isVbusIn()) {
return 0;
}
return readRegisterH6L8(XPOWERS_AXP2101_ADC_DATA_RELUST4, XPOWERS_AXP2101_ADC_DATA_RELUST5);
}
uint16_t AXP2101_getSystemVoltage(void) {
return readRegisterH6L8(XPOWERS_AXP2101_ADC_DATA_RELUST6, XPOWERS_AXP2101_ADC_DATA_RELUST7);
}

View File

@ -1,8 +1,12 @@
#include "backlight.h"
#include "main.h"
#include "hal_interface.h"
#include "regs.h"
extern TIM_HandleTypeDef htim1;
extern TIM_HandleTypeDef htim3;
// LCD backlight curve based on brightness measurements for specific value of PWM duty cycle.
// Using this, I've established a custom command curve.
#define LCD_BCKL_STEPS 10

View File

@ -1,5 +1,6 @@
#include "batt.h"
#include "main.h"
#include "hal_interface.h"
#include "axp2101.h"

868
Core/Src/hal_interface.c Normal file
View File

@ -0,0 +1,868 @@
/**
******************************************************************************
* @file hal_interface.c
* @brief Central access to STM32-HAL definitions and
* related functions.
******************************************************************************
* @attention
*
* Copyright (c) 2025 C.ARE (JackCarterSmith).
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
*
******************************************************************************
*
*/
#include "hal_interface.h"
#include "stm32f1xx_hal_flash_ex.h"
I2C_HandleTypeDef hi2c1;
I2C_HandleTypeDef hi2c2;
RTC_HandleTypeDef hrtc;
TIM_HandleTypeDef htim1;
TIM_HandleTypeDef htim2;
TIM_HandleTypeDef htim3;
#ifdef DEBUG
UART_HandleTypeDef huart1;
#endif
#ifdef UART_PICO_INTERFACE
UART_HandleTypeDef huart3;
#endif
volatile RTC_TimeTypeDef_u rtc_alarm_time = {.raw = 0x00000000};
volatile RTC_DateTypeDef_u rtc_alarm_date = {.raw = 0x00010101};
static void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim);
/**
* @brief System Clock Configuration
* @retval None
*/
void SystemClock_Config(void) {
LL_FLASH_SetLatency(LL_FLASH_LATENCY_0);
while(LL_FLASH_GetLatency()!= LL_FLASH_LATENCY_0) {}
LL_RCC_HSE_Enable();
/* Wait till HSE is ready */
while(LL_RCC_HSE_IsReady() != 1) {}
LL_RCC_LSI_Enable();
/* Wait till LSI is ready */
while(LL_RCC_LSI_IsReady() != 1) {}
LL_PWR_EnableBkUpAccess();
if(LL_RCC_GetRTCClockSource() != LL_RCC_RTC_CLKSOURCE_LSE) {
LL_RCC_ForceBackupDomainReset();
LL_RCC_ReleaseBackupDomainReset();
}
LL_RCC_LSE_Enable();
/* Wait till LSE is ready */
while(LL_RCC_LSE_IsReady() != 1) {}
if(LL_RCC_GetRTCClockSource() != LL_RCC_RTC_CLKSOURCE_LSE) {
LL_RCC_SetRTCClockSource(LL_RCC_RTC_CLKSOURCE_LSE);
}
LL_RCC_EnableRTC();
LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_2);
LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1);
LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1);
LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_HSE);
/* Wait till System clock is ready */
while(LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_HSE) {}
LL_SetSystemCoreClock(4000000);
/* Update the time base */
if (HAL_InitTick (TICK_INT_PRIORITY) != HAL_OK)
Error_Handler();
}
/**
* @brief I2C1 Initialization Function
* @param None
* @retval None
*/
static void MX_I2C1_Init(void) {
hi2c1.Instance = I2C1;
hi2c1.Init.ClockSpeed = 10000;
hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2;
hi2c1.Init.OwnAddress1 = 62;
hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c1.Init.OwnAddress2 = 0;
hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c1) != HAL_OK)
Error_Handler();
}
/**
* @brief I2C2 Initialization Function
* @param None
* @retval None
*/
static void MX_I2C2_Init(void) {
hi2c2.Instance = I2C2;
hi2c2.Init.ClockSpeed = 100000;
hi2c2.Init.DutyCycle = I2C_DUTYCYCLE_2;
hi2c2.Init.OwnAddress1 = 0;
hi2c2.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
hi2c2.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
hi2c2.Init.OwnAddress2 = 0;
hi2c2.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
hi2c2.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
if (HAL_I2C_Init(&hi2c2) != HAL_OK)
Error_Handler();
}
/**
* @brief IWDG Initialization Function
* @param None
* @retval None
*/
static void MX_IWDG_Init(void) {
LL_IWDG_Enable(IWDG);
LL_IWDG_EnableWriteAccess(IWDG);
LL_IWDG_SetPrescaler(IWDG, LL_IWDG_PRESCALER_32);
LL_IWDG_SetReloadCounter(IWDG, 4095);
while (LL_IWDG_IsReady(IWDG) != 1) {}
LL_IWDG_ReloadCounter(IWDG);
}
/**
* @brief RTC Initialization Function
* @param None
* @retval None
*/
static void MX_RTC_Init(void) {
RTC_TimeTypeDef sTime = {0};
RTC_DateTypeDef DateToUpdate = {0};
/** Initialize RTC Only
*/
hrtc.Instance = RTC;
hrtc.Init.AsynchPrediv = RTC_AUTO_1_SECOND;
hrtc.Init.OutPut = RTC_OUTPUTSOURCE_NONE;
if (HAL_RTC_Init(&hrtc) != HAL_OK)
Error_Handler();
/** Initialize RTC and set the Time and Date
*/
sTime.Hours = 0x0;
sTime.Minutes = 0x0;
sTime.Seconds = 0x0;
if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK)
Error_Handler();
DateToUpdate.WeekDay = RTC_WEEKDAY_MONDAY;
DateToUpdate.Month = RTC_MONTH_JANUARY;
DateToUpdate.Date = 0x1;
DateToUpdate.Year = 0x0;
if (HAL_RTC_SetDate(&hrtc, &DateToUpdate, RTC_FORMAT_BCD) != HAL_OK)
Error_Handler();
}
/**
* @brief RTC fake initialization Function, used when RTC is already alive (after a wake-up reset)
* @param None
* @retval None
*/
static void MX_RTC_Init2(void) {
hrtc.Instance = RTC;
hrtc.Init.AsynchPrediv = RTC_AUTO_1_SECOND;
hrtc.Init.OutPut = RTC_OUTPUTSOURCE_NONE;
hrtc.Lock = HAL_UNLOCKED;
HAL_RTC_MspInit(&hrtc);
hrtc.State = HAL_RTC_STATE_READY;
}
/**
* @brief TIM1 Initialization Function
* @param None
* @retval None
*/
static void MX_TIM1_Init(void) {
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
TIM_BreakDeadTimeConfigTypeDef sBreakDeadTimeConfig = {0};
htim1.Instance = TIM1;
htim1.Init.Prescaler = 0;
htim1.Init.CounterMode = TIM_COUNTERMODE_UP;
htim1.Init.Period = 800;
htim1.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim1.Init.RepetitionCounter = 0;
htim1.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
if (HAL_TIM_Base_Init(&htim1) != HAL_OK)
Error_Handler();
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim1, &sClockSourceConfig) != HAL_OK)
Error_Handler();
if (HAL_TIM_PWM_Init(&htim1) != HAL_OK)
Error_Handler();
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim1, &sMasterConfig) != HAL_OK)
Error_Handler();
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCNPolarity = TIM_OCNPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
sConfigOC.OCIdleState = TIM_OCIDLESTATE_RESET;
sConfigOC.OCNIdleState = TIM_OCNIDLESTATE_RESET;
if (HAL_TIM_PWM_ConfigChannel(&htim1, &sConfigOC, TIM_CHANNEL_1) != HAL_OK)
Error_Handler();
sBreakDeadTimeConfig.OffStateRunMode = TIM_OSSR_DISABLE;
sBreakDeadTimeConfig.OffStateIDLEMode = TIM_OSSI_DISABLE;
sBreakDeadTimeConfig.LockLevel = TIM_LOCKLEVEL_OFF;
sBreakDeadTimeConfig.DeadTime = 0;
sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
if (HAL_TIMEx_ConfigBreakDeadTime(&htim1, &sBreakDeadTimeConfig) != HAL_OK)
Error_Handler();
HAL_TIM_MspPostInit(&htim1);
}
/**
* @brief TIM2 Initialization Function
* @param None
* @retval None
*/
static void MX_TIM2_Init(void) {
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
htim2.Instance = TIM2;
htim2.Init.Prescaler = 4-1;
htim2.Init.CounterMode = TIM_COUNTERMODE_UP;
htim2.Init.Period = 1000;
htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim2.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
if (HAL_TIM_Base_Init(&htim2) != HAL_OK)
Error_Handler();
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim2, &sClockSourceConfig) != HAL_OK)
Error_Handler();
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)
Error_Handler();
}
/**
* @brief TIM3 Initialization Function
* @param None
* @retval None
*/
static void MX_TIM3_Init(void) {
TIM_ClockConfigTypeDef sClockSourceConfig = {0};
TIM_MasterConfigTypeDef sMasterConfig = {0};
TIM_OC_InitTypeDef sConfigOC = {0};
htim3.Instance = TIM3;
htim3.Init.Prescaler = 0;
htim3.Init.CounterMode = TIM_COUNTERMODE_UP;
htim3.Init.Period = 512;
htim3.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;
htim3.Init.AutoReloadPreload = TIM_AUTORELOAD_PRELOAD_ENABLE;
if (HAL_TIM_Base_Init(&htim3) != HAL_OK)
Error_Handler();
sClockSourceConfig.ClockSource = TIM_CLOCKSOURCE_INTERNAL;
if (HAL_TIM_ConfigClockSource(&htim3, &sClockSourceConfig) != HAL_OK)
Error_Handler();
if (HAL_TIM_PWM_Init(&htim3) != HAL_OK)
Error_Handler();
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;
sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;
if (HAL_TIMEx_MasterConfigSynchronization(&htim3, &sMasterConfig) != HAL_OK)
Error_Handler();
sConfigOC.OCMode = TIM_OCMODE_PWM1;
sConfigOC.Pulse = 0;
sConfigOC.OCPolarity = TIM_OCPOLARITY_HIGH;
sConfigOC.OCFastMode = TIM_OCFAST_DISABLE;
if (HAL_TIM_PWM_ConfigChannel(&htim3, &sConfigOC, TIM_CHANNEL_3) != HAL_OK)
Error_Handler();
HAL_TIM_MspPostInit(&htim3);
}
/**
* @brief USART1 Initialization Function
* @param None
* @retval None
*/
static void MX_USART1_UART_Init(void) {
#ifdef DEBUG
huart1.Instance = USART1;
huart1.Init.BaudRate = 115200;
huart1.Init.WordLength = UART_WORDLENGTH_8B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_NONE;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart1) != HAL_OK)
Error_Handler();
#endif
}
/**
* @brief USART3 Initialization Function
* @param None
* @retval None
*/
static void MX_USART3_UART_Init(void) {
#ifdef UART_PICO_INTERFACE
huart3.Instance = USART3;
huart3.Init.BaudRate = 115200;
huart3.Init.WordLength = UART_WORDLENGTH_8B;
huart3.Init.StopBits = UART_STOPBITS_1;
huart3.Init.Parity = UART_PARITY_NONE;
huart3.Init.Mode = UART_MODE_TX_RX;
huart3.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart3.Init.OverSampling = UART_OVERSAMPLING_16;
if (HAL_UART_Init(&huart3) != HAL_OK)
Error_Handler();
#endif
}
/**
* @brief GPIO Initialization Function
* @param None
* @retval None
*/
static void MX_GPIO_Init(void) {
LL_EXTI_InitTypeDef EXTI_InitStruct = {0};
LL_GPIO_InitTypeDef GPIO_InitStruct = {0};
/* GPIO Ports Clock Enable */
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOC);
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOD);
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOA);
LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_GPIOB);
/**/
LL_GPIO_SetOutputPin(GPIOC, SYS_LED_Pin|COL_1_Pin|COL_2_Pin|COL_3_Pin
|COL_4_Pin|COL_5_Pin|COL_6_Pin|COL_7_Pin
|COL_8_Pin);
/**/
LL_GPIO_ResetOutputPin(GPIOA, PICO_EN_Pin|SP_AMP_EN_Pin);
/**/
GPIO_InitStruct.Pin = SYS_LED_Pin;
GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;
LL_GPIO_Init(SYS_LED_GPIO_Port, &GPIO_InitStruct);
/**/
GPIO_InitStruct.Pin = COL_1_Pin|COL_2_Pin|COL_3_Pin|COL_4_Pin
|COL_5_Pin|COL_6_Pin|COL_7_Pin|COL_8_Pin;
GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_OPENDRAIN;
LL_GPIO_Init(GPIOC, &GPIO_InitStruct);
#ifndef UART_PICO_INTERFACE
GPIO_InitStruct.Pin = PICO_IRQ_Pin;
GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_HIGH;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
LL_GPIO_Init(GPIOC, &GPIO_InitStruct);
#endif
/**/
GPIO_InitStruct.Pin = ROW_1_Pin|ROW_2_Pin|ROW_3_Pin|ROW_4_Pin
|ROW_5_Pin|ROW_6_Pin|ROW_7_Pin|ROW_8_Pin;
GPIO_InitStruct.Mode = LL_GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/**/
GPIO_InitStruct.Pin = KEY_1_Pin|KEY_2_Pin|KEY_3_Pin|KEY_9_Pin
|KEY_10_Pin|KEY_11_Pin|KEY_12_Pin|KEY_4_Pin
|KEY_5_Pin|KEY_6_Pin|KEY_7_Pin|KEY_8_Pin;
GPIO_InitStruct.Mode = LL_GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = LL_GPIO_PULL_UP;
LL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/**/
GPIO_InitStruct.Pin = LL_GPIO_PIN_11|LL_GPIO_PIN_12|LL_GPIO_PIN_15;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;
LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/**/
GPIO_InitStruct.Pin = PICO_EN_Pin|SP_AMP_EN_Pin;
GPIO_InitStruct.Mode = LL_GPIO_MODE_OUTPUT;
GPIO_InitStruct.Speed = LL_GPIO_SPEED_FREQ_LOW;
GPIO_InitStruct.OutputType = LL_GPIO_OUTPUT_PUSHPULL;
LL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/**/
GPIO_InitStruct.Pin = HP_DET_Pin;
GPIO_InitStruct.Mode = LL_GPIO_MODE_FLOATING;
LL_GPIO_Init(HP_DET_GPIO_Port, &GPIO_InitStruct);
/**/
GPIO_InitStruct.Pin = LL_GPIO_PIN_2;
GPIO_InitStruct.Mode = LL_GPIO_MODE_ANALOG;
LL_GPIO_Init(GPIOD, &GPIO_InitStruct);
/**/
LL_GPIO_AF_SetEXTISource(LL_GPIO_AF_EXTI_PORTC, LL_GPIO_AF_EXTI_LINE9);
/**/
EXTI_InitStruct.Line_0_31 = LL_EXTI_LINE_9;
EXTI_InitStruct.LineCommand = ENABLE;
EXTI_InitStruct.Mode = LL_EXTI_MODE_IT;
EXTI_InitStruct.Trigger = LL_EXTI_TRIGGER_FALLING;
LL_EXTI_Init(&EXTI_InitStruct);
/**/
LL_GPIO_SetPinMode(PMU_IRQ_GPIO_Port, PMU_IRQ_Pin, LL_GPIO_MODE_FLOATING);
/* EXTI interrupt init*/
NVIC_SetPriority(EXTI9_5_IRQn, NVIC_EncodePriority(NVIC_GetPriorityGrouping(),3, 0));
NVIC_EnableIRQ(EXTI9_5_IRQn);
}
/**
* Initializes the Global MSP.
*/
void HAL_MspInit(void) {
__HAL_RCC_AFIO_CLK_ENABLE();
__HAL_RCC_PWR_CLK_ENABLE();
/* System interrupt init*/
/** DISABLE: JTAG-DP Disabled and SW-DP Disabled
*/
__HAL_AFIO_REMAP_SWJ_DISABLE();
}
/**
* @brief I2C MSP Initialization
* This function configures the hardware resources used in this example
* @param hi2c: I2C handle pointer
* @retval None
*/
void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c) {
GPIO_InitTypeDef GPIO_InitStruct = {0};
if (hi2c->Instance == I2C1) {
__HAL_RCC_GPIOB_CLK_ENABLE();
/**I2C1 GPIO Configuration
PB8 ------> I2C1_SCL
PB9 ------> I2C1_SDA
*/
GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
__HAL_AFIO_REMAP_I2C1_ENABLE();
/* Peripheral clock enable */
__HAL_RCC_I2C1_CLK_ENABLE();
/* I2C1 interrupt Init */
HAL_NVIC_SetPriority(I2C1_EV_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(I2C1_EV_IRQn);
HAL_NVIC_SetPriority(I2C1_ER_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(I2C1_ER_IRQn);
} else if (hi2c->Instance == I2C2) {
__HAL_RCC_GPIOB_CLK_ENABLE();
/**I2C2 GPIO Configuration
PB10 ------> I2C2_SCL
PB11 ------> I2C2_SDA
*/
GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* Peripheral clock enable */
__HAL_RCC_I2C2_CLK_ENABLE();
}
}
/**
* @brief I2C MSP De-Initialization
* This function freeze the hardware resources used in this example
* @param hi2c: I2C handle pointer
* @retval None
*/
void HAL_I2C_MspDeInit(I2C_HandleTypeDef* hi2c) {
if (hi2c->Instance == I2C1) {
/* Peripheral clock disable */
__HAL_RCC_I2C1_CLK_DISABLE();
/**I2C1 GPIO Configuration
PB8 ------> I2C1_SCL
PB9 ------> I2C1_SDA
*/
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_8);
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_9);
/* I2C1 interrupt DeInit */
HAL_NVIC_DisableIRQ(I2C1_EV_IRQn);
HAL_NVIC_DisableIRQ(I2C1_ER_IRQn);
} else if (hi2c->Instance == I2C2) {
/* Peripheral clock disable */
__HAL_RCC_I2C2_CLK_DISABLE();
/**I2C2 GPIO Configuration
PB10 ------> I2C2_SCL
PB11 ------> I2C2_SDA
*/
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_10);
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_11);
}
}
/**
* @brief RTC MSP Initialization
* This function configures the hardware resources used in this example
* @param hrtc: RTC handle pointer
* @retval None
*/
void HAL_RTC_MspInit(RTC_HandleTypeDef* hrtc) {
if (hrtc->Instance == RTC) {
HAL_PWR_EnableBkUpAccess();
/* Enable BKP CLK enable for backup registers */
__HAL_RCC_BKP_CLK_ENABLE();
/* Peripheral clock enable */
__HAL_RCC_RTC_ENABLE();
/* RTC interrupt Init */
HAL_NVIC_SetPriority(RTC_Alarm_IRQn, 0, 0);
HAL_NVIC_EnableIRQ(RTC_Alarm_IRQn);
}
}
/**
* @brief RTC MSP De-Initialization
* This function freeze the hardware resources used in this example
* @param hrtc: RTC handle pointer
* @retval None
*/
void HAL_RTC_MspDeInit(RTC_HandleTypeDef* hrtc) {
if (hrtc->Instance == RTC) {
/* Peripheral clock disable */
__HAL_RCC_RTC_DISABLE();
/* RTC interrupt DeInit */
HAL_NVIC_DisableIRQ(RTC_Alarm_IRQn);
}
}
/**
* @brief TIM_Base MSP Initialization
* This function configures the hardware resources used in this example
* @param htim_base: TIM_Base handle pointer
* @retval None
*/
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base) {
if (htim_base->Instance == TIM1) {
/* Peripheral clock enable */
__HAL_RCC_TIM1_CLK_ENABLE();
} else if (htim_base->Instance == TIM2) {
/* Peripheral clock enable */
__HAL_RCC_TIM2_CLK_ENABLE();
/* TIM2 interrupt Init */
HAL_NVIC_SetPriority(TIM2_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(TIM2_IRQn);
} else if (htim_base->Instance == TIM3) {
/* Peripheral clock enable */
__HAL_RCC_TIM3_CLK_ENABLE();
}
}
void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if (htim->Instance == TIM1) {
__HAL_RCC_GPIOA_CLK_ENABLE();
/**TIM1 GPIO Configuration
PA8 ------> TIM1_CH1
*/
GPIO_InitStruct.Pin = GPIO_PIN_8;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
} else if (htim->Instance == TIM3) {
__HAL_RCC_GPIOC_CLK_ENABLE();
/**TIM3 GPIO Configuration
PC8 ------> TIM3_CH3
*/
GPIO_InitStruct.Pin = GPIO_PIN_8;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
__HAL_AFIO_REMAP_TIM3_ENABLE();
}
}
/**
* @brief TIM_Base MSP De-Initialization
* This function freeze the hardware resources used in this example
* @param htim_base: TIM_Base handle pointer
* @retval None
*/
void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* htim_base) {
if (htim_base->Instance == TIM1) {
/* Peripheral clock disable */
__HAL_RCC_TIM1_CLK_DISABLE();
} else if (htim_base->Instance == TIM2) {
/* Peripheral clock disable */
__HAL_RCC_TIM2_CLK_DISABLE();
/* TIM2 interrupt DeInit */
HAL_NVIC_DisableIRQ(TIM2_IRQn);
} else if (htim_base->Instance == TIM3) {
/* Peripheral clock disable */
__HAL_RCC_TIM3_CLK_DISABLE();
}
}
/**
* @brief UART MSP Initialization
* This function configures the hardware resources used in this example
* @param huart: UART handle pointer
* @retval None
*/
void HAL_UART_MspInit(UART_HandleTypeDef* huart) {
GPIO_InitTypeDef GPIO_InitStruct = {0};
#ifdef DEBUG
if (huart->Instance == USART1) {
/* Peripheral clock enable */
__HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**USART1 GPIO Configuration
PA9 ------> USART1_TX
PA10 ------> USART1_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USART1 interrupt Init */
HAL_NVIC_SetPriority(USART1_IRQn, 4, 0);
HAL_NVIC_EnableIRQ(USART1_IRQn);
} else
#endif
#ifdef UART_PICO_INTERFACE
if (huart->Instance == USART3) {
/* Peripheral clock enable */
__HAL_RCC_USART3_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
/**USART3 GPIO Configuration
PC10 ------> USART3_TX
PC11 ------> USART3_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
__HAL_AFIO_REMAP_USART3_PARTIAL();
/* USART3 interrupt Init */
HAL_NVIC_SetPriority(USART3_IRQn, 3, 0);
HAL_NVIC_EnableIRQ(USART3_IRQn);
}
#else
NULL;
#endif
}
/**
* @brief UART MSP De-Initialization
* This function freeze the hardware resources used in this example
* @param huart: UART handle pointer
* @retval None
*/
void HAL_UART_MspDeInit(UART_HandleTypeDef* huart) {
#ifdef DEBUG
if (huart->Instance == USART1) {
/* Peripheral clock disable */
__HAL_RCC_USART1_CLK_DISABLE();
/**USART1 GPIO Configuration
PA9 ------> USART1_TX
PA10 ------> USART1_RX
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);
/* USART1 interrupt DeInit */
HAL_NVIC_DisableIRQ(USART1_IRQn);
} else
#endif
#ifdef UART_PICO_INTERFACE
if (huart->Instance == USART3) {
/* Peripheral clock disable */
__HAL_RCC_USART3_CLK_DISABLE();
/**USART3 GPIO Configuration
PC10 ------> USART3_TX
PC11 ------> USART3_RX
*/
HAL_GPIO_DeInit(GPIOC, GPIO_PIN_10|GPIO_PIN_11);
/* USART3 interrupt DeInit */
HAL_NVIC_DisableIRQ(USART3_IRQn);
}
#else
NULL;
#endif
}
/**
* @brief This function is executed in case of error occurrence.
* @retval None
*/
void Error_Handler(void) {
// User can add his own implementation to report the HAL error return state
//TODO: replace with dedicated, non-blocking, error handler
__disable_irq();
while (1) {
//LL_GPIO_TogglePin(SYS_LED_GPIO_Port, SYS_LED_Pin);
HAL_Delay(500);
}
}
#ifdef USE_FULL_ASSERT
/**
* @brief Reports the name of the source file and the source line number
* where the assert_param error has occurred.
* @param file: pointer to the source file name
* @param line: assert_param error line source number
* @retval None
*/
void assert_failed(uint8_t *file, uint32_t line)
{
/* USER CODE BEGIN 6 */
/* User can add his own implementation to report the file name and line number,
ex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
/* USER CODE END 6 */
}
#endif /* USE_FULL_ASSERT */
void flash_one_time(uint32_t ts, uint8_t restore_status) {
for (size_t i = 0; i < ts; i++) {
//#ifndef DEBUG
// LL_IWDG_ReloadCounter(IWDG);
//#endif
LL_GPIO_ResetOutputPin(SYS_LED_GPIO_Port, SYS_LED_Pin);
HAL_Delay(400);
LL_GPIO_SetOutputPin(SYS_LED_GPIO_Port, SYS_LED_Pin);
HAL_Delay(200);
}
if (restore_status)
LL_GPIO_ResetOutputPin(SYS_LED_GPIO_Port, SYS_LED_Pin);
else
LL_GPIO_SetOutputPin(SYS_LED_GPIO_Port, SYS_LED_Pin);
}
/**
* @brief This function is executed at the start of the program to initialize all peripherals.
* @retval None
*/
HAL_StatusTypeDef HAL_Interface_init(void) {
HAL_StatusTypeDef result = HAL_OK;
FLASH_OBProgramInitTypeDef flash_s;
result |= HAL_Init();
if (result != HAL_OK)
return result;
SystemClock_Config();
// Control wake-up state
//if (__HAL_RCC_GET_FLAG(RCC_FLAG_PINRST))
//__HAL_RCC_CLEAR_RESET_FLAGS();
// Use SRAM backup registers to check if we have soft-reset
HAL_PWR_EnableBkUpAccess();
MX_GPIO_Init();
MX_I2C1_Init();
MX_I2C2_Init();
if (HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR1) != 0)
MX_RTC_Init2();
else
MX_RTC_Init();
MX_USART1_UART_Init();
MX_USART3_UART_Init();
//#ifndef DEBUG
// MX_IWDG_Init();
//#endif
MX_TIM1_Init();
MX_TIM3_Init();
MX_TIM2_Init();
// Check options registers values
HAL_FLASHEx_OBGetConfig(&flash_s);
//if ((flash_s.USERConfig & (OB_STOP_NO_RST | OB_STDBY_NO_RST)) != 0) {
if ((flash_s.USERConfig & (OB_STOP_NO_RST | OB_STDBY_NO_RST)) == 0) {
HAL_FLASH_Unlock();
HAL_FLASH_OB_Unlock();
//flash_s.USERConfig &= (uint8_t)~(OB_STOP_NO_RST | OB_STDBY_NO_RST); // Enable reset when sleep
flash_s.USERConfig |= (uint8_t)(OB_STOP_NO_RST | OB_STDBY_NO_RST); // Disable reset when sleep
HAL_FLASHEx_OBProgram(&flash_s);
HAL_FLASH_OB_Launch(); // Reset system
// We should never reach this point
for ( ;; ) {}
}
return result;
}

View File

@ -1,4 +1,6 @@
#include "keyboard.h"
#include "hal_interface.h"
#include "regs.h"
#include "backlight.h"
#include "batt.h"
@ -101,12 +103,16 @@ static const struct gpio_pin btn_pins[12] = {
static struct list_item keys_list[KEY_LIST_SIZE];
static lock_callback _lock_callback = NULL;
static key_callback _key_callback= NULL;
static uint32_t last_process_time;
static uint32_t last_process_time = 0;
static uint8_t mods[MOD_LAST];
static uint8_t capslock_changed = 0;
static uint8_t capslock = 0;
static uint8_t numlock_changed = 0;
static uint8_t numlock = 0;
static uint16_t hold_period = KEY_HOLD_TIME;
uint8_t io_matrix[9] = {0}; //for IO matrix,last byte is the restore key(c64 only)
uint8_t js_bits = 0xFF; // c64 joystick bits
inline void keyboard_set_key_callback(key_callback callback) {
@ -125,6 +131,14 @@ inline uint8_t keyboard_get_numlock(void) {
return numlock & 0x1;
}
inline uint16_t keyboard_get_hold_period(void) {
return hold_period;
}
inline void keyboard_set_hold_period(uint16_t value) {
hold_period = value;
}
static void transition_to(struct list_item * const p_item, const enum key_state next_state) {
uint8_t output = 1;
const struct entry * const p_entry = p_item->p_entry;
@ -267,7 +281,7 @@ static void next_item_state(struct list_item* const p_item, const uint8_t presse
break;
case KEY_STATE_PRESSED:
if (uptime_ms() > p_item->hold_start_time + KEY_HOLD_TIME) {
if (uptime_ms() - p_item->hold_start_time > hold_period) {
transition_to(p_item, KEY_STATE_HOLD);
p_item->last_repeat_time = uptime_ms();
} else if (!pressed)
@ -278,8 +292,8 @@ static void next_item_state(struct list_item* const p_item, const uint8_t presse
if (!pressed)
transition_to(p_item, KEY_STATE_RELEASED);
else {
if (uptime_ms() > p_item->hold_start_time + KEY_HOLD_TIME) {
if(uptime_ms() > p_item->last_repeat_time + KEY_REPEAT_TIME) {
if (uptime_ms() - p_item->hold_start_time > hold_period) {
if(uptime_ms() - p_item->last_repeat_time > KEY_REPEAT_TIME) {
transition_to(p_item, KEY_STATE_HOLD);
p_item->last_repeat_time = uptime_ms();
}
@ -300,7 +314,7 @@ static void next_item_state(struct list_item* const p_item, const uint8_t presse
void keyboard_process(void) {
js_bits = 0xFF;
if (uptime_ms() <= (last_process_time + KEY_POLL_TIME))
if (uptime_ms() - last_process_time <= reg_get_value(REG_ID_FRQ))
return;
// Scan for columns
@ -403,6 +417,7 @@ void keyboard_process(void) {
}
io_matrix[8] = 0xFF;
last_process_time = uptime_ms();
}
last_process_time = uptime_ms();
}

File diff suppressed because it is too large Load Diff

View File

@ -1,8 +1,12 @@
#include "regs.h"
#include "main.h"
#include "eeprom.h"
#include "backlight.h"
#include "hal_interface.h"
#include "stm32f1xx_hal_rtc_ex.h"
#include "eeprom.h"
#include "version.h"
extern RTC_HandleTypeDef hrtc;
static uint8_t regs[REG_ID_LAST] = {0};
static uint8_t regs_unsync[REG_ID_LAST] = {0};
@ -57,21 +61,37 @@ inline void reg_set_bit(enum reg_id reg, uint8_t bit) {
| 0 | CFG_OVERFLOW_ON | When a FIFO overflow happens, should the new entry still be pushed, overwriting the oldest one. If 0 then new entry is lost. |
*/
void reg_init(void) {
uint16_t buff;
uint32_t buff;
regs[REG_ID_VER] = (uint8_t)((VERSION_MAJOR << 4) | VERSION_MINOR); // 1.2 => (0x1 << 4) | 0x2
EEPROM_ReadVariable(EEPROM_VAR_CFG, (EEPROM_Value*)&buff);
regs[REG_ID_CFG] = (uint8_t)(buff & 0xFF);
regs[REG_ID_CFG] = (uint8_t)((buff >> 8) & 0xFF);
regs[REG_ID_INT_CFG] = (uint8_t)(buff & 0xFF);
EEPROM_ReadVariable(EEPROM_VAR_KBD, (EEPROM_Value*)&buff);
regs[REG_ID_DEB] = (uint8_t)((buff >> 8) & 0xFF);
//regs[REG_ID_DEB] = (uint8_t)((buff >> 8) & 0xFF);
regs[REG_ID_FRQ] = (uint8_t)(buff & 0xFF);
EEPROM_ReadVariable(EEPROM_VAR_BCKL, (EEPROM_Value*)&buff);
regs[REG_ID_BKL] = (uint8_t)((buff >> 8) & 0xFF);
regs[REG_ID_BK2] = (uint8_t)(buff & 0xFF);
buff = 0;
buff |= HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR2);
buff |= HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR3) << 16;
regs[REG_ID_RTC_CFG] = (uint8_t)(buff & 0xFF);
rtc_alarm_time.raw = (uint8_t)((buff >> 8) & 0xFFFFFF);
buff = 0;
buff |= HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR4);
buff |= HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR5) << 16;
rtc_alarm_date.raw = buff;
regs[REG_ID_BAT] = 0; //default .no battery ,no charging
regs[REG_ID_TYP] = 0xCA; // That's me :3
eeprom_refresh_counter = uptime_ms();
}
@ -87,14 +107,24 @@ uint32_t reg_check_and_save_eeprom(void) {
if (need_save == 1) {
if (regs_unsync[REG_ID_CFG] == 1)
result |= EEPROM_WriteVariable(EEPROM_VAR_CFG, (EEPROM_Value)(uint16_t)regs[REG_ID_CFG], EEPROM_SIZE16);
result |= EEPROM_WriteVariable(EEPROM_VAR_CFG, (EEPROM_Value)(uint16_t)((regs[REG_ID_CFG] << 8) | regs[REG_ID_INT_CFG]), EEPROM_SIZE16);
if (regs_unsync[REG_ID_DEB] == 1 || regs_unsync[REG_ID_FRQ] == 1)
result |= EEPROM_WriteVariable(EEPROM_VAR_KBD, (EEPROM_Value)(uint16_t)((regs[REG_ID_DEB] << 8) | regs[REG_ID_FRQ]), EEPROM_SIZE16);
result |= EEPROM_WriteVariable(EEPROM_VAR_KBD, (EEPROM_Value)(uint32_t)((keyboard_get_hold_period() << 16) | regs[REG_ID_FRQ]), EEPROM_SIZE32);
if (regs_unsync[REG_ID_BKL] == 1 || regs_unsync[REG_ID_BK2] == 1)
result |= EEPROM_WriteVariable(EEPROM_VAR_BCKL, (EEPROM_Value)(uint16_t)((regs[REG_ID_BKL] << 8) | regs[REG_ID_BK2]), EEPROM_SIZE16);
if (regs_unsync[REG_ID_RTC_ALARM_TIME] == 1 || regs_unsync[REG_ID_RTC_CFG] == 1) {
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR2, ((rtc_alarm_time.raw & 0xFF) << 8) | regs[REG_ID_RTC_CFG]);
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR3, rtc_alarm_time.raw >> 16);
}
if (regs_unsync[REG_ID_RTC_ALARM_DATE] == 1) {
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR4, rtc_alarm_date.raw & 0xFFFF);
HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR5, rtc_alarm_date.raw >> 16);
}
for (size_t i = 0; i < REG_ID_LAST; i++)
regs_unsync[i] = 0;
}
@ -104,7 +134,7 @@ uint32_t reg_check_and_save_eeprom(void) {
void reg_sync(void) {
// Save user registers in EEPROM if unsynced every 1.5s
if (uptime_ms() > (eeprom_refresh_counter + 1500)) {
if (uptime_ms() - eeprom_refresh_counter > 1500) {
reg_check_and_save_eeprom();
eeprom_refresh_counter = uptime_ms();
}

81
Core/Src/rtc.c Normal file
View File

@ -0,0 +1,81 @@
#include "rtc.h"
#include "hal_interface.h"
#include "regs.h"
extern RTC_HandleTypeDef hrtc;
extern void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc) {
uint8_t rtc_conf = reg_get_value(REG_ID_RTC_CFG);
RTC_DateTypeDef date_s = {0};
uint8_t date_valid = 1;
if ((rtc_conf & RTC_CFG_DATE_ALARM) == RTC_CFG_DATE_ALARM) {
HAL_RTC_GetDate(hrtc, &date_s, RTC_FORMAT_BIN);
if (date_s.Year != rtc_alarm_date._s.Year ||
date_s.Month != rtc_alarm_date._s.Month ||
date_s.Date != rtc_alarm_date._s.Date)
date_valid = 0;
}
rtc_stop_alarm();
if (date_valid == 1) {
if ((rtc_conf & RTC_CFG_REARM) == RTC_CFG_REARM)
rtc_run_alarm();
} else {
rtc_run_alarm();
}
}
void i2cs_fill_buffer_RTC_date(uint8_t* const date_buff, const volatile RTC_DateTypeDef* const date_s) {
if (date_s == NULL || date_buff == NULL)
return;
date_buff[0] = date_s->Year;
date_buff[1] = date_s->Month;
date_buff[2] = date_s->Date;
date_buff[3] = date_s->WeekDay;
}
void i2cs_fill_buffer_RTC_time(uint8_t* const time_buff, const volatile RTC_TimeTypeDef* const time_s) {
if (time_s == NULL || time_buff == NULL)
return;
time_buff[0] = time_s->Hours;
time_buff[1] = time_s->Minutes;
time_buff[2] = time_s->Seconds;
}
void i2cs_RTC_date_from_buffer(volatile RTC_DateTypeDef* const date_s, const uint8_t* const date_buff) {
if (date_s == NULL || date_buff == NULL)
return;
date_s->Year = date_buff[0] <= 99? date_buff[0] : 99;
date_s->Month = (date_buff[1] > 0 && date_buff[1] <= 12)? date_buff[1] : 12;
date_s->Date = (date_buff[2] > 0 && date_buff[2] <= 99)? date_buff[2] : 99;
//data_s.WeekDay - this element is automatically recomputed
}
void i2cs_RTC_time_from_buffer(volatile RTC_TimeTypeDef* const time_s, const uint8_t* const time_buff) {
if (time_s == NULL || time_buff == NULL)
return;
time_s->Hours = time_buff[0] <= 23 ? time_buff[0] : 23;
time_s->Minutes = time_buff[1] <= 59 ? time_buff[1] : 59;
time_s->Seconds = time_buff[2] <= 59 ? time_buff[2] : 59;
}
inline uint32_t rtc_run_alarm(void) {
RTC_AlarmTypeDef alarm_s;
alarm_s.Alarm = RTC_ALARM_A;
alarm_s.AlarmTime.Hours = rtc_alarm_time._s.Hours;
alarm_s.AlarmTime.Minutes = rtc_alarm_time._s.Minutes;
alarm_s.AlarmTime.Seconds = rtc_alarm_time._s.Seconds;
return (uint32_t)HAL_RTC_SetAlarm_IT(&hrtc, &alarm_s, RTC_FORMAT_BIN);
}
inline uint32_t rtc_stop_alarm(void) {
return (uint32_t)HAL_RTC_DeactivateAlarm(&hrtc, RTC_ALARM_A);
}

View File

@ -1,468 +0,0 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file stm32f1xx_hal_msp.c
* @brief This file provides code for the MSP Initialization
* and de-Initialization codes.
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN TD */
/* USER CODE END TD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN Define */
/* USER CODE END Define */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN Macro */
/* USER CODE END Macro */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* External functions --------------------------------------------------------*/
/* USER CODE BEGIN ExternalFunctions */
/* USER CODE END ExternalFunctions */
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
void HAL_TIM_MspPostInit(TIM_HandleTypeDef *htim);
/**
* Initializes the Global MSP.
*/
void HAL_MspInit(void)
{
/* USER CODE BEGIN MspInit 0 */
/* USER CODE END MspInit 0 */
__HAL_RCC_AFIO_CLK_ENABLE();
__HAL_RCC_PWR_CLK_ENABLE();
/* System interrupt init*/
/** DISABLE: JTAG-DP Disabled and SW-DP Disabled
*/
__HAL_AFIO_REMAP_SWJ_DISABLE();
/* USER CODE BEGIN MspInit 1 */
/* USER CODE END MspInit 1 */
}
/**
* @brief I2C MSP Initialization
* This function configures the hardware resources used in this example
* @param hi2c: I2C handle pointer
* @retval None
*/
void HAL_I2C_MspInit(I2C_HandleTypeDef* hi2c)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(hi2c->Instance==I2C1)
{
/* USER CODE BEGIN I2C1_MspInit 0 */
/* USER CODE END I2C1_MspInit 0 */
__HAL_RCC_GPIOB_CLK_ENABLE();
/**I2C1 GPIO Configuration
PB8 ------> I2C1_SCL
PB9 ------> I2C1_SDA
*/
GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
__HAL_AFIO_REMAP_I2C1_ENABLE();
/* Peripheral clock enable */
__HAL_RCC_I2C1_CLK_ENABLE();
/* I2C1 interrupt Init */
HAL_NVIC_SetPriority(I2C1_EV_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(I2C1_EV_IRQn);
HAL_NVIC_SetPriority(I2C1_ER_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(I2C1_ER_IRQn);
/* USER CODE BEGIN I2C1_MspInit 1 */
/* USER CODE END I2C1_MspInit 1 */
}
else if(hi2c->Instance==I2C2)
{
/* USER CODE BEGIN I2C2_MspInit 0 */
/* USER CODE END I2C2_MspInit 0 */
__HAL_RCC_GPIOB_CLK_ENABLE();
/**I2C2 GPIO Configuration
PB10 ------> I2C2_SCL
PB11 ------> I2C2_SDA
*/
GPIO_InitStruct.Pin = GPIO_PIN_10|GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_AF_OD;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);
/* Peripheral clock enable */
__HAL_RCC_I2C2_CLK_ENABLE();
/* USER CODE BEGIN I2C2_MspInit 1 */
/* USER CODE END I2C2_MspInit 1 */
}
}
/**
* @brief I2C MSP De-Initialization
* This function freeze the hardware resources used in this example
* @param hi2c: I2C handle pointer
* @retval None
*/
void HAL_I2C_MspDeInit(I2C_HandleTypeDef* hi2c)
{
if(hi2c->Instance==I2C1)
{
/* USER CODE BEGIN I2C1_MspDeInit 0 */
/* USER CODE END I2C1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_I2C1_CLK_DISABLE();
/**I2C1 GPIO Configuration
PB8 ------> I2C1_SCL
PB9 ------> I2C1_SDA
*/
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_8);
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_9);
/* I2C1 interrupt DeInit */
HAL_NVIC_DisableIRQ(I2C1_EV_IRQn);
HAL_NVIC_DisableIRQ(I2C1_ER_IRQn);
/* USER CODE BEGIN I2C1_MspDeInit 1 */
/* USER CODE END I2C1_MspDeInit 1 */
}
else if(hi2c->Instance==I2C2)
{
/* USER CODE BEGIN I2C2_MspDeInit 0 */
/* USER CODE END I2C2_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_I2C2_CLK_DISABLE();
/**I2C2 GPIO Configuration
PB10 ------> I2C2_SCL
PB11 ------> I2C2_SDA
*/
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_10);
HAL_GPIO_DeInit(GPIOB, GPIO_PIN_11);
/* USER CODE BEGIN I2C2_MspDeInit 1 */
/* USER CODE END I2C2_MspDeInit 1 */
}
}
/**
* @brief TIM_Base MSP Initialization
* This function configures the hardware resources used in this example
* @param htim_base: TIM_Base handle pointer
* @retval None
*/
void HAL_TIM_Base_MspInit(TIM_HandleTypeDef* htim_base)
{
if(htim_base->Instance==TIM1)
{
/* USER CODE BEGIN TIM1_MspInit 0 */
/* USER CODE END TIM1_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_TIM1_CLK_ENABLE();
/* USER CODE BEGIN TIM1_MspInit 1 */
/* USER CODE END TIM1_MspInit 1 */
}
else if(htim_base->Instance==TIM2)
{
/* USER CODE BEGIN TIM2_MspInit 0 */
/* USER CODE END TIM2_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_TIM2_CLK_ENABLE();
/* TIM2 interrupt Init */
HAL_NVIC_SetPriority(TIM2_IRQn, 1, 0);
HAL_NVIC_EnableIRQ(TIM2_IRQn);
/* USER CODE BEGIN TIM2_MspInit 1 */
/* USER CODE END TIM2_MspInit 1 */
}
else if(htim_base->Instance==TIM3)
{
/* USER CODE BEGIN TIM3_MspInit 0 */
/* USER CODE END TIM3_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_TIM3_CLK_ENABLE();
/* USER CODE BEGIN TIM3_MspInit 1 */
/* USER CODE END TIM3_MspInit 1 */
}
}
void HAL_TIM_MspPostInit(TIM_HandleTypeDef* htim)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(htim->Instance==TIM1)
{
/* USER CODE BEGIN TIM1_MspPostInit 0 */
/* USER CODE END TIM1_MspPostInit 0 */
__HAL_RCC_GPIOA_CLK_ENABLE();
/**TIM1 GPIO Configuration
PA8 ------> TIM1_CH1
*/
GPIO_InitStruct.Pin = GPIO_PIN_8;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USER CODE BEGIN TIM1_MspPostInit 1 */
/* USER CODE END TIM1_MspPostInit 1 */
}
else if(htim->Instance==TIM3)
{
/* USER CODE BEGIN TIM3_MspPostInit 0 */
/* USER CODE END TIM3_MspPostInit 0 */
__HAL_RCC_GPIOC_CLK_ENABLE();
/**TIM3 GPIO Configuration
PC8 ------> TIM3_CH3
*/
GPIO_InitStruct.Pin = GPIO_PIN_8;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
__HAL_AFIO_REMAP_TIM3_ENABLE();
/* USER CODE BEGIN TIM3_MspPostInit 1 */
/* USER CODE END TIM3_MspPostInit 1 */
}
}
/**
* @brief TIM_Base MSP De-Initialization
* This function freeze the hardware resources used in this example
* @param htim_base: TIM_Base handle pointer
* @retval None
*/
void HAL_TIM_Base_MspDeInit(TIM_HandleTypeDef* htim_base)
{
if(htim_base->Instance==TIM1)
{
/* USER CODE BEGIN TIM1_MspDeInit 0 */
/* USER CODE END TIM1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_TIM1_CLK_DISABLE();
/* USER CODE BEGIN TIM1_MspDeInit 1 */
/* USER CODE END TIM1_MspDeInit 1 */
}
else if(htim_base->Instance==TIM2)
{
/* USER CODE BEGIN TIM2_MspDeInit 0 */
/* USER CODE END TIM2_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_TIM2_CLK_DISABLE();
/* TIM2 interrupt DeInit */
HAL_NVIC_DisableIRQ(TIM2_IRQn);
/* USER CODE BEGIN TIM2_MspDeInit 1 */
/* USER CODE END TIM2_MspDeInit 1 */
}
else if(htim_base->Instance==TIM3)
{
/* USER CODE BEGIN TIM3_MspDeInit 0 */
/* USER CODE END TIM3_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_TIM3_CLK_DISABLE();
/* USER CODE BEGIN TIM3_MspDeInit 1 */
/* USER CODE END TIM3_MspDeInit 1 */
}
}
/**
* @brief UART MSP Initialization
* This function configures the hardware resources used in this example
* @param huart: UART handle pointer
* @retval None
*/
void HAL_UART_MspInit(UART_HandleTypeDef* huart)
{
GPIO_InitTypeDef GPIO_InitStruct = {0};
if(huart->Instance==USART1)
{
/* USER CODE BEGIN USART1_MspInit 0 */
/* USER CODE END USART1_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_USART1_CLK_ENABLE();
__HAL_RCC_GPIOA_CLK_ENABLE();
/**USART1 GPIO Configuration
PA9 ------> USART1_TX
PA10 ------> USART1_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_9;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
/* USART1 interrupt Init */
HAL_NVIC_SetPriority(USART1_IRQn, 4, 0);
HAL_NVIC_EnableIRQ(USART1_IRQn);
/* USER CODE BEGIN USART1_MspInit 1 */
/* USER CODE END USART1_MspInit 1 */
}
else if(huart->Instance==USART3)
{
/* USER CODE BEGIN USART3_MspInit 0 */
/* USER CODE END USART3_MspInit 0 */
/* Peripheral clock enable */
__HAL_RCC_USART3_CLK_ENABLE();
__HAL_RCC_GPIOC_CLK_ENABLE();
/**USART3 GPIO Configuration
PC10 ------> USART3_TX
PC11 ------> USART3_RX
*/
GPIO_InitStruct.Pin = GPIO_PIN_10;
GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
GPIO_InitStruct.Pin = GPIO_PIN_11;
GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
GPIO_InitStruct.Pull = GPIO_NOPULL;
HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);
__HAL_AFIO_REMAP_USART3_PARTIAL();
/* USART3 interrupt Init */
HAL_NVIC_SetPriority(USART3_IRQn, 3, 0);
HAL_NVIC_EnableIRQ(USART3_IRQn);
/* USER CODE BEGIN USART3_MspInit 1 */
/* USER CODE END USART3_MspInit 1 */
}
}
/**
* @brief UART MSP De-Initialization
* This function freeze the hardware resources used in this example
* @param huart: UART handle pointer
* @retval None
*/
void HAL_UART_MspDeInit(UART_HandleTypeDef* huart)
{
if(huart->Instance==USART1)
{
/* USER CODE BEGIN USART1_MspDeInit 0 */
/* USER CODE END USART1_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_USART1_CLK_DISABLE();
/**USART1 GPIO Configuration
PA9 ------> USART1_TX
PA10 ------> USART1_RX
*/
HAL_GPIO_DeInit(GPIOA, GPIO_PIN_9|GPIO_PIN_10);
/* USART1 interrupt DeInit */
HAL_NVIC_DisableIRQ(USART1_IRQn);
/* USER CODE BEGIN USART1_MspDeInit 1 */
/* USER CODE END USART1_MspDeInit 1 */
}
else if(huart->Instance==USART3)
{
/* USER CODE BEGIN USART3_MspDeInit 0 */
/* USER CODE END USART3_MspDeInit 0 */
/* Peripheral clock disable */
__HAL_RCC_USART3_CLK_DISABLE();
/**USART3 GPIO Configuration
PC10 ------> USART3_TX
PC11 ------> USART3_RX
*/
HAL_GPIO_DeInit(GPIOC, GPIO_PIN_10|GPIO_PIN_11);
/* USART3 interrupt DeInit */
HAL_NVIC_DisableIRQ(USART3_IRQn);
/* USER CODE BEGIN USART3_MspDeInit 1 */
/* USER CODE END USART3_MspDeInit 1 */
}
}
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */

View File

@ -1,67 +1,30 @@
/* USER CODE BEGIN Header */
/**
******************************************************************************
* @file stm32f1xx_it.c
* @brief Interrupt Service Routines.
******************************************************************************
* @attention
*
* Copyright (c) 2025 STMicroelectronics.
* Copyright (c) 2025 C.ARE (JackCarterSmith).
* All rights reserved.
*
* This software is licensed under terms that can be found in the LICENSE file
* in the root directory of this software component.
* If no LICENSE file comes with this software, it is provided AS-IS.
*
******************************************************************************
*
*/
/* USER CODE END Header */
/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "hal_interface.h"
#include "stm32f1xx_it.h"
/* Private includes ----------------------------------------------------------*/
/* USER CODE BEGIN Includes */
/* USER CODE END Includes */
/* Private typedef -----------------------------------------------------------*/
/* USER CODE BEGIN TD */
/* USER CODE END TD */
/* Private define ------------------------------------------------------------*/
/* USER CODE BEGIN PD */
/* USER CODE END PD */
/* Private macro -------------------------------------------------------------*/
/* USER CODE BEGIN PM */
/* USER CODE END PM */
/* Private variables ---------------------------------------------------------*/
/* USER CODE BEGIN PV */
/* USER CODE END PV */
/* Private function prototypes -----------------------------------------------*/
/* USER CODE BEGIN PFP */
/* USER CODE END PFP */
/* Private user code ---------------------------------------------------------*/
/* USER CODE BEGIN 0 */
/* USER CODE END 0 */
/* External variables --------------------------------------------------------*/
extern I2C_HandleTypeDef hi2c1;
extern RTC_HandleTypeDef hrtc;
extern TIM_HandleTypeDef htim2;
#ifdef DEBUG
extern UART_HandleTypeDef huart1;
#endif
#ifdef UART_PICO_INTERFACE
extern UART_HandleTypeDef huart3;
/* USER CODE BEGIN EV */
#endif
/* USER CODE END EV */
/******************************************************************************/
/* Cortex-M3 Processor Interruption and Exception Handlers */
@ -69,129 +32,64 @@ extern UART_HandleTypeDef huart3;
/**
* @brief This function handles Non maskable interrupt.
*/
void NMI_Handler(void)
{
/* USER CODE BEGIN NonMaskableInt_IRQn 0 */
/* USER CODE END NonMaskableInt_IRQn 0 */
/* USER CODE BEGIN NonMaskableInt_IRQn 1 */
while (1)
{
}
/* USER CODE END NonMaskableInt_IRQn 1 */
void NMI_Handler(void) {
while (1) {}
}
/**
* @brief This function handles Hard fault interrupt.
*/
void HardFault_Handler(void)
{
/* USER CODE BEGIN HardFault_IRQn 0 */
/* USER CODE END HardFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_HardFault_IRQn 0 */
/* USER CODE END W1_HardFault_IRQn 0 */
}
void HardFault_Handler(void) {
while (1) {}
}
/**
* @brief This function handles Memory management fault.
*/
void MemManage_Handler(void)
{
/* USER CODE BEGIN MemoryManagement_IRQn 0 */
/* USER CODE END MemoryManagement_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */
/* USER CODE END W1_MemoryManagement_IRQn 0 */
}
void MemManage_Handler(void) {
while (1) {}
}
/**
* @brief This function handles Prefetch fault, memory access fault.
*/
void BusFault_Handler(void)
{
/* USER CODE BEGIN BusFault_IRQn 0 */
/* USER CODE END BusFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_BusFault_IRQn 0 */
/* USER CODE END W1_BusFault_IRQn 0 */
}
void BusFault_Handler(void) {
while (1) {}
}
/**
* @brief This function handles Undefined instruction or illegal state.
*/
void UsageFault_Handler(void)
{
/* USER CODE BEGIN UsageFault_IRQn 0 */
/* USER CODE END UsageFault_IRQn 0 */
while (1)
{
/* USER CODE BEGIN W1_UsageFault_IRQn 0 */
/* USER CODE END W1_UsageFault_IRQn 0 */
}
void UsageFault_Handler(void) {
while (1) {}
}
/**
* @brief This function handles System service call via SWI instruction.
*/
void SVC_Handler(void)
{
/* USER CODE BEGIN SVCall_IRQn 0 */
/* USER CODE END SVCall_IRQn 0 */
/* USER CODE BEGIN SVCall_IRQn 1 */
/* USER CODE END SVCall_IRQn 1 */
void SVC_Handler(void) {
while (1) {}
}
/**
* @brief This function handles Debug monitor.
*/
void DebugMon_Handler(void)
{
/* USER CODE BEGIN DebugMonitor_IRQn 0 */
void DebugMon_Handler(void) {
/* USER CODE END DebugMonitor_IRQn 0 */
/* USER CODE BEGIN DebugMonitor_IRQn 1 */
/* USER CODE END DebugMonitor_IRQn 1 */
}
/**
* @brief This function handles Pendable request for system service.
*/
void PendSV_Handler(void)
{
/* USER CODE BEGIN PendSV_IRQn 0 */
void PendSV_Handler(void) {
/* USER CODE END PendSV_IRQn 0 */
/* USER CODE BEGIN PendSV_IRQn 1 */
/* USER CODE END PendSV_IRQn 1 */
}
/**
* @brief This function handles System tick timer.
*/
void SysTick_Handler(void)
{
/* USER CODE BEGIN SysTick_IRQn 0 */
/* USER CODE END SysTick_IRQn 0 */
HAL_IncTick();
/* USER CODE BEGIN SysTick_IRQn 1 */
/* USER CODE END SysTick_IRQn 1 */
void SysTick_Handler(void) {
HAL_IncTick();
}
/******************************************************************************/
@ -204,93 +102,55 @@ void SysTick_Handler(void)
/**
* @brief This function handles EXTI line[9:5] interrupts.
*/
void EXTI9_5_IRQHandler(void)
{
/* USER CODE BEGIN EXTI9_5_IRQn 0 */
void EXTI9_5_IRQHandler(void) {
if (LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_9) != RESET) {
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_9);
/* USER CODE END EXTI9_5_IRQn 0 */
if (LL_EXTI_IsActiveFlag_0_31(LL_EXTI_LINE_9) != RESET)
{
LL_EXTI_ClearFlag_0_31(LL_EXTI_LINE_9);
/* USER CODE BEGIN LL_EXTI_LINE_9 */
pmu_irq = 1;
/* USER CODE END LL_EXTI_LINE_9 */
}
/* USER CODE BEGIN EXTI9_5_IRQn 1 */
/* USER CODE END EXTI9_5_IRQn 1 */
pmu_irq = 1;
}
}
/**
* @brief This function handles TIM2 global interrupt.
*/
void TIM2_IRQHandler(void)
{
/* USER CODE BEGIN TIM2_IRQn 0 */
/* USER CODE END TIM2_IRQn 0 */
HAL_TIM_IRQHandler(&htim2);
/* USER CODE BEGIN TIM2_IRQn 1 */
/* USER CODE END TIM2_IRQn 1 */
void TIM2_IRQHandler(void) {
HAL_TIM_IRQHandler(&htim2);
}
/**
* @brief This function handles I2C1 event interrupt.
*/
void I2C1_EV_IRQHandler(void)
{
/* USER CODE BEGIN I2C1_EV_IRQn 0 */
/* USER CODE END I2C1_EV_IRQn 0 */
HAL_I2C_EV_IRQHandler(&hi2c1);
/* USER CODE BEGIN I2C1_EV_IRQn 1 */
/* USER CODE END I2C1_EV_IRQn 1 */
void I2C1_EV_IRQHandler(void) {
HAL_I2C_EV_IRQHandler(&hi2c1);
}
/**
* @brief This function handles I2C1 error interrupt.
*/
void I2C1_ER_IRQHandler(void)
{
/* USER CODE BEGIN I2C1_ER_IRQn 0 */
/* USER CODE END I2C1_ER_IRQn 0 */
HAL_I2C_ER_IRQHandler(&hi2c1);
/* USER CODE BEGIN I2C1_ER_IRQn 1 */
/* USER CODE END I2C1_ER_IRQn 1 */
void I2C1_ER_IRQHandler(void) {
HAL_I2C_ER_IRQHandler(&hi2c1);
}
#ifdef DEBUG
/**
* @brief This function handles USART1 global interrupt.
*/
void USART1_IRQHandler(void)
{
/* USER CODE BEGIN USART1_IRQn 0 */
/* USER CODE END USART1_IRQn 0 */
HAL_UART_IRQHandler(&huart1);
/* USER CODE BEGIN USART1_IRQn 1 */
/* USER CODE END USART1_IRQn 1 */
void USART1_IRQHandler(void) {
HAL_UART_IRQHandler(&huart1);
}
#endif
#ifdef UART_PICO_INTERFACE
/**
* @brief This function handles USART3 global interrupt.
*/
void USART3_IRQHandler(void)
{
/* USER CODE BEGIN USART3_IRQn 0 */
/* USER CODE END USART3_IRQn 0 */
HAL_UART_IRQHandler(&huart3);
/* USER CODE BEGIN USART3_IRQn 1 */
/* USER CODE END USART3_IRQn 1 */
void USART3_IRQHandler(void) {
HAL_UART_IRQHandler(&huart3);
}
#endif
/* USER CODE BEGIN 1 */
/* USER CODE END 1 */
/**
* @brief This function handles RTC alarm interrupt through EXTI line 17.
*/
void RTC_Alarm_IRQHandler(void) {
HAL_RTC_AlarmIRQHandler(&hrtc);
}

View File

@ -76,17 +76,16 @@ Mcu.Pin47=VP_IWDG_VS_IWDG
Mcu.Pin48=VP_RTC_VS_RTC_Activate
Mcu.Pin49=VP_RTC_VS_RTC_Calendar
Mcu.Pin5=PC0
Mcu.Pin50=VP_RTC_No_RTC_Output
Mcu.Pin51=VP_SYS_VS_ND
Mcu.Pin52=VP_SYS_VS_Systick
Mcu.Pin53=VP_TIM1_VS_ClockSourceINT
Mcu.Pin54=VP_TIM2_VS_ClockSourceINT
Mcu.Pin55=VP_TIM3_VS_ClockSourceINT
Mcu.Pin50=VP_SYS_VS_ND
Mcu.Pin51=VP_SYS_VS_Systick
Mcu.Pin52=VP_TIM1_VS_ClockSourceINT
Mcu.Pin53=VP_TIM2_VS_ClockSourceINT
Mcu.Pin54=VP_TIM3_VS_ClockSourceINT
Mcu.Pin6=PC1
Mcu.Pin7=PC2
Mcu.Pin8=PC3
Mcu.Pin9=PA0-WKUP
Mcu.PinsNb=56
Mcu.PinsNb=55
Mcu.ThirdPartyNb=0
Mcu.UserConstants=
Mcu.UserName=STM32F103R8Tx
@ -103,6 +102,7 @@ NVIC.MemoryManagement_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.NonMaskableInt_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.PendSV_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.PriorityGroup=NVIC_PRIORITYGROUP_4
NVIC.RTC_Alarm_IRQn=true\:0\:0\:false\:false\:true\:true\:true\:true
NVIC.SVCall_IRQn=true\:0\:0\:false\:false\:true\:false\:false\:false
NVIC.SysTick_IRQn=true\:1\:0\:true\:false\:true\:false\:true\:false
NVIC.TIM2_IRQn=true\:1\:0\:true\:false\:true\:true\:true\:true
@ -413,12 +413,12 @@ ProjectManager.ProjectName=picocalc_BIOS_jcs
ProjectManager.ProjectStructure=
ProjectManager.RegisterCallBack=
ProjectManager.StackSize=0x400
ProjectManager.TargetToolchain=STM32CubeIDE
ProjectManager.TargetToolchain=Makefile
ProjectManager.ToolChainLocation=
ProjectManager.UAScriptAfterPath=
ProjectManager.UAScriptBeforePath=
ProjectManager.UnderRoot=true
ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-LL-false,2-MX_GPIO_Init-GPIO-false-LL-true,3-MX_I2C1_Init-I2C1-false-HAL-true,4-MX_I2C2_Init-I2C2-false-HAL-true,5-MX_RTC_Init-RTC-false-LL-true,6-MX_USART1_UART_Init-USART1-false-HAL-true,7-MX_USART3_UART_Init-USART3-false-HAL-true,8-MX_IWDG_Init-IWDG-false-LL-true,9-MX_TIM1_Init-TIM1-false-HAL-true,10-MX_TIM3_Init-TIM3-false-HAL-true,11-MX_TIM2_Init-TIM2-false-HAL-true
ProjectManager.UnderRoot=false
ProjectManager.functionlistsort=1-SystemClock_Config-RCC-false-LL-false,2-MX_GPIO_Init-GPIO-false-LL-true,3-MX_I2C1_Init-I2C1-false-HAL-true,4-MX_I2C2_Init-I2C2-false-HAL-true,5-MX_RTC_Init-RTC-false-HAL-true,6-MX_USART1_UART_Init-USART1-false-HAL-true,7-MX_USART3_UART_Init-USART3-false-HAL-true,8-MX_IWDG_Init-IWDG-false-LL-true,9-MX_TIM1_Init-TIM1-false-HAL-true,10-MX_TIM3_Init-TIM3-false-HAL-true,11-MX_TIM2_Init-TIM2-false-HAL-true
RCC.ADCFreqValue=2000000
RCC.AHBCLKDivider=RCC_SYSCLK_DIV2
RCC.AHBFreq_Value=4000000
@ -474,8 +474,6 @@ USART3.IPParameters=VirtualMode
USART3.VirtualMode=VM_ASYNC
VP_IWDG_VS_IWDG.Mode=IWDG_Activate
VP_IWDG_VS_IWDG.Signal=IWDG_VS_IWDG
VP_RTC_No_RTC_Output.Mode=RTC_OUT_NO
VP_RTC_No_RTC_Output.Signal=RTC_No_RTC_Output
VP_RTC_VS_RTC_Activate.Mode=RTC_Enabled
VP_RTC_VS_RTC_Activate.Signal=RTC_VS_RTC_Activate
VP_RTC_VS_RTC_Calendar.Mode=RTC_Calendar

View File

@ -0,0 +1,76 @@
#PCC Sequence - do not modify
#Wed May 21 14:12:50 CEST 2025
PCC.Battery=16850
PCC.Battery.Capacity=3000.0
PCC.Battery.InParallel=2
PCC.Battery.InSeries=1
PCC.Battery.SelfDischarge=0.08
PCC.Checker=false
PCC.Datasheet=DS5319_Rev17
PCC.Line=STM32F103
PCC.MCU=STM32F103R(8-B)Tx
PCC.PartNumber=STM32F103R8Tx
PCC.Seq0=4
PCC.Seq0.Step0.Average_Current=3.41 mA
PCC.Seq0.Step0.CPU_Frequency=4 MHz
PCC.Seq0.Step0.Category=In DS Table
PCC.Seq0.Step0.DMIPS=5.0
PCC.Seq0.Step0.Duration=0.1 ms
PCC.Seq0.Step0.Frequency=8 MHz
PCC.Seq0.Step0.Memory=FLASH
PCC.Seq0.Step0.Mode=RUN
PCC.Seq0.Step0.Oscillator=HSE
PCC.Seq0.Step0.Peripherals=APB1-Bridge APB2-Bridge GPIOA GPIOB GPIOC GPIOD I2C1 I2C2 PVD/BOR PWR RTC TIM1 TIM2 TIM3 WWDG
PCC.Seq0.Step0.TaMax=104.49
PCC.Seq0.Step0.User's_Consumption=0 mA
PCC.Seq0.Step0.Vcore=No Scale
PCC.Seq0.Step0.Vdd=3.3
PCC.Seq0.Step0.Voltage_Source=Battery
PCC.Seq0.Step1.Average_Current=1.7 mA
PCC.Seq0.Step1.CPU_Frequency=4 MHz
PCC.Seq0.Step1.Category=In DS Table
PCC.Seq0.Step1.DMIPS=5.0
PCC.Seq0.Step1.Duration=1 ms
PCC.Seq0.Step1.Frequency=8 MHz
PCC.Seq0.Step1.Memory=RAM/FLASH
PCC.Seq0.Step1.Mode=SLEEP
PCC.Seq0.Step1.Oscillator=HSE
PCC.Seq0.Step1.Peripherals=APB1-Bridge APB2-Bridge GPIOA GPIOB GPIOC GPIOD I2C1 I2C2 RTC TIM1 TIM2 TIM3 WWDG
PCC.Seq0.Step1.TaMax=104.75
PCC.Seq0.Step1.User's_Consumption=0 mA
PCC.Seq0.Step1.Vcore=No Scale
PCC.Seq0.Step1.Vdd=3.3
PCC.Seq0.Step1.Voltage_Source=Battery
PCC.Seq0.Step2.Average_Current=24 \u00B5A
PCC.Seq0.Step2.CPU_Frequency=0 Hz
PCC.Seq0.Step2.Category=In DS Table
PCC.Seq0.Step2.DMIPS=0.0
PCC.Seq0.Step2.Duration=1 ms
PCC.Seq0.Step2.Frequency=0 Hz
PCC.Seq0.Step2.Memory=n/a
PCC.Seq0.Step2.Mode=STOP
PCC.Seq0.Step2.Oscillator=Regulator_ON
PCC.Seq0.Step2.Peripherals=RTC*
PCC.Seq0.Step2.TaMax=105
PCC.Seq0.Step2.User's_Consumption=0 mA
PCC.Seq0.Step2.Vcore=No Scale
PCC.Seq0.Step2.Vdd=3.3
PCC.Seq0.Step2.Voltage_Source=Battery
PCC.Seq0.Step3.Average_Current=2 \u00B5A
PCC.Seq0.Step3.CPU_Frequency=0 Hz
PCC.Seq0.Step3.Category=In DS Table
PCC.Seq0.Step3.DMIPS=0.0
PCC.Seq0.Step3.Duration=1 ms
PCC.Seq0.Step3.Frequency=0 Hz
PCC.Seq0.Step3.Memory=n/a
PCC.Seq0.Step3.Mode=STANDBY
PCC.Seq0.Step3.Oscillator=ALL CLOCKS OFF
PCC.Seq0.Step3.Peripherals=RTC*
PCC.Seq0.Step3.TaMax=105
PCC.Seq0.Step3.User's_Consumption=0 mA
PCC.Seq0.Step3.Vcore=No Scale
PCC.Seq0.Step3.Vdd=3.3
PCC.Seq0.Step3.Voltage_Source=Battery
PCC.Series=STM32F1
PCC.Temperature=25
PCC.Vdd=3.3

View File

@ -2,8 +2,9 @@
# Generic Makefile (based on gcc)
#
# ChangeLog :
# 2025-05-09 - Added I2C_REGS_COMPAT option
# 2025-04-25 - Tuned for PicoCalc firmware project
# 2017-02-10 - Several enhancements + project update mode
# 2017-02-10 - Several enhancements + project update mode
# 2015-07-22 - first version
# ------------------------------------------------
@ -20,6 +21,8 @@ TARGET = picocalc_BIOS_jcs
DEBUG = 0
# optimization
OPT = -O3
# use old I2C registers structure
I2C_REGS_COMPAT = 0
#######################################
@ -32,41 +35,43 @@ BUILD_DIR = build
# source
######################################
# C sources
C_SOURCES = \
Core/Src/main.c \
Core/Src/stm32f1xx_it.c \
Core/Src/stm32f1xx_hal_msp.c \
C_SOURCES = \
Core/Src/main.c \
Core/Src/stm32f1xx_it.c \
Core/Src/hal_interface.c \
Core/Src/axp2101.c \
Core/Src/backlight.c \
Core/Src/batt.c \
Core/Src/eeprom.c \
Core/Src/fifo.c \
Core/Src/keyboard.c \
Core/Src/regs.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio_ex.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_ll_gpio.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_i2c.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_ll_rcc.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_ll_utils.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_ll_exti.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc_ex.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_dma.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_cortex.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_pwr.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash_ex.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_exti.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_ll_rtc.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim_ex.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_uart.c \
Core/Src/regs.c \
Core/Src/rtc.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio_ex.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_ll_gpio.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_i2c.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_ll_rcc.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_ll_utils.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_ll_exti.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rcc_ex.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_gpio.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_dma.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_cortex.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_pwr.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_flash_ex.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_exti.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rtc.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_rtc_ex.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_tim_ex.c \
Drivers/STM32F1xx_HAL_Driver/Src/stm32f1xx_hal_uart.c \
Core/Src/system_stm32f1xx.c
# ASM sources
ASM_SOURCES = \
ASM_SOURCES = \
startup_stm32f103xb.s
# ASM sources
@ -113,25 +118,29 @@ MCU = $(CPU) -mthumb $(FPU) $(FLOAT-ABI)
AS_DEFS =
# C defines
C_DEFS = \
-DUSE_FULL_LL_DRIVER \
-DUSE_HAL_DRIVER \
C_DEFS = \
-DUSE_FULL_LL_DRIVER \
-DUSE_HAL_DRIVER \
-DSTM32F103xB
ifeq ($(DEBUG), 1)
C_DEFS += -DDEBUG
endif
ifeq ($(I2C_REGS_COMPAT), 1)
C_DEFS += -DI2C_REGS_COMPAT
endif
# AS includes
AS_INCLUDES =
# C includes
C_INCLUDES = \
-ICore/Inc \
-IDrivers/STM32F1xx_HAL_Driver/Inc \
-IDrivers/STM32F1xx_HAL_Driver/Inc/Legacy \
-IDrivers/CMSIS_Device_ST_STM32F1xx/Include \
C_INCLUDES = \
-ICore/Inc \
-IDrivers/STM32F1xx_HAL_Driver/Inc \
-IDrivers/STM32F1xx_HAL_Driver/Inc/Legacy \
-IDrivers/CMSIS_Device_ST_STM32F1xx/Include \
-IDrivers/CMSIS/Include
@ -146,6 +155,7 @@ endif
# Generate dependency information
CFLAGS_ASM := $(CFLAGS)
CFLAGS += -MMD -MP -MF"$(@:%.o=%.d)"
@ -169,6 +179,7 @@ all: $(BUILD_DIR)/$(TARGET).elf $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET
#######################################
# list of objects
OBJECTS = $(addprefix $(BUILD_DIR)/,$(notdir $(C_SOURCES:.c=.o)))
OBJECTS_ASM = $(addprefix $(BUILD_DIR)/,$(notdir $(C_SOURCES:.c=.s)))
vpath %.c $(sort $(dir $(C_SOURCES)))
# list of ASM program objects
OBJECTS += $(addprefix $(BUILD_DIR)/,$(notdir $(ASM_SOURCES:.s=.o)))
@ -179,12 +190,15 @@ vpath %.S $(sort $(dir $(ASMM_SOURCES)))
$(BUILD_DIR)/%.o: %.c Makefile | $(BUILD_DIR)
$(CC) -c $(CFLAGS) -Wa,-a,-ad,-alms=$(BUILD_DIR)/$(notdir $(<:.c=.lst)) $< -o $@
$(BUILD_DIR)/%.s: %.c Makefile | $(BUILD_DIR)
$(CC) $(CFLAGS_ASM) -fverbose-asm -S $< -o $@
$(BUILD_DIR)/%.o: %.s Makefile | $(BUILD_DIR)
$(AS) -c $(CFLAGS) $< -o $@
$(BUILD_DIR)/%.o: %.S Makefile | $(BUILD_DIR)
$(AS) -c $(CFLAGS) $< -o $@
$(BUILD_DIR)/$(TARGET).elf: $(OBJECTS) Makefile
$(BUILD_DIR)/$(TARGET).elf: $(OBJECTS) $(OBJECTS_ASM) Makefile
$(CC) $(OBJECTS) $(LDFLAGS) -o $@
$(SZ) $@
@ -208,4 +222,4 @@ clean:
#######################################
-include $(wildcard $(BUILD_DIR)/*.d)
# *** EOF ***
# *** EOF ***

View File

@ -7,15 +7,28 @@ PicoCalc STM32F103R8T6 firmware.
The main differences with the original firmware are the followings:
- drastic reduction in the STM32's electricity consumption when running (~3.5 mA),
- clean up (in progress) to reduce binary size (~25 KB) and allow more features to be implemented,
- removed stm32duino dependencies (use STM32HAL instead, maybe I'll switch to libopencm3 someday...),
- clean up (by removing stm32duino dependencies, use STM32HAL instead, maybe I'll switch to libopencm3 someday...) to reduce binary size (~25 KB) and allow more features to be implemented,
- added configuration saving solution (using internal flash, including backlight option),
- new I2C registers and structure (keeping compatible access to REG_ID_TYP and REG_ID_VER registers to check how to handle comm from pico board side),
- interrupt event output to pico board can be configured during runtime (for keyboard event or RTC alarm),
- rewriten or added some debug UART interface message,
- internal RTC access through dedicated I2C registers (WIP),
- lighten AXP2101 PMIC driver.
## Compile
This source code can be compiled using ARM gcc toolchain (using v13) in path and using make program.
CAUTION: By default, I2C registers use a new, exploded structure that is more flexible!
But this makes them incompatible with official firmware. (More details to come about I2C registers structure in the wiki...)
If you plan using pico official firmware (PicoMite, etc.), you should set I2C_REGS_COMPAT = 1 in the Makefile.
## Important notes
The current implementation of this firmware is subject to change until the v1 release.
The permanent settings (EEPROM) save can be broken between 0.x version, it is recommanded to make a full flash erase before updating, as
EEPROM configuration survives update.
## Credits
- STM32-HAL: [link](https://github.com/STMicroelectronics/stm32f1xx-hal-driver)
- STM32-CMSIS: [link](https://github.com/STMicroelectronics/cmsis-device-f1)

View File

@ -62,7 +62,8 @@ _Min_Stack_Size = 0x400; /* required amount of stack */
MEMORY
{
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 20K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 64K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 62K
FEE (rw) : ORIGIN = 0x800F800, LENGTH = 2K
}
/* Define output sections */