add files

This commit is contained in:
Kizarm 2024-01-16 16:14:54 +01:00
parent 8cb27e36d7
commit e777d9e58a
9 changed files with 19643 additions and 0 deletions

61
Makefile Normal file
View 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
View 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
View 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

File diff suppressed because it is too large Load diff

17668
stm32l4x2/STM32L4x2.h Normal file

File diff suppressed because it is too large Load diff

View 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
View 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
View 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
View 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 */