From b07c0607d32b5b9be56c9aaf37f4285a7638ebff Mon Sep 17 00:00:00 2001 From: Vitalii Popov Date: Wed, 14 May 2025 01:20:39 +0300 Subject: [PATCH] initial --- .gitignore | 1 + CMakeLists.txt | 39 ++ _cmake/sdcc-toolchain.cmake | 28 ++ _cmake/sdcc.cmake | 29 ++ _common/stm8s103f3.h | 74 ++++ _common/stm_base.h | 701 ++++++++++++++++++++++++++++++++++++ _common/type.h | 20 + build.sh | 4 + src/main.c | 312 ++++++++++++++++ 9 files changed, 1208 insertions(+) create mode 100644 .gitignore create mode 100644 CMakeLists.txt create mode 100644 _cmake/sdcc-toolchain.cmake create mode 100644 _cmake/sdcc.cmake create mode 100644 _common/stm8s103f3.h create mode 100644 _common/stm_base.h create mode 100644 _common/type.h create mode 100755 build.sh create mode 100644 src/main.c diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..84c048a --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/build/ diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..d1ea4f6 --- /dev/null +++ b/CMakeLists.txt @@ -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) diff --git a/_cmake/sdcc-toolchain.cmake b/_cmake/sdcc-toolchain.cmake new file mode 100644 index 0000000..aeb2a23 --- /dev/null +++ b/_cmake/sdcc-toolchain.cmake @@ -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 ") diff --git a/_cmake/sdcc.cmake b/_cmake/sdcc.cmake new file mode 100644 index 0000000..e1f8733 --- /dev/null +++ b/_cmake/sdcc.cmake @@ -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) diff --git a/_common/stm8s103f3.h b/_common/stm8s103f3.h new file mode 100644 index 0000000..9117573 --- /dev/null +++ b/_common/stm8s103f3.h @@ -0,0 +1,74 @@ +#ifndef STM8S103F3_DEF +#define STM8S103F3_DEF + +#include + +// 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 \ No newline at end of file diff --git a/_common/stm_base.h b/_common/stm_base.h new file mode 100644 index 0000000..10efcca --- /dev/null +++ b/_common/stm_base.h @@ -0,0 +1,701 @@ +#ifndef STM_BASE_H +#define STM_BASE_H + +#include + +// 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 \ No newline at end of file diff --git a/_common/type.h b/_common/type.h new file mode 100644 index 0000000..5d42455 --- /dev/null +++ b/_common/type.h @@ -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 \ No newline at end of file diff --git a/build.sh b/build.sh new file mode 100755 index 0000000..76e27d1 --- /dev/null +++ b/build.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +mkdir -p build +(cd build && cmake --toolchain ../_cmake/sdcc-toolchain.cmake .. && make) diff --git a/src/main.c b/src/main.c new file mode 100644 index 0000000..5ae1c3a --- /dev/null +++ b/src/main.c @@ -0,0 +1,312 @@ +#include +#include +#include +#include +#include + +#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 + } +} \ No newline at end of file