This commit is contained in:
Vitalii 2025-05-14 01:20:39 +03:00
commit b07c0607d3
Signed by: SymbX
GPG Key ID: FF51F4E4BCE459EE
9 changed files with 1208 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/build/

39
CMakeLists.txt Normal file
View File

@ -0,0 +1,39 @@
cmake_minimum_required(VERSION 3.22)
project(s8-bathlight C ASM)
include(./_cmake/sdcc.cmake)
include_directories(./_common)
add_executable(s8-bathlight
src/main.c
)
target_link_libraries(s8-bathlight)
target_compile_definitions(s8-bathlight
PUBLIC
F_CPU=16000000UL
)
set_target_properties(s8-bathlight
PROPERTIES
COMPILE_FLAGS "-mstm8 --nolospre --opt-code-size"
LINK_FLAGS "-mstm8"
FAMILY stm8
PART stm8s103f3
)
target_include_directories(s8-bathlight
PUBLIC
../_common
)
set_target_properties(s8-bathlight
PROPERTIES
COMPILE_FLAGS "-mstm8 --nolospre --opt-code-size"
LINK_FLAGS "-mstm8"
FAMILY stm8
PART stm8s103f3
)
add_upload_to_target(s8-bathlight)

View File

@ -0,0 +1,28 @@
# the name of the target operating system
SET(CMAKE_SYSTEM_NAME Generic)
set(CMAKE_C_FLAGS_INIT "-mstm8 --std-sdcc11 --code-loc 0x8000") # -s
set(CMAKE_EXE_LINKER_FLAGS_INIT "")
# which compilers to use for C and ASM
SET(CMAKE_C_COMPILER /usr/bin/sdcc)
SET(CMAKE_ASM_COMPILER /usr/bin/sdasstm8)
find_program (SDCC NAMES sdcc)
get_filename_component(SDCC_BIN_DIR ${SDCC} DIRECTORY)
get_filename_component(SDCC_PATH_DIR ${SDCC_BIN_DIR} DIRECTORY)
# here is the target environment is located
SET(CMAKE_FIND_ROOT_PATH ${SDCC_PATH_DIR}/usr/share/sdcc)
# adjust the default behaviour of the FIND_XXX() commands:
# search headers and libraries in the target environment, search
# programs in the host environment
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
# TODO This is not being recognised
set(CMAKE_ASM_OUTPUT_EXTENSION ".rel")
set(CMAKE_ASM_COMPILE_OBJECT "${CMAKE_ASM_COMPILER} -o <OBJECT> <SOURCE>")

29
_cmake/sdcc.cmake Normal file
View File

@ -0,0 +1,29 @@
find_program(STM8FLASH stm8flash
DOC "stm8flash binary location"
)
set(STM8FLASH_PROGRAMMER
"stlinkv2" CACHE STRING
"Choice of stlink, stlinkv2 or espstlink, when not specified in target properties")
function(add_upload_to_target target)
get_target_property(FAMILY ${target} FAMILY)
if (FAMILY STREQUAL "stm8")
if (STM8FLASH STREQUAL "STM8FLASH-NOTFOUND")
message(SEND_ERROR "stm8flash is not found")
endif()
get_target_property(STM8_PART ${target} PART)
get_target_property(PROGRAMMER ${target} PROGRAMMER)
if(PROGRAMMER STREQUAL "PROGRAMMER-NOTFOUND")
set(PROGRAMMER ${STM8FLASH_PROGRAMMER})
endif()
add_custom_target(${target}-upload
COMMAND ${STM8FLASH} -c ${PROGRAMMER} -p ${STM8_PART} -w ${target}.ihx
DEPENDS ${target}
COMMENT "Uploading ${target}"
)
endif()
endfunction(add_upload_to_target)

74
_common/stm8s103f3.h Normal file
View File

