Compare commits
2 commits
8cb27e36d7
...
78c0c17ef3
Author | SHA1 | Date | |
---|---|---|---|
|
78c0c17ef3 | ||
|
e777d9e58a |
10 changed files with 19654 additions and 0 deletions
11
.gitignore
vendored
Normal file
11
.gitignore
vendored
Normal file
|
@ -0,0 +1,11 @@
|
|||
# kdevelop
|
||||
.kde*
|
||||
*.kdev4
|
||||
# other
|
||||
bld/*
|
||||
*.o
|
||||
*.pcm
|
||||
*.lst
|
||||
*.map
|
||||
*.bin
|
||||
*.elf
|
61
Makefile
Normal file
61
Makefile
Normal file
|
@ -0,0 +1,61 @@
|
|||
TARGET = stm32l4x2
|
||||
PRJ = example
|
||||
BLD = ./bld/
|
||||
# clang 18, modules experimental
|
||||
CC = clang
|
||||
CXX = clang++
|
||||
# arm-none-eabi- toolchain (+gcc)
|
||||
LD = arm-none-eabi-ld
|
||||
SIZE = arm-none-eabi-size
|
||||
DUMP = arm-none-eabi-objdump
|
||||
COPY = arm-none-eabi-objcopy
|
||||
|
||||
TGT = --target=thumbv7em-none-eabi -mthumb -mcpu=cortex-m4 -mfpu=fpv4-sp-d16 -mfloat-abi=hard
|
||||
LDLIBS = -L/usr/lib/gcc/arm-none-eabi/9.2.1/thumb/v7e-m+fp/hard -L./$(TARGET) -Tscript.ld -lgcc
|
||||
CFLAGS = -Wall $(TGT) -Oz -gdwarf-3 -I./$(TARGET) -ffunction-sections -fdata-sections -fno-exceptions
|
||||
LFLAGS = -nostart-files --gc-sections -Map=example.map
|
||||
MFLAGS = $(CFLAGS) -fmodules -fprebuilt-module-path=.
|
||||
VFLAGS = -std=c++20 -fno-rtti
|
||||
|
||||
VPATH = . ./$(TARGET)
|
||||
|
||||
# zdrojaky -> objekty
|
||||
OBJS = STM32L4x2_startup.o system.o
|
||||
MOBJS = main.o io.o
|
||||
|
||||
BOBJS = $(addprefix $(BLD),$(OBJS))
|
||||
|
||||
all: $(BLD) $(PRJ).elf
|
||||
# ... atd.
|
||||
# -include $(BLD)*.d
|
||||
# linker
|
||||
$(PRJ).elf: $(BOBJS) $(MOBJS)
|
||||
-@echo [LD $(TARGET)] $@
|
||||
@$(LD) $(LFLAGS) -o $(PRJ).elf $(BOBJS) $(MOBJS) $(LDLIBS)
|
||||
-@echo "size:"
|
||||
@$(SIZE) $(PRJ).elf
|
||||
-@echo "listing:"
|
||||
$(DUMP) -d $(PRJ).elf > $(PRJ).lst
|
||||
$(COPY) --strip-unneeded -O binary $(PRJ).elf $(PRJ).bin
|
||||
-@echo "OK."
|
||||
# preloz co je potreba
|
||||
$(BLD)%.o: %.c
|
||||
-@echo [CC $(TARGET)] $@
|
||||
@$(CC) -c $(CFLAGS) $< -o $@
|
||||
$(BLD)%.o: %.cpp
|
||||
-@echo [CXX $(TARGET)] $@
|
||||
@$(CXX) $(VFLAGS) -c $(CFLAGS) $< -o $@
|
||||
$(BLD):
|
||||
mkdir $(BLD)
|
||||
# MODULES #
|
||||
main.o: main.cpp io.pcm
|
||||
%.o: %.cpp
|
||||
-@echo [CXM $(TARGET)] $@
|
||||
@$(CXX) $(VFLAGS) -c $(MFLAGS) $< -o $@
|
||||
%.pcm: %.cpp
|
||||
-@echo [PRE $(TARGET)] $@
|
||||
@$(CXX) $(VFLAGS) -x c++-module $(TGT) -I./$(TARGET) -fno-exceptions $< --precompile -o $@
|
||||
# vycisti
|
||||
clean:
|
||||
rm -f $(BLD)* *.o *.lst *.bin *.elf *.map *.pcm *~
|
||||
.PHONY: all clean
|
186
io.cpp
Normal file
186
io.cpp
Normal file
|
@ -0,0 +1,186 @@
|
|||
module;
|
||||
#include "STM32L4x2.h"
|
||||
export module io;
|
||||
|
||||
/// Asociace port Adress a RCC clock
|
||||
struct GpioAssocPort {
|
||||
GPIOA_Type * portAdr;
|
||||
uint32_t clkMask;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief GPIO Configuration Mode enumeration
|
||||
*/
|
||||
typedef enum {
|
||||
GPIO_Mode_IN = 0x00, /*!< GPIO Input Mode */
|
||||
GPIO_Mode_OUT = 0x01, /*!< GPIO Output Mode */
|
||||
GPIO_Mode_AF = 0x02, /*!< GPIO Alternate function Mode */
|
||||
GPIO_Mode_AN = 0x03 /*!< GPIO Analog Mode */
|
||||
}GPIOMode_TypeDef;
|
||||
|
||||
/**
|
||||
* @brief GPIO Output type enumeration
|
||||
*/
|
||||
typedef enum {
|
||||
GPIO_OType_PP = 0x00,
|
||||
GPIO_OType_OD = 0x01
|
||||
}GPIOOType_TypeDef;
|
||||
/**
|
||||
* @brief GPIO Output Maximum frequency enumeration
|
||||
*/
|
||||
typedef enum {
|
||||
GPIO_Speed_LS = 0x00, /*!< Low speed */
|
||||
GPIO_Speed_MS = 0x01, /*!< Medium speed */
|
||||
GPIO_Speed_FS = 0x02, /*!< Fast speed */
|
||||
GPIO_Speed_HS = 0x03 /*!< Very High speed */
|
||||
}GPIOSpeed_TypeDef;
|
||||
/**
|
||||
* @brief GPIO Configuration PullUp PullDown enumeration
|
||||
*/
|
||||
typedef enum {
|
||||
GPIO_PuPd_NOPULL = 0x00,
|
||||
GPIO_PuPd_UP = 0x01,
|
||||
GPIO_PuPd_DOWN = 0x02
|
||||
}GPIOPuPd_TypeDef;
|
||||
|
||||
/** Vstupní parametry metod */
|
||||
typedef enum {
|
||||
GPIO_Dir_Mode_IN = 0x00, /*!< GPIO Input Mode */
|
||||
GPIO_Dir_Mode_OUT = 0x01, /*!< GPIO Output Mode */
|
||||
} GPIODir_TypeDef;
|
||||
|
||||
/// Enum pro PortNumber
|
||||
typedef enum {
|
||||
GpioPortA,
|
||||
GpioPortB,
|
||||
GpioPortC,
|
||||
GpioPortD,
|
||||
GpioPortE,
|
||||
GpioPortH,
|
||||
} GpioPortNum;
|
||||
namespace io {
|
||||
/** @file
|
||||
* @brief Obecný GPIO pin.
|
||||
*
|
||||
* @class GpioClass
|
||||
* @brief Obecný GPIO pin.
|
||||
*
|
||||
*/
|
||||
export class GpioClass {
|
||||
public:
|
||||
/** Konstruktor
|
||||
@param port GpioPortA | GpioPortB | GpioPortC | GpioPortD | GpioPortF
|
||||
@param no číslo pinu na portu
|
||||
@param type IN, OUT, AF, AN default OUT
|
||||
*/
|
||||
GpioClass (GpioPortNum const port, const uint32_t no, const GPIOMode_TypeDef type = GPIO_Mode_OUT);
|
||||
/// Nastav pin @param b na tuto hodnotu
|
||||
const GpioClass& operator<< (const bool b) const {
|
||||
if (b) io->BSRR.R = (uint32_t) pos;
|
||||
else io->BSRR.R = (uint32_t) pos << 16;
|
||||
return *this;
|
||||
}
|
||||
/// Nastav pin na log. H
|
||||
const GpioClass& operator+ (void) const {
|
||||
io->BSRR.R = (uint32_t) pos;
|
||||
return *this;
|
||||
}
|
||||
/// Nastav pin na log. L
|
||||
const GpioClass& operator- (void) const {
|
||||
io->BSRR.R = (uint32_t) pos << 16;
|
||||
return *this;
|
||||
}
|
||||
/// Změň hodnotu pinu
|
||||
const GpioClass& operator~ (void) const {
|
||||
io->ODR.R ^= pos;
|
||||
return *this;
|
||||
};
|
||||
/// Načti logickou hodnotu na pinu
|
||||
const bool get (void) const {
|
||||
if (io->IDR.R & pos) return true;
|
||||
else return false;
|
||||
};
|
||||
/// A to samé jako operátor
|
||||
const GpioClass& operator>> (bool& b) const {
|
||||
b = get();
|
||||
return *this;
|
||||
}
|
||||
/// Různá nastavení
|
||||
void setMode (GPIOMode_TypeDef p) {
|
||||
uint32_t dno = num * 2;
|
||||
io->MODER.R &= ~(3UL << dno);
|
||||
io->MODER.R |= (p << dno);
|
||||
}
|
||||
void setOType (GPIOOType_TypeDef p) {
|
||||
io->OTYPER.R &= ~(1UL << num);
|
||||
io->OTYPER.R |= (p << num);
|
||||
}
|
||||
void setSpeed (GPIOSpeed_TypeDef p) {
|
||||
uint32_t dno = num * 2;
|
||||
io->OSPEEDR.R &= ~(3UL << dno);
|
||||
io->OSPEEDR.R |= (p << dno);
|
||||
}
|
||||
void setPuPd (GPIOPuPd_TypeDef p) {
|
||||
uint32_t dno = num * 2;
|
||||
io->PUPDR.R &= ~(3UL << dno);
|
||||
io->PUPDR.R |= (p << dno);
|
||||
}
|
||||
void setAF (unsigned af) {
|
||||
unsigned int pd,pn = num;
|
||||
pd = (pn & 7) << 2; pn >>= 3;
|
||||
if (pn) {
|
||||
io->AFRH.R &= ~(0xFU << pd);
|
||||
io->AFRH.R |= ( af << pd);
|
||||
} else {
|
||||
io->AFRL.R &= ~(0xFU << pd);
|
||||
io->AFRL.R |= ( af << pd);
|
||||
}
|
||||
}
|
||||
void setDir (GPIODir_TypeDef p) {
|
||||
uint32_t dno = num * 2;
|
||||
if (p) io->MODER.R |= (1UL << dno);
|
||||
else io->MODER.R &= ~(3UL << dno);
|
||||
}
|
||||
private:
|
||||
/// Port.
|
||||
GPIOA_Type * const io; // může být klidně i odkaz, ale je to stejné, necháme to tak jak bylo
|
||||
/// A pozice pinu na něm, stačí 16.bit
|
||||
const uint16_t pos;
|
||||
/// pro funkce setXXX necháme i číslo pinu
|
||||
const uint16_t num;
|
||||
|
||||
};
|
||||
#define RCC_AHB2ENR_GPIOAEN ((uint32_t)0x00000001u) /*!< Ofs=0 IO port A clock enable */
|
||||
#define RCC_AHB2ENR_GPIOBEN ((uint32_t)0x00000002u) /*!< Ofs=1 IO port B clock enable */
|
||||
#define RCC_AHB2ENR_GPIOCEN ((uint32_t)0x00000004u) /*!< Ofs=2 IO port C clock enable */
|
||||
#define RCC_AHB2ENR_GPIODEN ((uint32_t)0x00000008u) /*!< Ofs=3 IO port D clock enable */
|
||||
#define RCC_AHB2ENR_GPIOEEN ((uint32_t)0x00000010u) /*!< Ofs=4 IO port E clock enable */
|
||||
#define RCC_AHB2ENR_GPIOHEN ((uint32_t)0x00000080u) /*!< Ofs=7 IO port H clock enable */
|
||||
|
||||
#define pGPIOA ((GPIOA_Type * const) 0x48000000u) /*!< General-purpose I/Os */
|
||||
#define pGPIOB ((GPIOA_Type * const) 0x48000400u) /*!< General-purpose I/Os */
|
||||
#define pGPIOC ((GPIOA_Type * const) 0x48000800u) /*!< General-purpose I/Os */
|
||||
#define pGPIOD ((GPIOA_Type * const) 0x48000C00u) /*!< General-purpose I/Os */
|
||||
#define pGPIOE ((GPIOA_Type * const) 0x48001000u) /*!< General-purpose I/Os */
|
||||
#define pGPIOH ((GPIOA_Type * const) 0x48001C00u) /*!< General-purpose I/Os */
|
||||
|
||||
static const struct GpioAssocPort cPortTab[] = {
|
||||
{pGPIOA, RCC_AHB2ENR_GPIOAEN},
|
||||
{pGPIOB, RCC_AHB2ENR_GPIOBEN},
|
||||
{pGPIOC, RCC_AHB2ENR_GPIOCEN},
|
||||
{pGPIOD, RCC_AHB2ENR_GPIODEN},
|
||||
{pGPIOE, RCC_AHB2ENR_GPIOEEN},
|
||||
{pGPIOH, RCC_AHB2ENR_GPIOHEN},
|
||||
};
|
||||
|
||||
GpioClass::GpioClass (GpioPortNum const port, const uint32_t no, const GPIOMode_TypeDef type) :
|
||||
io (cPortTab[port].portAdr), pos(1UL << no), num(no) {
|
||||
// Povol hodiny
|
||||
RCC.AHB2ENR.R |= cPortTab[port].clkMask;
|
||||
setMode (type);
|
||||
}
|
||||
export void wait (const unsigned ms = 500000u) {
|
||||
volatile unsigned n;
|
||||
for (n=0u; n<ms; n+=1) asm volatile ("nop");
|
||||
}
|
||||
};
|
12
main.cpp
Normal file
12
main.cpp
Normal file
|
@ -0,0 +1,12 @@
|
|||
/* SIMPLE EXAMPLE: LED blinking */
|
||||
import io; // use module !!!
|
||||
//////////////////////////////////////
|
||||
static io::GpioClass led (GpioPortA, 10);
|
||||
|
||||
int main () {
|
||||
for (;;) {
|
||||
~led; // change status - unary ~
|
||||
io::wait ();
|
||||
}
|
||||
return 0;
|
||||
}
|
1112
stm32l4x2/CortexM4.h
Normal file
1112
stm32l4x2/CortexM4.h
Normal file
File diff suppressed because it is too large
Load diff
17668
stm32l4x2/STM32L4x2.h
Normal file
17668
stm32l4x2/STM32L4x2.h
Normal file
File diff suppressed because it is too large
Load diff
248
stm32l4x2/STM32L4x2_startup.c
Normal file
248
stm32l4x2/STM32L4x2_startup.c
Normal file
|
@ -0,0 +1,248 @@
|
|||
#include <stdint.h>
|
||||
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
extern void (*__init_array_start)();
|
||||
extern void (*__init_array_end) ();
|
||||
void static_init() {
|
||||
void (**p)();
|
||||
for (p = &__init_array_start; p < &__init_array_end; p++) (*p)();
|
||||
}
|
||||
#define WEAK __attribute__ ((weak))
|
||||
#define ALIAS(f) __attribute__ ((weak, alias (#f)))
|
||||
|
||||
extern unsigned int _estack;
|
||||
extern unsigned int _sidata;
|
||||
extern unsigned int _sdata;
|
||||
extern unsigned int _edata;
|
||||
extern unsigned int _sbss;
|
||||
extern unsigned int _ebss;
|
||||
|
||||
WEAK void Reset_Handler (void);
|
||||
WEAK void DefaultHandler (void);
|
||||
void NonMaskableInt_Handler (void) ALIAS(Default_Handler);
|
||||
void HardFault_Handler (void) ALIAS(Default_Handler);
|
||||
void MemoryManagement_Handler (void) ALIAS(Default_Handler);
|
||||
void BusFault_Handler (void) ALIAS(Default_Handler);
|
||||
void UsageFault_Handler (void) ALIAS(Default_Handler);
|
||||
void SVCall_Handler (void) ALIAS(Default_Handler);
|
||||
void DebugMonitor_Handler (void) ALIAS(Default_Handler);
|
||||
void PendSV_Handler (void) ALIAS(Default_Handler);
|
||||
void SysTick_Handler (void) ALIAS(Default_Handler);
|
||||
|
||||
void WWDG_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void PVD_PVM_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void RTC_TAMP_STAMP_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void RTC_WKUP_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void FLASH_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void RCC_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void EXTI0_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void EXTI1_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void EXTI2_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void EXTI3_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void EXTI4_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void DMA1_CH1_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void DMA1_CH2_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void DMA1_CH3_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void DMA1_CH4_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void DMA1_CH5_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void DMA1_CH6_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void DMA1_CH7_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void ADC1_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void CAN1_TX_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void CAN1_RX0_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void CAN1_RX1_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void CAN1_SCE_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void EXTI9_5_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void TIM1_BRK_TIM15_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void TIM1_UP_TIM16_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void TIM1_TRG_COM_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void TIM1_CC_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void TIM2_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void TIM3_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void I2C1_EV_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void I2C1_ER_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void I2C2_EV_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void I2C2_ER_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void SPI1_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void SPI2_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void USART1_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void USART2_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void USART3_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void EXTI15_10_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void RTC_ALARM_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void DFSDM1_FLT3_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void ADC3_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void SDMMC1_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void SPI3_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void UART4_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void TIM6_DACUNDER_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void TIM7_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void DMA2_CH1_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void DMA2_CH2_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void DMA2_CH3_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void DMA2_CH4_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void DMA2_CH5_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void DFSDM1_FLT0_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void DFSDM1_FLT1_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void DFSDM1_FLT2_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void COMP_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void LPTIM1_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void LPTIM2_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void USB_FS_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void DMA2_CH6_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void DMA2_CH7_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void LPUART1_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void QUADSPI_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void I2C3_EV_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void I2C3_ER_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void SAI1_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void SWPMI1_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void TSC_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void LCD_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void AES_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void RNG_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void CRS_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void I2C4_EV_IRQHandler (void) ALIAS(Default_Handler);
|
||||
void I2C4_ER_IRQHandler (void) ALIAS(Default_Handler);
|
||||
|
||||
extern int main (void);
|
||||
extern void SystemInit (void);
|
||||
extern void SystemCoreClockUpdate (void);
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}; // extern "C"
|
||||
#endif
|
||||
typedef void (*handler) (void);
|
||||
__attribute__ ((section(".isr_vector")))
|
||||
handler Vectors[] = {
|
||||
(handler) &_estack,
|
||||
Reset_Handler,
|
||||
NonMaskableInt_Handler,
|
||||
HardFault_Handler,
|
||||
MemoryManagement_Handler,
|
||||
BusFault_Handler,
|
||||
UsageFault_Handler,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
SVCall_Handler,
|
||||
DebugMonitor_Handler,
|
||||
0,
|
||||
PendSV_Handler,
|
||||
SysTick_Handler,
|
||||
|
||||
WWDG_IRQHandler,
|
||||
PVD_PVM_IRQHandler,
|
||||
RTC_TAMP_STAMP_IRQHandler,
|
||||
RTC_WKUP_IRQHandler,
|
||||
FLASH_IRQHandler,
|
||||
RCC_IRQHandler,
|
||||
EXTI0_IRQHandler,
|
||||
EXTI1_IRQHandler,
|
||||
EXTI2_IRQHandler,
|
||||
EXTI3_IRQHandler,
|
||||
EXTI4_IRQHandler,
|
||||
DMA1_CH1_IRQHandler,
|
||||
DMA1_CH2_IRQHandler,
|
||||
DMA1_CH3_IRQHandler,
|
||||
DMA1_CH4_IRQHandler,
|
||||
DMA1_CH5_IRQHandler,
|
||||
DMA1_CH6_IRQHandler,
|
||||
DMA1_CH7_IRQHandler,
|
||||
ADC1_IRQHandler,
|
||||
CAN1_TX_IRQHandler,
|
||||
CAN1_RX0_IRQHandler,
|
||||
CAN1_RX1_IRQHandler,
|
||||
CAN1_SCE_IRQHandler,
|
||||
EXTI9_5_IRQHandler,
|
||||
TIM1_BRK_TIM15_IRQHandler,
|
||||
TIM1_UP_TIM16_IRQHandler,
|
||||
TIM1_TRG_COM_IRQHandler,
|
||||
TIM1_CC_IRQHandler,
|
||||
TIM2_IRQHandler,
|
||||
TIM3_IRQHandler,
|
||||
0,
|
||||
I2C1_EV_IRQHandler,
|
||||
I2C1_ER_IRQHandler,
|
||||
I2C2_EV_IRQHandler,
|
||||
I2C2_ER_IRQHandler,
|
||||
SPI1_IRQHandler,
|
||||
SPI2_IRQHandler,
|
||||
USART1_IRQHandler,
|
||||
USART2_IRQHandler,
|
||||
USART3_IRQHandler,
|
||||
EXTI15_10_IRQHandler,
|
||||
RTC_ALARM_IRQHandler,
|
||||
DFSDM1_FLT3_IRQHandler,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
ADC3_IRQHandler,
|
||||
0,
|
||||
SDMMC1_IRQHandler,
|
||||
0,
|
||||
SPI3_IRQHandler,
|
||||
UART4_IRQHandler,
|
||||
0,
|
||||
TIM6_DACUNDER_IRQHandler,
|
||||
TIM7_IRQHandler,
|
||||
DMA2_CH1_IRQHandler,
|
||||
DMA2_CH2_IRQHandler,
|
||||
DMA2_CH3_IRQHandler,
|
||||
DMA2_CH4_IRQHandler,
|
||||
DMA2_CH5_IRQHandler,
|
||||
DFSDM1_FLT0_IRQHandler,
|
||||
DFSDM1_FLT1_IRQHandler,
|
||||
DFSDM1_FLT2_IRQHandler,
|
||||
COMP_IRQHandler,
|
||||
LPTIM1_IRQHandler,
|
||||
LPTIM2_IRQHandler,
|
||||
USB_FS_IRQHandler,
|
||||
DMA2_CH6_IRQHandler,
|
||||
DMA2_CH7_IRQHandler,
|
||||
LPUART1_IRQHandler,
|
||||
QUADSPI_IRQHandler,
|
||||
I2C3_EV_IRQHandler,
|
||||
I2C3_ER_IRQHandler,
|
||||
SAI1_IRQHandler,
|
||||
0,
|
||||
SWPMI1_IRQHandler,
|
||||
TSC_IRQHandler,
|
||||
LCD_IRQHandler,
|
||||
AES_IRQHandler,
|
||||
RNG_IRQHandler,
|
||||
0,
|
||||
CRS_IRQHandler,
|
||||
I2C4_EV_IRQHandler,
|
||||
I2C4_ER_IRQHandler,
|
||||
|
||||
};
|
||||
void Reset_Handler(void) {
|
||||
unsigned int *src, *dst, *end;
|
||||
/* Zero fill the bss section */
|
||||
dst = &_sbss;
|
||||
end = &_ebss;
|
||||
while (dst < end) *dst++ = 0U;
|
||||
|
||||
/* Copy data section from flash to RAM */
|
||||
src = &_sidata;
|
||||
dst = &_sdata;
|
||||
end = &_edata;
|
||||
while (dst < end) *dst++ = *src++;
|
||||
|
||||
SystemInit();
|
||||
SystemCoreClockUpdate(); // Potřebné pro USART
|
||||
static_init(); // Zde zavolám globální konstruktory
|
||||
|
||||
main();
|
||||
|
||||
for (;;);
|
||||
}
|
||||
|
||||
void Default_Handler (void) {
|
||||
asm volatile ("bkpt 1");
|
||||
}
|
94
stm32l4x2/script.ld
Normal file
94
stm32l4x2/script.ld
Normal file
|
@ -0,0 +1,94 @@
|
|||
/* Entry Point */
|
||||
ENTRY(Reset_Handler)
|
||||
|
||||
/* Generate a link error if heap and stack don't fit into RAM */
|
||||
_Min_Heap_Size = 0; /* required amount of heap */
|
||||
_Min_Stack_Size = 0; /* required amount of stack */
|
||||
|
||||
/* Specify the memory areas */
|
||||
MEMORY {
|
||||
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 160K
|
||||
USER (xr) : ORIGIN = 0x08010000, LENGTH = 448K
|
||||
}
|
||||
|
||||
/* Highest address of the user mode stack */
|
||||
_estack = ORIGIN(RAM) + LENGTH(RAM);
|
||||
_total_len = _etext - _program_begin;
|
||||
|
||||
/* Define output sections */
|
||||
SECTIONS {
|
||||
/* The startup code goes first into FLASH */
|
||||
/* The program code and other data goes into FLASH */
|
||||
.text : {
|
||||
. = ALIGN(4);
|
||||
_program_begin = .;
|
||||
PROVIDE_HIDDEN (_vect_tab_begin = .);
|
||||
KEEP(*(.isr_vector)) /* Startup code */
|
||||
PROVIDE_HIDDEN (_soft_tab_begin = .);
|
||||
KEEP(*(.sft_vector)) /* Soft IRQ VECTORS */
|
||||
KEEP(*(.usb_vector)) /* USB vector code */
|
||||
. = ALIGN(4);
|
||||
*(.text) /* .text sections (code) */
|
||||
*(.text*) /* .text* sections (code) */
|
||||
*(.rodata) /* .rodata sections (constants, strings, etc.) */
|
||||
*(.rodata*) /* .rodata* sections (constants, strings, etc.) */
|
||||
*(.glue_7) /* glue arm to thumb code */
|
||||
*(.glue_7t) /* glue thumb to arm code */
|
||||
*(.eh_frame)
|
||||
|
||||
*(.init)
|
||||
*(.fini)
|
||||
/* Pro použití statických konstruktorů v C++, KEEP musí být použit při gc */
|
||||
. = ALIGN(4);
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP (*(.ctors)) /* for clang */
|
||||
KEEP (*(.init_array*)) /* for gcc */
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
_etext = .; /* define a global symbols at end of code */
|
||||
} >RAM
|
||||
|
||||
|
||||
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >RAM
|
||||
|
||||
.ARM : {
|
||||
__exidx_start = .;
|
||||
*(.ARM.exidx*)
|
||||
__exidx_end = .;
|
||||
} >RAM
|
||||
|
||||
/* used by the startup to initialize data */
|
||||
_sidata = .;
|
||||
|
||||
/* Initialized data sections goes into RAM, load LMA copy after code */
|
||||
.data : AT ( _sidata ) {
|
||||
. = ALIGN(4);
|
||||
_sdata = .; /* create a global symbol at data start */
|
||||
*(.data) /* .data sections */
|
||||
*(.data*) /* .data* sections */
|
||||
_edata = .; /* define a global symbol at data end */
|
||||
} >RAM
|
||||
|
||||
/* Uninitialized data section */
|
||||
. = ALIGN(4);
|
||||
.bss : {
|
||||
/* This is used by the startup in order to initialize the .bss secion */
|
||||
_sbss = .; /* define a global symbol at bss start */
|
||||
__bss_start__ = _sbss;
|
||||
*(.bss)
|
||||
*(.bss*)
|
||||
*(COMMON)
|
||||
|
||||
__bss_end__ = _ebss;
|
||||
_ebss = .; /* define a global symbol at bss end */
|
||||
} >RAM
|
||||
|
||||
/* Remove information from the standard libraries */
|
||||
/DISCARD/ : {
|
||||
*(.comment*)
|
||||
*(.ARM.*)
|
||||
}
|
||||
|
||||
.ARM.attributes 0 : { *(.ARM.attributes) }
|
||||
}
|
207
stm32l4x2/system.cpp
Normal file
207
stm32l4x2/system.cpp
Normal file
|
@ -0,0 +1,207 @@
|
|||
#include "CortexM4.h"
|
||||
#include "system.h"
|
||||
/** @file
|
||||
* @brief Základní nastavení systému.
|
||||
*
|
||||
* */
|
||||
|
||||
#if !defined (HSE_VALUE)
|
||||
#define HSE_VALUE 8000000U /*!< Value of the External oscillator in Hz */
|
||||
#endif /* HSE_VALUE */
|
||||
|
||||
#if !defined (MSI_VALUE)
|
||||
#define MSI_VALUE 4000000U /*!< Value of the Internal oscillator in Hz */
|
||||
#endif /* MSI_VALUE */
|
||||
|
||||
#if !defined (HSI_VALUE)
|
||||
#define HSI_VALUE 16000000U /*!< Value of the Internal oscillator in Hz */
|
||||
#endif /* HSI_VALUE */
|
||||
|
||||
/// Použito v locker.h
|
||||
//volatile int gblMutex = 0;
|
||||
/// Systémové hodiny
|
||||
uint32_t SystemCoreClock = 4000000U;
|
||||
|
||||
const uint8_t AHBPrescTable[16] = {0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 1U, 2U, 3U, 4U, 6U, 7U, 8U, 9U};
|
||||
//const uint8_t APBPrescTable[8] = {0U, 0U, 0U, 0U, 1U, 2U, 3U, 4U};
|
||||
const uint32_t MSIRangeTable[12] = {100000U, 200000U, 400000U, 800000U, 1000000U, 2000000U,
|
||||
4000000U, 8000000U, 16000000U, 24000000U, 32000000U, 48000000U
|
||||
};
|
||||
|
||||
// In Linker script
|
||||
extern uint32_t _vect_tab_begin;
|
||||
|
||||
/**
|
||||
* @brief Configures the System clock source, PLL Multiplier and Divider factors,
|
||||
* AHB/APBx prescalers and Flash settings
|
||||
*
|
||||
* NOTE: This function should be called only once the RCC clock configuration
|
||||
* is reset to the default reset state (done in SystemInit() function).
|
||||
*/
|
||||
static inline void HSE72MhzClock (void) {
|
||||
RCC.APB1ENR1.B.PWREN = SET;
|
||||
// Set power Range 1
|
||||
PWR.CR1.modify([](auto & r)->auto {
|
||||
r.B.VOS = 1u;
|
||||
return r.R;
|
||||
});
|
||||
while (PWR.SR2.B.VOSF);
|
||||
PWR.CR2.B.USV = SET; // !!! bylo nutno pridat
|
||||
/* Adjust Flash latency */
|
||||
FLASH.ACR.modify([](auto & r)->auto {
|
||||
r.B.DCEN = SET;
|
||||
r.B.ICEN = SET;
|
||||
r.B.PRFTEN = SET;
|
||||
r.B.LATENCY = 4u;
|
||||
return r.R;
|
||||
});
|
||||
RCC.CR.modify([=](auto & r)->auto {
|
||||
r.B.MSIRANGE = 11u; // MSI 48 MHz (USB)
|
||||
r.B.MSIRGSEL = SET;
|
||||
r.B.MSION = SET;
|
||||
r.B.HSEON = SET;
|
||||
return r.R;
|
||||
});
|
||||
while (RCC.CR.B.HSERDY == 0u);
|
||||
while (RCC.CR.B.MSIRDY == 0u);
|
||||
RCC.PLLCFGR.modify([](auto & r)->auto {
|
||||
r.B.PLLSRC = 3u; // HSE 8 MHz
|
||||
r.B.PLLM = 0u; // : 1 => 8 MHz
|
||||
r.B.PLLN = 36u; // 36 x => 288 MHz
|
||||
|
||||
r.B.PLLR = 1u; // : 4 => 72MHz (SYSTEM)
|
||||
r.B.PLLQ = 2u; // : 6 => 48MHz (UNUSED)
|
||||
return r.R;
|
||||
});
|
||||
RCC.CR.B.PLLON = SET;
|
||||
while (RCC.CR.B.PLLRDY == 0u);
|
||||
RCC.PLLCFGR.modify([](auto & r)->auto {
|
||||
r.B.PLLREN = SET; // PLLCLK output enable
|
||||
r.B.PLLQEN = RESET; // PLL PLL48M1CLK output disable
|
||||
return r.R;
|
||||
});
|
||||
RCC.CFGR.modify([](auto & r)->auto {
|
||||
r.B.SW = 3u; // PLL 72MHz selected as system clock
|
||||
return r.R;
|
||||
});
|
||||
RCC.CCIPR.modify([](auto & r)->auto {
|
||||
r.B.CLK48SEL = 3u; // MSI clock selected as 48 MHz clock
|
||||
return r.R;
|
||||
});
|
||||
#ifdef USE_USB
|
||||
/* enable GPIOA clock */
|
||||
RCC.AHB2ENR.B.GPIOAEN = SET;
|
||||
/* set GP11 and GP12 as USB data pins AF10 */
|
||||
GPIOA.AFRH.R |= (0x0A << 12) | (0x0A << 16);
|
||||
GPIOA.MODER.R &= ~((0x03 << 22) | (0x03 << 24));
|
||||
GPIOA.MODER.R |= (0x02 << 22) | (0x02 << 24);
|
||||
GPIOA.OSPEEDR.R |= (0x03 << 22) | (0x03 << 24);
|
||||
#endif // USE_USB
|
||||
}
|
||||
void SystemInit (void) {
|
||||
/* FPU settings
|
||||
* Zapíná FPU, pokud je přítomen (ano) a při překladu je použit parametr -mfpu=fpv4-sp-d16
|
||||
*/
|
||||
#if (__FPU_PRESENT == 1) && (__ARM_PCS_VFP == 1)
|
||||
SCB.CPACR |= ( (3UL << 10*2) | (3UL << 11*2)); /* set CP10 and CP11 Full Access */
|
||||
#else
|
||||
#warning "FPU not allowed"
|
||||
#endif
|
||||
|
||||
/* Reset the RCC clock configuration to the default reset state ------------*/
|
||||
/* Set MSION bit */
|
||||
RCC.CR.B.MSION = SET;
|
||||
|
||||
/* Reset CFGR register */
|
||||
RCC.CFGR.R = 0x00000000U;
|
||||
|
||||
/* Reset HSEON, CSSON , HSION, and PLLON bits */
|
||||
RCC.CR.R &= 0xEAF6FFFFU;
|
||||
|
||||
/* Reset PLLCFGR register */
|
||||
RCC.PLLCFGR.R = 0x00001000U;
|
||||
|
||||
/* Reset HSEBYP bit */
|
||||
RCC.CR.R &= 0xFFFBFFFFU;
|
||||
|
||||
/* Disable all interrupts */
|
||||
RCC.CIER.R = 0x00000000U;
|
||||
|
||||
|
||||
/* Configure the Vector Table location add offset address ------------------*/
|
||||
SCB.VTOR.R = (uint32_t) &_vect_tab_begin; /* Vector Table Relocation in SRAM/FLASH */
|
||||
|
||||
/* Configure the System clock source, PLL Multiplier and Divider factors,
|
||||
AHB/APBx prescalers and Flash settings ----------------------------------*/
|
||||
/* tady je ještě nastavení flash cache, priority grouping NVIC (asi zbytečné) */
|
||||
HSE72MhzClock();
|
||||
}
|
||||
void UserSystemInit () {
|
||||
SCB.VTOR.R = (uint32_t) &_vect_tab_begin;
|
||||
}
|
||||
/* Převzato z HAL, zde bude důležité zřejmě jen msirange, v low power je lépe všechny HS oscilátory vypnout.
|
||||
* */
|
||||
void SystemCoreClockUpdate (void) {
|
||||
uint32_t tmp = 0U, msirange = 0U, pllvco = 0U, pllr = 2U, pllsource = 0U, pllm = 2U;
|
||||
|
||||
/* Get MSI Range frequency--------------------------------------------------*/
|
||||
if (RCC.CR.B.MSIRGSEL == 0) {
|
||||
/* MSISRANGE from RCC_CSR applies */
|
||||
msirange = RCC.CSR.B.MSISRANGE;
|
||||
} else {
|
||||
/* MSIRANGE from RCC_CR applies */
|
||||
msirange = RCC.CR.B.MSIRANGE;
|
||||
}
|
||||
/* MSI frequency range in HZ */
|
||||
msirange = MSIRangeTable[msirange];
|
||||
|
||||
/* Get SYSCLK source -------------------------------------------------------*/
|
||||
switch (RCC.CFGR.B.SWS) {
|
||||
case 0x00: /* MSI used as system clock source */
|
||||
SystemCoreClock = msirange;
|
||||
break;
|
||||
|
||||
case 0x01: /* HSI used as system clock source */
|
||||
SystemCoreClock = HSI_VALUE;
|
||||
break;
|
||||
|
||||
case 0x02: /* HSE used as system clock source */
|
||||
SystemCoreClock = HSE_VALUE;
|
||||
break;
|
||||
|
||||
case 0x03: /* PLL used as system clock source */
|
||||
/* PLL_VCO = (HSE_VALUE or HSI_VALUE or MSI_VALUE/ PLLM) * PLLN
|
||||
SYSCLK = PLL_VCO / PLLR
|
||||
*/
|
||||
pllsource = RCC.PLLCFGR.B.PLLSRC;
|
||||
pllm = RCC.PLLCFGR.B.PLLM + 1U ;
|
||||
|
||||
switch (pllsource) {
|
||||
case 0x02: /* HSI used as PLL clock source */
|
||||
pllvco = (HSI_VALUE / pllm);
|
||||
break;
|
||||
|
||||
case 0x03: /* HSE used as PLL clock source */
|
||||
pllvco = (HSE_VALUE / pllm);
|
||||
break;
|
||||
|
||||
default: /* MSI used as PLL clock source */
|
||||
pllvco = (msirange / pllm);
|
||||
break;
|
||||
}
|
||||
pllvco = pllvco * RCC.PLLCFGR.B.PLLN;
|
||||
pllr = (RCC.PLLCFGR.B.PLLR + 1U) * 2U;
|
||||
SystemCoreClock = pllvco/pllr;
|
||||
break;
|
||||
|
||||
default: // zbytecne
|
||||
SystemCoreClock = msirange;
|
||||
break;
|
||||
}
|
||||
/* Compute HCLK clock frequency --------------------------------------------*/
|
||||
/* Get HCLK prescaler */
|
||||
tmp = AHBPrescTable[RCC.CFGR.B.HPRE];
|
||||
/* HCLK clock frequency */
|
||||
SystemCoreClock >>= tmp;
|
||||
}
|
||||
|
55
stm32l4x2/system.h
Normal file
55
stm32l4x2/system.h
Normal file
|
@ -0,0 +1,55 @@
|
|||
#ifndef __SYSTEM_STM32L4XX_H
|
||||
#define __SYSTEM_STM32L4XX_H
|
||||
#include <stdint.h>
|
||||
|
||||
/** @file
|
||||
* @brief Základní nastavení CPU.
|
||||
*
|
||||
* Doplněné o DBGMCU pro debug ve sleep módu.
|
||||
* */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
/** System Clock Frequency (Core Clock) */
|
||||
extern uint32_t SystemCoreClock;
|
||||
/** Inicializace jádra a hodin periferií */
|
||||
extern void SystemInit (void);
|
||||
/** Spočte frekvenci jádra v závislosti na nastavení */
|
||||
extern void SystemCoreClockUpdate (void);
|
||||
|
||||
/** Inicializace jen tabulky vektorů, hodiny a flash inicializovány bootloaderem */
|
||||
extern void UserSystemInit (void);
|
||||
/// Control registr DEBUG MCU
|
||||
typedef union {
|
||||
struct {
|
||||
uint32_t DBG_SLEEP : 1; //!< Debug Sleep mode
|
||||
uint32_t DBG_STOP : 1; //!< Debug Stop mode
|
||||
uint32_t DBG_STANDBY : 1; //!< Debug Standby mode
|
||||
uint32_t UNUSED1 : 2;
|
||||
uint32_t TRACE_IOEN : 1; //!< Trace pin assignment control
|
||||
uint32_t TRACE_MODE : 2; //!< TRACE pin assignment for Asynchronous/Synchronous Mode, TRACEDATA size
|
||||
uint32_t UNUSED2 : 24;
|
||||
} B; //!< jednotlivé bity
|
||||
uint32_t R; //!< Celková hodnota
|
||||
} DBGMCU_CR;
|
||||
/// Blok řízení DEBUG MCU
|
||||
typedef struct {
|
||||
volatile uint32_t IDCODE; //!< ID procesoru
|
||||
volatile DBGMCU_CR CR; //!< Řízení debug při low power modech.
|
||||
volatile uint32_t APB1_FZ1; //!< chování periferií při debug
|
||||
volatile uint32_t APB1_FZ2; //!< chování periferií při debug
|
||||
volatile uint32_t APB2_FZ; //!< chování periferií při debug
|
||||
} DBGMCU_L4;
|
||||
/// Adresa DBGMCU bloku
|
||||
static DBGMCU_L4 * const MDBGMCU = (DBGMCU_L4 *) 0xE0042000;
|
||||
/// Pokud použijeme v programu wfi/wfe, je nutné povolit debug i v tt. módu.
|
||||
static inline void EnableDebugOnSleep (void) {
|
||||
MDBGMCU->CR.B.DBG_SLEEP = 1;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*__SYSTEM_STM32L4XX_H */
|
Loading…
Reference in a new issue