@ -0,0 +1,74 @@
#ifndef STM8S103F3_DEF
#define STM8S103F3_DEF
#include <type.h>
// Interrupt codes
#define IRQ_TOP_LVL 0x00
#define IRQ_WAKE_UP 0x01
#define IRQ_CLOCK 0x02
#define IRQ_EXTI_A 0x03
#define IRQ_EXTI_B 0x04
#define IRQ_EXTI_C 0x05
#define IRQ_EXTI_D 0x06
#define IRQ_EXTI_E 0x07
#define IRQ_SPI_END 0x0A
#define IRQ_TIM1_OVERFLOW 0x0B
#define IRQ_TIM1_COMCAP 0x0C
#define IRQ_TIM2_OVERFLOW 0x0D
#define IRQ_TIM2_COMCAP 0x0E
#define IRQ_UART1_TX_C 0x11
#define IRQ_UART1_RX_F 0x12
#define IRQ_I2C 0x13
#define IRQ_ADC_END 0x16
#define IRQ_TIM4_OVERFLOW 0x17
#define IRQ_FLASH 0x18
// Map port registres to structures
#define PORT_A (*(Port*) 0x5000)
#define PORT_B (*(Port*) 0x5005)
#define PORT_C (*(Port*) 0x500A)
#define PORT_D (*(Port*) 0x500F)
#define PORT_E (*(Port*) 0x5014)
#define PORT_F (*(Port*) 0x501A)
// Uart to structure
#define UART1 (*(UART*) 0x5230)
// GPIO Interrupt control structures
#define EXTI_CR1 (*(ExternalInterruptControlFull*) 0x50A0)
#define EXTI_CR2 (*(ExternalInterruptControlLim*) 0x50A1)
// #define CLK_CKDIVR (*(volatile u08*) 0x50C6)
// #define CLK_PCKENR1 (*(volatile u08*) 0x50C7)
#define UART_SR_TXE (1 << 7)
#define FLASH (*(Flash*) 0x505A)
#define UNLOCK_DATA_KEY1 0xAE
#define UNLOCK_DATA_KEY2 0x56
#define FLASH_PROG_START 0x8000
#define FLASH_PROG_END 0x9FFF
#define FLASH_DATA_START 0x4000
#define FLASH_DATA_END 0x427F
// #define SERIAL_ADDRESS FLASH_DATA_START
// #define SERIAL ((_MEM_(SERIAL_ADDRESS + 1) << 8) | _MEM_(SERIAL_ADDRESS))
#define AES_KEY_ADDRESS (FLASH_DATA_START + 2)
#define TIM1 (*(AdvancedTimer*) 0x5250)
#define I2C1 (*(volatile I2C*) 0x5210)
#define CLK (*(Clock*) 0x50C0)
#define WWDG (*(Watchdog*) 0x50D1)
#define ADC1 (*(ADC*) 0x5400)
#define TIM2 (*(GeneralTimer*) 0x5300)
#define I2C_SR1 (*(u08*) 0x5217)
#define I2C_SR2 (*(u08*) 0x5218)
#define I2C_SR3 (*(u08*) 0x5219)
#define CFG_GCR (*(u08*) 0x7F60)
#define IWATCHDOG (*(IndependWatchdog*) 0x50E0)
#endif//STM8S103F3_DEF

701
_common/stm_base.h Normal file
View File

@ -0,0 +1,701 @@
#ifndef STM_BASE_H
#define STM_BASE_H
#include <type.h>
// Enable interrupts
#define rim() {__asm__("rim\n");}
// Disable interrupts
#define sim() {__asm__("sim\n");}
// Do nothing
#define nop() {__asm__("nop\n");}
// Trap (Soft IT)
#define trap() {__asm__("trap\n");}
// Wait for interrupt
#define wfi() {__asm__("wfi\n");}
// Halt
#define halt() {__asm__("halt\n");}
// Interrupt
#define interrupt(key, name) void name(void) __interrupt(key)
// Pins structure (easy access to each pin)
typedef struct {
u08 Pin0 :1;
u08 Pin1 :1;
u08 Pin2 :1;
u08 Pin3 :1;
u08 Pin4 :1;
u08 Pin5 :1;
u08 Pin6 :1;
u08 Pin7 :1;
} Pins;
// Port structure (all pins control)
typedef struct {
Pins ODR;
Pins IDR;
Pins DDR;
Pins CR1;
Pins CR2;
} Port;
// Uart register structure
typedef struct {
u08 Status :8;
u08 Data :8;
u08 BRR1 :8;
u08 BRR2 :8;
u08 CR1 :8;
u08 CR2 :8;
u08 CR3 :8;
u08 CR4 :8;
u08 CR5 :8;
u08 GTR :8;
u08 PSCR :8;
} UART;
// Uart configuration bits
#define UART_TX_EMPTY (1 << 7)
#define UART_TX_COMPLETE (1 << 6)
#define UART_RX_NOT_EMPTY (1 << 5)
#define UART_RX_IDLE (1 << 4)
#define UART_RX_OVERRUN (1 << 3)
#define UART_RX_NOISE (1 << 2)
#define UART_RX_FRAME_ERROR (1 << 1)
#define UART_RX_PARITY_ERROR (1 << 0)
#define UART_CR2_SBK (1 << 0)
#define UART_CR2_RWU (1 << 1)
#define UART_CR2_REN (1 << 2)
#define UART_CR2_TEN (1 << 3)
#define UART_CR2_IDLE_IVT (1 << 4)
#define UART_CR2_RXNE_IVT (1 << 5)
#define UART_CR2_TXC_IVT (1 << 6)
#define UART_CR2_TXE_IVT (1 << 7)
#define UART_CR3_LINEN (1 << 6)
#define UART_CR3_STOP2 (1 << 5)
#define UART_CR3_STOP1 (1 << 4)
#define UART_CR3_CLKEN (1 << 3)
#define UART_CR3_CLKPOL (1 << 2)
#define UART_CR3_CLKPHA (1 << 1)
#define UART_CR3_LBCL (1 << 0)
// Delay function (in ticks)
static void delay_tick(unsigned int t)
{
while(t--);
}
// GPIO Control register structure (1)
typedef struct {
u08 PortA :2;
u08 PortB :2;
u08 PortC :2;
u08 PortD :2;
} ExternalInterruptControlFull;
// GPIO Control register structure (2)
typedef struct {
u08 PortE :2;
} ExternalInterruptControlLim;
// GPIO interrupt mode
#define EXTI_FALLING_LOW 0x00
#define EXTI_RISING 0x01
#define EXTI_FALLING 0x02
#define EXTI_RISING_FALLING 0x03
// Flash control register struct (1)
typedef struct {
u08 FixedTime :1;
u08 Interrupt :1;
u08 ActiveHaltPowerDown :1;
u08 HaltPowerDown :1;
u08 :4;
} FlashControl1;
// Flash control register struct (2)
typedef struct {
u08 StandardBlockProgramming :1;
u08 :3;
u08 FastBlockProgramming :1;
u08 BlockErase :1;
u08 WordProgramming :1;
u08 WriteOptionBytes :1;
} FlashControl2;
typedef struct {
u08 UserBootAreaSize :6;
u08 :2;
} FlashProtection;
// Flash status register struct
typedef struct {
u08 AttemptWriteProtected :1;
u08 FlashUnlocked :1;
u08 EndOfOperation :1;
u08 DataUnlocked :1;
u08 :2;
u08 EndOfHV :1;
u08 :1;
} FlashStatus;
typedef struct {
FlashControl1 Control1;
FlashControl2 Control2;
FlashControl2 ComplimentaryControl;
FlashProtection Protection;
FlashProtection NProtection;
FlashStatus Status;
u16 :16;
u08 FlashProtectionKey :8;
u08 :8;
u08 DataProtectionKey :8;
} Flash;
#define FLASH_UNLOCK_KEY1 0x56
#define FLASH_UNLOCK_KEY2 0xAE
#define DATA_UNLOCK_KEY1 0xAE
#define DATA_UNLOCK_KEY2 0x56
#define _MEM_(mem_addr) (*(volatile u08*)(mem_addr))
typedef struct {
u08 CounterEnable :1;
u08 UpdateDisable :1;
u08 UpdateRequestSource :1;
u08 OnePulseMode :1;
u08 Direction :1;
u08 CenterAlignedMode :1;
u08 AutoReloadPreload :1;
} TimerControl1;
typedef struct {
u08 CaptureCountrolPreload :1;
u08 :1;
u08 CaptureControlUpdate :1;
u08 :1;
u08 MasterMode :3;
u08 :1;
} TimerControl2;
typedef struct {
u08 Mode :3;
u08 :1;
u08 Trigger :3;
u08 MasterSlave :1;
} TimerSlaveControl;
typedef struct {
u08 Filter :4;
u08 Prescaler :2;
u08 ExternalClock :1;
u08 TriggerPolariry :1;
} TimerExternalTrigger;
typedef struct {
u08 UpdateInterrupt :1;
u08 Capture1Interrupt :1;
u08 Capture2Interrupt :1;
u08 Capture3Interrupt :1;
u08 Capture4Interrupt :1;
u08 CommutationInterrupt :1;
u08 TriggerInterrupt :1;
u08 BreakInterrupt :1;
} TimerInterrupt;
typedef struct {
u08 UpdateInterruptFlag :1;
u08 Capture1InterruptFlag :1;
u08 Capture2InterruptFlag :1;
u08 Capture3InterruptFlag :1;
u08 Capture4InterruptFlag :1;
u08 CommutationInterruptFlag :1;
u08 TriggerInterruptFlag :1;
u08 BreakInterruptFlag :1;
} TimerStatus1;
typedef struct {
u08 :1;
u08 Capture1OvercaptureFlag :1;
u08 Capture2OvercaptureFlag :1;
u08 Capture3OvercaptureFlag :1;
u08 Capture4OvercaptureFlag :1;
u08 :3;
} TimerStatus2;
typedef struct {
u08 UpdateGeneration :1;
u08 Capture1Generation :1;
u08 Capture2Generation :1;
u08 Capture3Generation :1;
u08 Capture4Generation :1;
u08 CaptureUpdateGeneration :1;
u08 TriggerGeneration :1;
u08 BreakGeneration :1;
} TimerEventGen;
typedef struct {
u08 Enable1 :1;
u08 Polarity1 :1;
u08 ComplimentaryEnable1 :1;
u08 ComplimentaryPolarity1 :1;
u08 Enable2 :1;
u08 Polarity2 :1;
u08 ComplimentaryEnable2 :1;
u08 ComplimentaryPolarity2 :1;
} TimerCaptureRegister1;
typedef struct {
u08 Enable3 :1;
u08 Polarity3 :1;
u08 ComplimentaryEnable3 :1;
u08 ComplimentaryPolarity3 :1;
u08 Enable4 :1;
u08 Polarity4 :1;
u08 ComplimentaryEnable4 :1;
u08 ComplimentaryPolarity4 :1;
} TimerCaptureRegister2;
typedef struct {
TimerControl1 Control1;
TimerControl2 Control2;
TimerSlaveControl SlaveControl;
TimerExternalTrigger ExternalTrigger;
TimerInterrupt Interrupt;
TimerStatus1 Status1;
TimerStatus2 Status2;
TimerEventGen EventGeneration;
u08 CaptureMode1 :8;
u08 CaptureMode2 :8;
u08 CaptureMode3 :8;
u08 CaptureMode4 :8;
TimerCaptureRegister1 Capture12;
TimerCaptureRegister2 Capture34;
u08 CounterH :8;
u08 CounterL :8;
u08 PrescalerH :8;
u08 PrescalerL :8;
u08 AutoReloadH :8;
u08 AutoReloadL :8;
} AdvancedTimer;
typedef struct {
u08 Enable :1;
u08 :5;
u08 GeneralCallEnable :1;
u08 NoStretch :1;
} I2CControl1;
typedef struct {
u08 Start :1;
u08 Stop :1;
u08 Acknowledge :1;
u08 AcknowledgePosition :1;
u08 :3;
u08 SoftwareReset :1;
} I2CControl2;
typedef struct {
u08 Address10Bit0 :1;
u08 Address :7;
} I2CAddressL;
typedef struct {
u08 :1;
u08 Address10Bit89 :2;
u08 :3;
u08 AddressConfig :1;
u08 AddressMode :1;
} I2CAddressH;
typedef struct {
u08 StartBit :1;
u08 AddressSent :1;
u08 ByteTransferFinished :1;
u08 Address10Bit0 :1;
u08 StopFlag :1;
u08 :1;
u08 ReceiveNotEmpty :1;
u08 TransmitEmpty :1;
} I2CStatus1;
typedef struct {
u08 BusError :1;
u08 ArbitrationLost :1;
u08 AcknowledgeFailure :1;
u08 Overrun :1;
u08 :1;
u08 WakeUp :1;
u08 :2;
} I2CStatus2;
typedef struct {
u08 MasterMode :1;
u08 BusBusy :1;
u08 Transmitting :1;
u08 :1;
u08 GeneralCallHeader :1;
u08 :2;
u08 DualFlag :1;
} I2CStatus3;
typedef struct {
u08 Error :1;
u08 Event :1;
u08 Buffer :1;
u08 :5;
} I2CInterrupt;
typedef struct {
u16 Clock :12;
u08 :2;
u08 FastModeDuty :1;
u08 FastMode :1;
} I2CClockControl;
typedef struct {
u08 Time :6;
u08 :2;
} I2CRiseControl;
typedef struct {
I2CControl1 Control1;
I2CControl2 Control2;
u08 Frequency :6;
u08 :2;
I2CAddressL AddressL;
I2CAddressH AddressH;
u08 :8;
u08 Data :8;
I2CStatus1 Status1;
I2CStatus2 Status2;
I2CStatus3 Status3;
I2CInterrupt Interrupt;
I2CClockControl ClockControl;
I2CRiseControl TimeRise;
u08 :8; // Errors
} I2C;
typedef struct {
u08 HighSpeedInternalEnable :1;
u08 HighSpeedInternalReady :1;
u08 FastWakeUp :1;
u08 LowSpeedInternalEnable :1;
u08 LowSpeedInternalReady :1;
u08 RegulatorPoweroff :1;
u08 :2;
} ClockInternal;
typedef struct {
u08 HighSpeedExternalEnable :1;
u08 HighSpeedExternalReady :1;
u08 :6;
} ClockExternal;
typedef enum {
HighSpeedExternal = 0xB4,
LowSpeedInternal = 0xD2,
HighSpeedInternal = 0xE1
} ClockMasterType;
typedef struct {
u08 SwitchBusy :1;
u08 SwitchStartStop :1;
u08 SwitchInterrupt :1;
u08 SwitchInterruptFlag :1;
u08 :4;
} ClockSwitch;
typedef struct {
u08 Prescaler :3;
u08 HighSpeedPrescaler :2;
u08 :3;
} ClockDivider;
typedef struct {
u08 I2C :1;
u08 SPI :1;
u08 :1;
u08 Serial1 :1;
u08 Timer4 :1;
u08 Timer2 :1;
u08 :1;
u08 Timer1 :1;
} ClockPeripheral1;
typedef struct {
u08 :2;
u08 AutoWakeUp :1;
u08 AnalogDigitalConvertor :1;
u08 :4;
} ClockPeripheral2;
typedef struct {
u08 Enable :1;
u08 AuxiliaryConnected :1;
u08 DetectionInterrupt :1;
u08 Detection :1;
u08 :4;
} ClockSecuritySystem;
typedef struct {
u08 Enable :1;
u08 Selection :4;
u08 Ready :1;
u08 Busy :1;
u08 :1;
} ClockOutput;
typedef struct {
u08 HighSpeedIntenalTrim :4;
u08 :4;
} ClockTrimming;
typedef struct {
u08 Divider :1;
u08 :7;
} ClockSWIM;
typedef struct {
ClockInternal Internal;
ClockExternal External;
u08 :8;
ClockMasterType MasterStatus :8;
ClockMasterType MasterSwitch :8;
ClockSwitch SwitchControl;
ClockDivider Divider;
ClockPeripheral1 Peripheral1;
ClockSecuritySystem SecuritySystem;
ClockOutput Output;
ClockPeripheral2 Peripheral2;
u08 :8;
ClockTrimming Trimming;
ClockSWIM SWIM;
} Clock;
typedef struct {
u08 Counter :7;
u08 Activate :1;
} WatchdogControl;
typedef struct {
u08 Counter :7;
u08 :1;
} WatchdogWindow;
typedef struct {
WatchdogControl Control;
WatchdogWindow Window;
} Watchdog;
typedef struct {
u08 High :8;
u08 Low :8;
} ADCBuffer;
typedef struct {
u08 Channel :4;
u08 AnalogWatchdogInterrupt :1;
u08 Interrupt :1;
u08 AnalogWatchdog :1;
u08 EndOfConversion :1;
} ADCControlStatus;
typedef struct {
u08 ConverterOn :1;
u08 ContinousConversion :1;
u08 :2;
u08 Prescaler :3;
u08 :1;
} ADCConfig1;
typedef struct {
u08 :1;
u08 ScanMode :1;
u08 :1;
u08 Alignment :1;
u08 ExternalEventSelection :2;
u08 ExternalTrigger :1;
u08 :1;
} ADCConfig2;
typedef struct {
u08 :6;
u08 OverrunFlag :1;
u08 DataBufferEnable :1;
} ADCConfig3;
typedef struct {
u08 High :8;
u08 Low :8;
} ADCData;
typedef struct {
u08 High :8;
u08 Low :2;
u08 :6;
} ADCThreshold;
typedef struct {
ADCControlStatus ControlStatus;
ADCConfig1 Configuration1;
ADCConfig2 Configuration2;
ADCConfig3 Configuration3;
ADCData Data;
ADCData SchmittDisable;
ADCThreshold HighThreshold;
ADCThreshold LowThreshold;
u08 :8; // Watchdog
u08 :8; // Watchdog
u08 :8; // Watchdog
u08 :8; // Watchdog
} ADC;
typedef struct {
u08 Enable :1;
u08 UpdateDisable :1;
u08 UpdateRequestSource :1;
u08 OnePulseMode :1;
u08 :3;
u08 AutoReload :1;
} GeneralTimerControl1;
typedef struct {
u08 :4;
u08 MasterModeSelection :3;
u08 :1;
} GeneralTimerControl2;
typedef struct {
u08 SlaveModeSelection :3;
u08 :1;
u08 TriggerSelection :3;
u08 MasterSlaveMode :1;
} GeneralTimerSlaveControl;
typedef struct {
u08 UpdateInterrupt :1;
u08 Capture1Interrupt :1;
u08 Capture2Interrupt :1;
u08 Capture3Interrupt :1;
u08 :2;
u08 TriggerInterrupt :1;
u08 :1;
} GeneralTimerInterrupt;
typedef struct {
u08 UpdateInterruptFlag :1;
u08 Capture1InterruptFlag :1;
u08 Capture2InterruptFlag :1;
u08 Capture3InterruptFlag :1;
u08 :2;
u08 TriggerInterruptFlag :1;
u08 :1;
} GeneralTimerStatus1;
typedef struct {
u08 :1;
u08 Overcapture1Flag :1;
u08 Overcapture2Flag :1;
u08 Overcapture3Flag :1;
u08 :4;
} GeneralTimerStatus2;
typedef struct {
u08 UpdateGeneration :1;
u08 Capture1Generation :1;
u08 Capture2Generation :1;
u08 Capture3Generation :1;
u08 :2;
u08 TriggerGeneration :1;
u08 :1;
} GeneralTimerEventGeneration;
typedef struct {
u08 CaptureSelection :2;
u08 :1;
u08 PreloadEnable :1;
u08 CompareMode :3;
u08 :1;
} GeneralTimerCaptureMode;
typedef struct {
u08 Capture1Enable :1;
u08 Capture1Polarity :1;
u08 :2;
u08 Capture2Enable :1;
u08 Capture2Polarity :1;
u08 :2;
} GeneralTimerCaptureRegister1;
typedef struct {
u08 Capture3Enable :1;
u08 Capture3Polarity :1;
u08 :6;
} GeneralTimerCaptureRegister2;
typedef struct {
u08 High :8;
u08 Low :8;
} GeneralTimer16Register;
typedef struct {
GeneralTimerControl1 Control1;
u08 :8;
u08 :8;
GeneralTimerInterrupt Interrupt;
GeneralTimerStatus1 Status1;
GeneralTimerStatus2 Status2;
GeneralTimerEventGeneration Event;
GeneralTimerCaptureMode Capture1;
GeneralTimerCaptureMode Capture2;
GeneralTimerCaptureMode Capture3;
GeneralTimerCaptureRegister1 CaptureReg1;
GeneralTimerCaptureRegister2 CaptureReg2;
GeneralTimer16Register Counter;
u08 Prescaler :4;
u08 :4;
GeneralTimer16Register AutoReload;
GeneralTimer16Register Compare1;
GeneralTimer16Register Compare2;
GeneralTimer16Register Compare3;
} GeneralTimer;
typedef enum {
IndependWatchdogOff = 0x00,
IndependWatchdogEdit = 0x55,
IndependWatchdogReset= 0xAA,
IndependWatchdogOn = 0xCC
} IndependWatchdogKey;
typedef enum {
WatchdogPrescaler_4 = 0x00,
WatchdogPrescaler_8 = 0x01,
WatchdogPrescaler_16 = 0x02,
WatchdogPrescaler_32 = 0x03,
WatchdogPrescaler_64 = 0x04,
WatchdogPrescaler_128= 0x05,
WatchdogPrescaler_256= 0x06
} WatchdogPrescaler;
typedef struct {
IndependWatchdogKey Key :8;
WatchdogPrescaler Prescaler :3;
u08 :5;
u08 Reload :8;
} IndependWatchdog;
#endif//STM_BASE_H

20
_common/type.h Normal file
View File

@ -0,0 +1,20 @@
#ifndef STM_TYPE_H
#define STM_TYPE_H
// Here defined basic types used in code
typedef unsigned char u08;
typedef signed char i08;
typedef unsigned short u16;
typedef signed short i16;
typedef unsigned long u32;
typedef signed long i32;
typedef unsigned char bool;
#define false 0
#define true 1
#define STRLLEN(x) (sizeof(x) - 1)
#endif//STM_TYPE_H

4
build.sh Executable file
View File

@ -0,0 +1,4 @@
#!/bin/sh
mkdir -p build
(cd build && cmake --toolchain ../_cmake/sdcc-toolchain.cmake .. && make)

312
src/main.c Normal file
View File

@ -0,0 +1,312 @@
#include <type.h>
#include <stm_base.h>
#include <stm8s103f3.h>
#include <string.h>
#include <stdio.h>
#define WATCHDOG
#define BUFFER_LEN 48
#define LED_PIN_DIR PORT_C.DDR.Pin3
#define LED_PIN_CR1 PORT_C.CR1.Pin3
#define LED_PIN_CR2 PORT_C.CR2.Pin3
#define LED_PIN_OUT PORT_C.ODR.Pin3
#define RX_PIN_DIR PORT_D.DDR.Pin6
#define RX_PIN_CR1 PORT_D.CR1.Pin6
#define RX_PIN_CR2 PORT_D.CR2.Pin6
#define RX_PIN_OUT PORT_D.ODR.Pin6
#define TX_PIN_DIR PORT_D.DDR.Pin5
#define TX_PIN_CR1 PORT_D.CR1.Pin5
#define TX_PIN_CR2 PORT_D.CR2.Pin5
#define TX_PIN_OUT PORT_D.ODR.Pin5
#define SHORT_PRESS_MS 25
#define LONG_PRESS_MS 1000
// Countdown timestamp (2^15 max, sign used to notify "unitialized")
volatile i16 countdown_tick = 0;
// volatile u08 exec = 0;
volatile i16 timer = 0;
volatile u08 cmd[BUFFER_LEN];
volatile u08 cmdPos = 0;
volatile u08 cmdLen = 0;
volatile u08 state = 0;
void reboot(void) {
#ifdef WATCHDOG
IWATCHDOG.Key = IndependWatchdogReset;
#else
delay_tick(0xffff);
#endif
WWDG.Control.Activate = 1;
WWDG.Control.Counter = 0;
}
void start_cmd(u08 len) {
cmdPos = 0;
cmdLen = len;
UART1.CR2 |= UART_CR2_TXE_IVT;
UART1.Data = cmd[0];
}
/**
* Mark current time for further comparison
*/
inline void start_countdown(void) {
countdown_tick = (TIM1.CounterH << 8) | TIM1.CounterL;
}
/**
* Mark countdown as unitialized
*/
inline void stop_countdown(void) {
countdown_tick = -1;
}
/**
* Check if countdown is active
*/
inline bool is_countdown_active(void) {
return countdown_tick >= 0;
}
/**
* Get time elapsed from countdown start in ms
*/
i16 elapsed(void) {
if (!is_countdown_active()) {
return -1;
}
u16 next = (TIM1.CounterH << 8) | TIM1.CounterL;
if (next < countdown_tick) {
return (next + 2500) - countdown_tick;
} else {
return next - countdown_tick;
}
}
void send_some_command(void) {
cmd[0] = 'C';
cmd[1] = 'M';
cmd[2] = 'D';
start_cmd(3);
}
void initialize_state(void) {
switch (state) {
case 0:
send_some_command();
// initialization step 0
break;
case 1:
send_some_command();
// initialization step 1
break;
}
state++;
}
#define LED_DELAY 888
u08 led_state = 0;
void turn_on(void) {
if (led_state == 1) {
return;
}
led_state = 1;
u16 delay = LED_DELAY;
while (delay > 1) {
LED_PIN_OUT ^= 1;
delay_tick(delay);
delay--;
}
LED_PIN_OUT = 1;
}
void turn_off(void) {
if (led_state == 0) {
return;
}
led_state = 0;
u16 delay = 1;
while (delay < LED_DELAY) {
LED_PIN_OUT ^= 1;
delay_tick(delay);
delay++;
}
LED_PIN_OUT = 0;
}
void tick_250ms(void) {
if (timer > 0) {
timer--;
}
if (timer != 0) {
turn_on();
} else {
turn_off();
}
if (state < 2) {
initialize_state();
}
}
interrupt(IRQ_UART1_RX_F, uart_recv) {
u08 s = UART1.Status;
u08 c = UART1.Data;
// if (exec == 1) {
// switch (c) {
// case 0x2A:
// timer = 1200;
// break;
// case 0x2B:
// timer = -1;
// break;
// case 0x2C:
// timer = 0;
// break;
// }
// }
// if (c == 0x24) {
// exec = 1;
// } else {
// exec = 0;
// }
}
interrupt(IRQ_UART1_TX_C, uart_sent) {
cmdPos++;
if (cmdPos < cmdLen) {
UART1.Data = cmd[cmdPos];
} else {
cmdPos = 0;
cmdLen = 0;
memset(cmd, '\0', BUFFER_LEN);
UART1.CR2 &= ~UART_CR2_TXE_IVT;
}
}
interrupt(IRQ_EXTI_C, touch) {
if (PORT_C.IDR.Pin4) {
// Mark touch start
start_countdown();
} else if (is_countdown_active()) {
// Get time on release
i16 time = elapsed();
if (time > LONG_PRESS_MS) {
// Make light continuously if pressed for long
timer = -1;
} else if (time > SHORT_PRESS_MS) {
// If it was short touch set timer for enough time
timer = 30 * 4; // 30 seconds * 4 (250ms tick)
}
}
}
interrupt(IRQ_TIM1_OVERFLOW, timer1_tick) {
TIM1.Status1.UpdateInterruptFlag = 0;
#ifdef WATCHDOG
IWATCHDOG.Key = IndependWatchdogReset;
#endif
tick_250ms();
}
void main(void) {
// Setup clock (External, 16Mhz)
CLK.External.HighSpeedExternalEnable = 1;
while (CLK.External.HighSpeedExternalReady == 0) {
nop();
}
CLK.MasterSwitch = HighSpeedExternal;
while (CLK.SwitchControl.SwitchInterruptFlag == 0) {
nop();
}
CLK.SwitchControl.SwitchStartStop = 1;
CLK.Divider.Prescaler = 0x00;
CLK.Divider.HighSpeedPrescaler = 0x00;
CLK.Peripheral1.I2C= 0;
CLK.Peripheral1.SPI = 0;
CLK.Peripheral1.Timer2 = 0;
CLK.Peripheral1.Timer4 = 0;
CLK.Peripheral2.AnalogDigitalConvertor = 0;
// Setup UART pins
RX_PIN_DIR = 0;
RX_PIN_CR1 = 0;
RX_PIN_CR2 = 0;
TX_PIN_DIR = 1;
// Setup touch sensor pins
PORT_C.DDR.Pin4 = 0;
PORT_C.CR1.Pin4 = 0;
PORT_C.CR2.Pin4 = 1;
EXTI_CR1.PortC = EXTI_RISING_FALLING;
// Setup UART (115200 8N1, with interupt)
// 115200 | 9600 | 57600
UART1.CR3 &= ~(UART_CR3_STOP1 | UART_CR3_STOP2);
// UART1.BRR2 = 0x0B; // 0x03; // 0x11;
// UART1.BRR1 = 0x08; // 0x68; // 0x06;
UART1.BRR2 = 0x03;
UART1.BRR1 = 0x68;
UART1.CR2 = UART_CR2_TEN | UART_CR2_REN | UART_CR2_RXNE_IVT | UART_CR2_SBK;
CLK.Peripheral1.Serial1 = 1;
// Setup LED pin
LED_PIN_DIR = 1;
LED_PIN_CR1 = 1;
LED_PIN_CR2 = 0;
LED_PIN_OUT = 1;
// Setup timer 250ms tick
CLK.Peripheral1.Timer1 = 1;
const u16 div = 1599;
const u16 cou = 2500;
TIM1.PrescalerH = div >> 8;
TIM1.PrescalerL = div & 0xFF;
TIM1.AutoReloadH = cou >> 8;
TIM1.AutoReloadL = cou & 0xFF;
TIM1.Interrupt.UpdateInterrupt = 1;
TIM1.Control1.CounterEnable = 1;
#ifdef INVERSION
LED_PIN_OUT = 1;
#else
LED_PIN_OUT = 0;
#endif
#ifdef WATCHDOG
// Start watchdog
IWATCHDOG.Key = IndependWatchdogOn;
IWATCHDOG.Key = IndependWatchdogEdit;
IWATCHDOG.Prescaler = WatchdogPrescaler_256; // Around 128kHz/256=500Hz=2ms
IWATCHDOG.Reload = 0xFF; // 2ms*256=512ms
IWATCHDOG.Key = IndependWatchdogReset;
#endif
// Start interrupts
rim();
// Fast blink on start
/* for (u08 j = 0; j < 10; j++) {
LED_PIN_OUT ^= 1;
delay_tick(0xffff);
IWATCHDOG.Key = IndependWatchdogReset;
} */
// Just for test
CFG_GCR |= 0x02; // Set AL for disable main();
wfi();
// Infinite worker loop
for (;;) {
delay_tick(0xff);
#ifdef WATCHDOG
IWATCHDOG.Key = IndependWatchdogReset;
#endif
}
}