From 8280892bab7d7a3824de70b3b241f7c3a10edb65 Mon Sep 17 00:00:00 2001 From: perigoso Date: Fri, 2 Jul 2021 16:03:38 +0100 Subject: [PATCH 01/13] external: add sam3u family cmsis pack Signed-off-by: perigoso --- .gitmodules | 3 +++ external/cmsis-dfp-sam3u | 1 + 2 files changed, 4 insertions(+) create mode 160000 external/cmsis-dfp-sam3u diff --git a/.gitmodules b/.gitmodules index d1f98869..ab8c80ab 100644 --- a/.gitmodules +++ b/.gitmodules @@ -16,3 +16,6 @@ [submodule "external/cmsis-dfp-sams70"] path = external/cmsis-dfp-sams70 url = https://github.com/cmsis-packs/cmsis-dfp-sams70 +[submodule "external/cmsis-dfp-sam3u"] + path = external/cmsis-dfp-sam3u + url = https://github.com/cmsis-packs/cmsis-dfp-sam3u diff --git a/external/cmsis-dfp-sam3u b/external/cmsis-dfp-sam3u new file mode 160000 index 00000000..32d3f749 --- /dev/null +++ b/external/cmsis-dfp-sam3u @@ -0,0 +1 @@ +Subproject commit 32d3f7491bfd96741827cb9e0dbd60076d80987a From a96ff0de3c87a6a78cbd59d03fae37b7d7233cfe Mon Sep 17 00:00:00 2001 From: perigoso Date: Fri, 2 Jul 2021 16:12:02 +0100 Subject: [PATCH 02/13] build_system/dependencies: add sam3u cmsis dependency Signed-off-by: perigoso --- build_system/dependencies.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/build_system/dependencies.py b/build_system/dependencies.py index e23cf248..ab90052d 100644 --- a/build_system/dependencies.py +++ b/build_system/dependencies.py @@ -143,6 +143,7 @@ def __init__(self, location: BuildLocation, target: str) -> None: 'cmsis-dfp-stm32f1', 'cmsis-dfp-efm32gg12b', 'cmsis-dfp-sams70', + 'cmsis-dfp-sam3u', } @@ -192,6 +193,17 @@ def __init__(self, location: BuildLocation) -> None: } +class CMSISDeviceSAM3UDependency(Dependency, name='cmsis-dfp-sam3u'): + def __init__(self, location: BuildLocation) -> None: + super().__init__(location) + self.dependencies = { + 'cmsis-5', + } + self.external_include = { + self.base_path / 'include', + } + + class SensorBlobDependency(Dependency, name='sensor-blobs'): def __init__(self, location: BuildLocation) -> None: super().__init__(location) From 0f4bd994ede3b932ec88edfdbb1ab8bbeeeba661 Mon Sep 17 00:00:00 2001 From: perigoso Date: Fri, 2 Jul 2021 16:15:16 +0100 Subject: [PATCH 03/13] config/families: add sam3u family Signed-off-by: perigoso --- config/families/sam3u.toml | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 config/families/sam3u.toml diff --git a/config/families/sam3u.toml b/config/families/sam3u.toml new file mode 100644 index 00000000..9e76c4e3 --- /dev/null +++ b/config/families/sam3u.toml @@ -0,0 +1,37 @@ +toolchain = 'arm-none-eabi' +c_flags = [ + '-Os', + '-nostdlib', + '-nostartfiles', + '-ffunction-sections', + '-fdata-sections', + '-march=armv7-m', + '-mtune=cortex-m3', + '-mthumb', + '-mfloat-abi=soft', + '-ffreestanding', +] +ld_flags = [ + '-lm', + '-lc', + '-lgcc', + '-lnosys', + '-nostdlib', + '-nostartfiles', + '-fdata-sections', + '-ffunction-sections', + '--specs=nano.specs', + '--specs=nosys.specs', + '-Wl,--gc-sections', + '-march=armv7-m', + '-mtune=cortex-m3', + '-mthumb', +] +source = [ +# 'startup.c', +] + +[dependencies] +cmsis-5 = {} +cmsis-dfp-sam3u = {} +#tinyusb = { target = 'microchip/sam3u' } From 63df672e79a28fe6591645d431edf8f4ccbd624a Mon Sep 17 00:00:00 2001 From: perigoso Date: Fri, 2 Jul 2021 16:22:26 +0100 Subject: [PATCH 04/13] config/linker: add sam3u family linkers Signed-off-by: perigoso --- config/linker/sam3u/common.ld | 140 ++++++++++++++++++++++++++++++++++ config/linker/sam3u/sam3u1.ld | 7 ++ config/linker/sam3u/sam3u2.ld | 7 ++ config/linker/sam3u/sam3u4.ld | 7 ++ 4 files changed, 161 insertions(+) create mode 100644 config/linker/sam3u/common.ld create mode 100644 config/linker/sam3u/sam3u1.ld create mode 100644 config/linker/sam3u/sam3u2.ld create mode 100644 config/linker/sam3u/sam3u4.ld diff --git a/config/linker/sam3u/common.ld b/config/linker/sam3u/common.ld new file mode 100644 index 00000000..f4e569c3 --- /dev/null +++ b/config/linker/sam3u/common.ld @@ -0,0 +1,140 @@ +ENTRY(_reset_isr) + +_min_heap_size = 0x800; +_min_stack_size = 0x400; + +/* Initial stack pointer (must be 8 byte aligned) */ +_estack = (ORIGIN(ram) + LENGTH(ram)) & ~7; + +/* Internal device memory */ +PROVIDE(_system_unique_id = 0x1FFFF7E8); +PROVIDE(_system_memory = 0x1FFFF000); + +SECTIONS +{ + /* ISR Vectors */ + .isr_vector : + { + . = ALIGN(4); + _svect = .; + + KEEP(*(.isr_vector)) + + . = ALIGN(4); + _evect = .; + } > rom + + /* Flash Code */ + .text : + { + . = ALIGN(4); + _stext = .; + + *(.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 */ + + KEEP(*(.init)) + KEEP(*(.fini)) + + . = ALIGN(4); + _etext = .; + } > rom + + /* ARM */ + .ARM.extab : + { + *(.ARM.extab* .gnu.linkonce.armextab.*) + } > rom + .ARM : + { + __exidx_start = .; + + *(.ARM.exidx*) + + __exidx_end = .; + } > rom + .ARM.attributes : + { + *(.ARM.attributes) + } > rom + + /* C Array init/fini */ + .preinit_array : + { + PROVIDE_HIDDEN(__preinit_array_start = .); + KEEP(*(.preinit_array*)) + PROVIDE_HIDDEN(__preinit_array_end = .); + } > rom + .init_array : + { + PROVIDE_HIDDEN(__init_array_start = .); + KEEP(*(SORT(.init_array.*))) + KEEP(*(.init_array*)) + PROVIDE_HIDDEN(__init_array_end = .); + } > rom + .fini_array : + { + PROVIDE_HIDDEN(__fini_array_start = .); + KEEP(*(.fini_array*)) + KEEP(*(SORT(.fini_array.*))) + PROVIDE_HIDDEN(__fini_array_end = .); + } > rom + + /* RAM Data */ + _sidata = LOADADDR(.data); + + .data : + { + . = ALIGN(4); + _sdata = .; /* create a global symbol at data start */ + + *(.data) /* .data sections */ + *(.data*) /* .data* sections */ + + . = ALIGN(4); + _edata = .; /* define a global symbol at data end */ + } > ram AT > rom + + /* BSS */ + .bss : + { + . = ALIGN(4); + _sbss = .; /* define a global symbol at bss start */ + __bss_start__ = _sbss; + + *(.bss) + *(.bss*) + *(COMMON) + + . = ALIGN(4); + _ebss = .; /* define a global symbol at bss end */ + __bss_end__ = _ebss; + } > ram + + PROVIDE(end = _ebss); + PROVIDE(_end = _ebss); + + /* Ensure minimum stack & heap */ + .min_heap_stack : + { + . = ALIGN(4); + + . = . + _min_heap_size; + . = . + _min_stack_size; + + . = ALIGN(4); + } > ram + + /* Remove unused code from libs */ + /DISCARD/ : + { + libc.a(*) + libm.a(*) + libgcc.a(*) + libnosys.a(*) + } +} diff --git a/config/linker/sam3u/sam3u1.ld b/config/linker/sam3u/sam3u1.ld new file mode 100644 index 00000000..bb94a524 --- /dev/null +++ b/config/linker/sam3u/sam3u1.ld @@ -0,0 +1,7 @@ +MEMORY +{ + rom (rx) : ORIGIN = 0x00080000, LENGTH = 0x00010000 + ram (rw) : ORIGIN = 0x20000000, LENGTH = 0x00004000 +} + +INCLUDE sam3u/common.ld diff --git a/config/linker/sam3u/sam3u2.ld b/config/linker/sam3u/sam3u2.ld new file mode 100644 index 00000000..914b7f95 --- /dev/null +++ b/config/linker/sam3u/sam3u2.ld @@ -0,0 +1,7 @@ +MEMORY +{ + rom (rx) : ORIGIN = 0x00080000, LENGTH = 0x00020000 + ram (rw) : ORIGIN = 0x20000000, LENGTH = 0x00008000 +} + +INCLUDE sam3u/common.ld diff --git a/config/linker/sam3u/sam3u4.ld b/config/linker/sam3u/sam3u4.ld new file mode 100644 index 00000000..dde2e747 --- /dev/null +++ b/config/linker/sam3u/sam3u4.ld @@ -0,0 +1,7 @@ +MEMORY +{ + rom (rx) : ORIGIN = 0x00080000, LENGTH = 0x00040000 + ram (rw) : ORIGIN = 0x20000000, LENGTH = 0x0000C000 +} + +INCLUDE sam3u/common.ld From c85c959e86695d3992f69bcbd360c33373970307 Mon Sep 17 00:00:00 2001 From: perigoso Date: Fri, 2 Jul 2021 16:51:52 +0100 Subject: [PATCH 05/13] platform/sam3u: add startup Signed-off-by: perigoso --- config/families/sam3u.toml | 2 +- src/platform/sam3u/startup.c | 181 +++++++++++++++++++++++++++++++++++ 2 files changed, 182 insertions(+), 1 deletion(-) create mode 100644 src/platform/sam3u/startup.c diff --git a/config/families/sam3u.toml b/config/families/sam3u.toml index 9e76c4e3..f47e940b 100644 --- a/config/families/sam3u.toml +++ b/config/families/sam3u.toml @@ -28,7 +28,7 @@ ld_flags = [ '-mthumb', ] source = [ -# 'startup.c', + 'startup.c', ] [dependencies] diff --git a/src/platform/sam3u/startup.c b/src/platform/sam3u/startup.c new file mode 100644 index 00000000..6521247c --- /dev/null +++ b/src/platform/sam3u/startup.c @@ -0,0 +1,181 @@ +/* + * SPDX-License-Identifier: MIT + * SPDX-FileCopyrightText: 2021 Rafael Silva + */ + +#include + +#include "util/types.h" + +/* Stack pointer */ +extern void _estack(); /* Not a function, just to be compatible with the vector table array */ + +/* Variables */ +extern u32 _svect; /* ISR Vectors */ +extern u32 _evect; + +extern u32 _stext; /* Main program */ +extern u32 _etext; + +extern u32 _sidata; /* Data source */ +extern u32 _sdata; /* Data destination */ +extern u32 _edata; + +extern u32 _sbss; /* BSS destination */ +extern u32 _ebss; + +extern u32 _end; + +/* Functions */ +void _default_isr() +{ + while (1) continue; +} + +void __attribute__((weak)) __libc_init_array() +{ +} + +extern void __attribute__((noreturn)) main(); + +#define DEFAULT_ISR "_default_isr" + +void _reset_isr() +{ + u32 *src, *dst; + + src = &_sidata; + dst = &_sdata; + + while (dst < &_edata) /* Copy data */ + *(dst++) = *(src++); + + src = 0; + dst = &_sbss; + + while (dst < &_ebss) /* Zero BSS */ + *(dst++) = 0; + + __libc_init_array(); + + SCB->VTOR = (u32) &_svect; /* ISR Vectors offset */ + SCB->AIRCR = 0x05FA0000 | (4 << 8); /* Interrupt priority - 3 bits Group, 1 bit Sub-group */ + SCB->SHCSR = SCB_SHCSR_USGFAULTENA_Msk | SCB_SHCSR_BUSFAULTENA_Msk | + SCB_SHCSR_MEMFAULTENA_Msk; /* Enable separate fault handlers */ + + main(); + + __disable_irq(); + while (1) continue; +} + +/* Cortex-M Exception Handlers */ +void _nmi_isr() __attribute__((weak, alias(DEFAULT_ISR))); +void _hardfault_isr() __attribute__((weak, alias(DEFAULT_ISR))); +void _memmanage_isr() __attribute__((weak, alias(DEFAULT_ISR))); +void _busfault_isr() __attribute__((weak, alias(DEFAULT_ISR))); +void _usagefault_isr() __attribute__((weak, alias(DEFAULT_ISR))); +void _svc_isr() __attribute__((weak, alias(DEFAULT_ISR))); +void _debugmon_isr() __attribute__((weak, alias(DEFAULT_ISR))); +void _pendsv_isr() __attribute__((weak, alias(DEFAULT_ISR))); +void _systick_isr() __attribute__((weak, alias(DEFAULT_ISR))); +/* External interrupts */ +void _supc_isr() __attribute__((weak, alias(DEFAULT_ISR))); +void _rstc_isr() __attribute__((weak, alias(DEFAULT_ISR))); +void _rtc_isr() __attribute__((weak, alias(DEFAULT_ISR))); +void _rtt_isr() __attribute__((weak, alias(DEFAULT_ISR))); +void _wdt_isr() __attribute__((weak, alias(DEFAULT_ISR))); +void _pmc_isr() __attribute__((weak, alias(DEFAULT_ISR))); +void _efc0_isr() __attribute__((weak, alias(DEFAULT_ISR))); +#ifdef _SAM3U_EFC1_INSTANCE_ +void _efc1_isr() __attribute__((weak, alias(DEFAULT_ISR))); +#endif /* _SAM3U_EFC1_INSTANCE_ */ +void _uart_isr() __attribute__((weak, alias(DEFAULT_ISR))); +void _pioa_isr() __attribute__((weak, alias(DEFAULT_ISR))); +void _piob_isr() __attribute__((weak, alias(DEFAULT_ISR))); +#ifdef _SAM3U_PIOC_INSTANCE_ +void _pioc_isr() __attribute__((weak, alias(DEFAULT_ISR))); +#endif /* _SAM3U_PIOC_INSTANCE_ */ +void _usart0_isr() __attribute__((weak, alias(DEFAULT_ISR))); +void _usart1_isr() __attribute__((weak, alias(DEFAULT_ISR))); +void _usart2_isr() __attribute__((weak, alias(DEFAULT_ISR))); +#ifdef _SAM3U_USART3_INSTANCE_ +void _usart3_isr() __attribute__((weak, alias(DEFAULT_ISR))); +#endif /* _SAM3U_USART3_INSTANCE_ */ +void _hsmci_isr() __attribute__((weak, alias(DEFAULT_ISR))); +void _twi0_isr() __attribute__((weak, alias(DEFAULT_ISR))); +void _twi1_isr() __attribute__((weak, alias(DEFAULT_ISR))); +void _spi_isr() __attribute__((weak, alias(DEFAULT_ISR))); +void _ssc_isr() __attribute__((weak, alias(DEFAULT_ISR))); +void _tc0_isr() __attribute__((weak, alias(DEFAULT_ISR))); +void _tc1_isr() __attribute__((weak, alias(DEFAULT_ISR))); +void _tc2_isr() __attribute__((weak, alias(DEFAULT_ISR))); +void _pwm_isr() __attribute__((weak, alias(DEFAULT_ISR))); +void _adc12b_isr() __attribute__((weak, alias(DEFAULT_ISR))); +void _adc_isr() __attribute__((weak, alias(DEFAULT_ISR))); +void _dmac_isr() __attribute__((weak, alias(DEFAULT_ISR))); +void _udphs_isr() __attribute__((weak, alias(DEFAULT_ISR))); + +/* Vector table */ +__attribute__((section(".isr_vector"), used)) void (*const g_pfnVectors[])() = { + /* Cortex-M Exception Handlers */ + _estack, /* Stack pointer */ + _reset_isr, /* Reset */ + _nmi_isr, /* Non-maskable interrupt */ + _hardfault_isr, /* Hard fault */ + _memmanage_isr, /* */ + _busfault_isr, /* Bus Fault */ + _usagefault_isr, /* Usage fault */ + 0, /* Reserved */ + 0, /* Reserved */ + 0, /* Reserved */ + 0, /* Reserved */ + _svc_isr, /* SVCall */ + _debugmon_isr, /* Debug Monitor */ + 0, /* Reserved */ + _pendsv_isr, /* PendSV */ + _systick_isr, /* System tick */ + /* External interrupts */ + _supc_isr, /* 0 Supply Controller */ + _rstc_isr, /* 1 Reset Controller */ + _rtc_isr, /* 2 Real Time Clock */ + _rtt_isr, /* 3 Real Time Timer */ + _wdt_isr, /* 4 Watchdog Timer */ + _pmc_isr, /* 5 Power Management Controller */ + _efc0_isr, /* 6 Enhanced Embedded Flash Controller 0 */ +#ifdef _SAM3U_EFC1_INSTANCE_ + _efc1_isr, /* 7 Enhanced Embedded Flash Controller 1 */ +#else + 0, /* 7 Reserved */ +#endif /* _SAM3U_EFC1_INSTANCE_ */ + _uart_isr, /* 8 Universal Asynchronous Receiver Transmitter */ + 0, /* 9 Reserved */ + _pioa_isr, /* 10 Parallel I/O Controller A, */ + _piob_isr, /* 11 Parallel I/O Controller B */ +#ifdef _SAM3U_PIOC_INSTANCE_ + _pioc_isr, /* 12 Parallel I/O Controller C */ +#else + 0, /* 12 Reserved */ +#endif /* _SAM3U_PIOC_INSTANCE_ */ + _usart0_isr, /* 13 USART 0 */ + _usart1_isr, /* 14 USART 1 */ + _usart2_isr, /* 15 USART 2 */ +#ifdef _SAM3U_USART3_INSTANCE_ + _usart3_isr, /* 16 USART 3 */ +#else + 0, /* 16 Reserved */ +#endif /* _SAM3U_USART3_INSTANCE_ */ + _hsmci_isr, /* 17 High Speed Multimedia Card Interface */ + _twi0_isr, /* 18 Two-Wire Interface 0 */ + _twi1_isr, /* 19 Two-Wire Interface 1 */ + _spi_isr, /* 20 Serial Peripheral Interface */ + _ssc_isr, /* 21 Synchronous Serial Controller */ + _tc0_isr, /* 22 Timer Counter 0 */ + _tc1_isr, /* 23 Timer Counter 1 */ + _tc2_isr, /* 24 Timer Counter 2 */ + _pwm_isr, /* 25 Pulse Width Modulation Controller */ + _adc12b_isr, /* 26 12-bit ADC Controller */ + _adc_isr, /* 27 10-bit ADC Controller */ + _dmac_isr, /* 28 DMA Controller */ + _udphs_isr, /* 29 USB Device High Speed */ +}; From e00ce788e561373791f7bb276efc803f994ba54b Mon Sep 17 00:00:00 2001 From: perigoso Date: Fri, 2 Jul 2021 18:06:33 +0100 Subject: [PATCH 06/13] platform: partial vector table documentation Signed-off-by: perigoso --- src/platform/efm32gg/startup.c | 153 ++++++++++++++--------------- src/platform/stm32f1/startup.c | 171 +++++++++++++++++---------------- 2 files changed, 164 insertions(+), 160 deletions(-) diff --git a/src/platform/efm32gg/startup.c b/src/platform/efm32gg/startup.c index baed2030..7ffe6234 100644 --- a/src/platform/efm32gg/startup.c +++ b/src/platform/efm32gg/startup.c @@ -144,83 +144,84 @@ void _trng0_isr() __attribute__((weak, alias(DEFAULT_ISR))); void _qspi0_isr() __attribute__((weak, alias(DEFAULT_ISR))); void _pdm_isr() __attribute__((weak, alias(DEFAULT_ISR))); +/* Vector table */ __attribute__((section(".isr_vector"), used)) void (*const g_pfnVectors[])() = { /* Cortex-M Exception Handlers */ - _estack, - _reset_isr, - _nmi_isr, - _hardfault_isr, - _memmanage_isr, - _busfault_isr, - _usagefault_isr, - 0, - 0, - 0, - 0, - _svc_isr, - _debugmon_isr, - 0, - _pendsv_isr, - _systick_isr, + _estack, /* Stack pointer */ + _reset_isr, /* Reset */ + _nmi_isr, /* Non-maskable interrupt */ + _hardfault_isr, /* Hard fault */ + _memmanage_isr, /* */ + _busfault_isr, /* Bus Fault */ + _usagefault_isr, /* Usage fault */ + 0, /* Reserved */ + 0, /* Reserved */ + 0, /* Reserved */ + 0, /* Reserved */ + _svc_isr, /* SVCall */ + _debugmon_isr, /* Debug Monitor */ + 0, /* Reserved */ + _pendsv_isr, /* PendSV */ + _systick_isr, /* System tick */ /* External interrupts */ - _emu_isr, - _wdog0_isr, - _ldma_isr, - _gpio_even_isr, - _smu_isr, - _timer0_isr, - _usart0_rx_isr, - _usart0_tx_isr, - _acmp0_1_isr, - _adc0_isr, - _idac0_isr, - _i2c0_isr, - _i2c1_isr, - _gpio_odd_isr, - _timer1_isr, - _timer2_isr, - _timer3_isr, - _usart1_rx_isr, - _usart1_tx_isr, - _usart2_rx_isr, - _usart2_tx_isr, - _uart0_rx_isr, - _uart0_tx_isr, - _uart1_rx_isr, - _uart1_tx_isr, - _leuart0_isr, - _leuart1_isr, - _letimer0_isr, - _pcnt0_isr, - _pcnt1_isr, - _pcnt2_isr, - _rtcc_isr, - _cmu_isr, - _msc_isr, - _crypto0_isr, - _cryotimer_isr, - _fpueh_isr, - _usart3_rx_isr, - _usart3_tx_isr, - _usart4_rx_isr, - _usart4_tx_isr, - _wtimer0_isr, - _wtimer1_isr, - _vdac0_isr, - _csen_isr, - _lesense_isr, - _ebi_isr, - _acmp2_3_isr, - _adc1_isr, - _lcd_isr, - _sdio_isr, - _can0_isr, - _can1_isr, - _usb_isr, - _rtc_isr, - _wdog1_isr, - _letimer1_isr, - _trng0_isr, - _qspi0_isr, - _pdm_isr, + _emu_isr, /* 0 Energy management unit */ + _wdog0_isr, /* 1 Watch dog timer 0 */ + _ldma_isr, /* 2 Linked DMA */ + _gpio_even_isr, /* 3 Even numbered GPIO interrupt */ + _smu_isr, /* 4 */ + _timer0_isr, /* 5 */ + _usart0_rx_isr, /* 6 */ + _usart0_tx_isr, /* 7 */ + _acmp0_1_isr, /* 8 */ + _adc0_isr, /* 9 */ + _idac0_isr, /* 10 */ + _i2c0_isr, /* 11 */ + _i2c1_isr, /* 12 */ + _gpio_odd_isr, /* 13 Odd numbered GPIO interrupt */ + _timer1_isr, /* 14 Timer counter 1 */ + _timer2_isr, /* 15 Timer counter 2 */ + _timer3_isr, /* 16 Timer counter 3 */ + _usart1_rx_isr, /* 17 */ + _usart1_tx_isr, /* 18 */ + _usart2_rx_isr, /* 19 */ + _usart2_tx_isr, /* 20 */ + _uart0_rx_isr, /* 21 */ + _uart0_tx_isr, /* 22 */ + _uart1_rx_isr, /* 23 */ + _uart1_tx_isr, /* 24 */ + _leuart0_isr, /* 25 */ + _leuart1_isr, /* 26 */ + _letimer0_isr, /* 27 */ + _pcnt0_isr, /* 28 */ + _pcnt1_isr, /* 29 */ + _pcnt2_isr, /* 30 */ + _rtcc_isr, /* 31 */ + _cmu_isr, /* 32 */ + _msc_isr, /* 33 */ + _crypto0_isr, /* 34 */ + _cryotimer_isr, /* 35 */ + _fpueh_isr, /* 36 */ + _usart3_rx_isr, /* 37 */ + _usart3_tx_isr, /* 38 */ + _usart4_rx_isr, /* 39 */ + _usart4_tx_isr, /* 40 */ + _wtimer0_isr, /* 41 */ + _wtimer1_isr, /* 42 */ + _vdac0_isr, /* 43 Digital to analog coverter */ + _csen_isr, /* 44 */ + _lesense_isr, /* 45 Low energy sensor interface */ + _ebi_isr, /* 46 External bus interface */ + _acmp2_3_isr, /* 47 Analog comparator 2 & 3 */ + _adc1_isr, /* 48 ADC channel 1 */ + _lcd_isr, /* 49 LCd Driver */ + _sdio_isr, /* 50 */ + _can0_isr, /* 51 */ + _can1_isr, /* 52 */ + _usb_isr, /* 53 USB controller */ + _rtc_isr, /* 54 */ + _wdog1_isr, /* 55 Watchdog timer 1 */ + _letimer1_isr, /* 56 Low energy timer 1 */ + _trng0_isr, /* 57 True random number generator */ + _qspi0_isr, /* 58 Quad SPI flash controller */ + _pdm_isr, /* 59 PDM interface */ }; diff --git a/src/platform/stm32f1/startup.c b/src/platform/stm32f1/startup.c index c5b125f9..36a64ecc 100644 --- a/src/platform/stm32f1/startup.c +++ b/src/platform/stm32f1/startup.c @@ -140,89 +140,92 @@ void _dma2_channel2_isr() __attribute__((weak, alias(DEFAULT_ISR))); void _dma2_channel3_isr() __attribute__((weak, alias(DEFAULT_ISR))); void _dma2_channel4_5_isr() __attribute__((weak, alias(DEFAULT_ISR))); +/* Vector table */ __attribute__((section(".isr_vector"), used)) void (*const g_pfnVectors[])() = { - _estack, - _reset_isr, - _nmi_isr, - _hardfault_isr, - _memmanage_isr, - _busfault_isr, - _usagefault_isr, - 0, - 0, - 0, - 0, - _svc_isr, - _debugmon_isr, - 0, - _pendsv_isr, - _systick_isr, - _wwdg_isr, - _pvd_isr, - _tamper_stamp_isr, - _rtc_isr, - _flash_isr, - _rcc_isr, - _exti0_isr, - _exti1_isr, - _exti2_isr, - _exti3_isr, - _exti4_isr, - _dma1_channel1_isr, - _dma1_channel2_isr, - _dma1_channel3_isr, - _dma1_channel4_isr, - _dma1_channel5_isr, - _dma1_channel6_isr, - _dma1_channel7_isr, - _adc1_2_isr, - _usb_hp_can_tx_isr, - _usb_lp_can_rx0_isr, - _can_rx1_isr, - _can_sce_isr, - _exti9_5_isr, - _tim1_brk_isr, - _tim1_up_isr, - _tim1_trg_com_isr, - _tim1_cc_isr, - _tim2_isr, - _tim3_isr, - _tim4_isr, - _i2c1_ev_isr, - _i2c1_er_isr, - _i2c2_ev_isr, - _i2c2_er_isr, - _spi1_isr, - _spi2_isr, - _usart1_isr, - _usart2_isr, - _usart3_isr, - _exti15_10_isr, - _rtc_alarm_isr, - _usb_wakeup_isr, - _tim8_brk_isr, - _tim8_up_isr, - _tim8_trg_com_isr, - _tim8_cc_isr, - _adc3_isr, - _fsmc_isr, - _sdio_isr, - _tim5_isr, - _spi3_isr, - _uart4_isr, - _uart5_isr, - _tim6_isr, - _tim7_isr, - _dma2_channel1_isr, - _dma2_channel2_isr, - _dma2_channel3_isr, - _dma2_channel4_5_isr, - 0, - 0, - 0, - 0, - 0, - 0, - 0, - 0, + /* Cortex-M Exception Handlers */ + _estack, /* Stack pointer */ + _reset_isr, /* Reset */ + _nmi_isr, /* Non-maskable interrupt */ + _hardfault_isr, /* Hard fault */ + _memmanage_isr, /* */ + _busfault_isr, /* Bus Fault */ + _usagefault_isr, /* Usage fault */ + 0, /* Reserved */ + 0, /* Reserved */ + 0, /* Reserved */ + 0, /* Reserved */ + _svc_isr, /* SVCall */ + _debugmon_isr, /* Debug Monitor */ + 0, /* Reserved */ + _pendsv_isr, /* PendSV */ + _systick_isr, /* System tick */ + /* External interrupts */ + _wwdg_isr, /* 0 */ + _pvd_isr, /* 1 */ + _tamper_stamp_isr, /* 2 */ + _rtc_isr, /* 3 Real time clock */ + _flash_isr, /* 4 Flash controller */ + _rcc_isr, /* 5 */ + _exti0_isr, /* 6 */ + _exti1_isr, /* 7 */ + _exti2_isr, /* 8 */ + _exti3_isr, /* 9 */ + _exti4_isr, /* 10 */ + _dma1_channel1_isr, /* 11 */ + _dma1_channel2_isr, /* 12 */ + _dma1_channel3_isr, /* 13 */ + _dma1_channel4_isr, /* 14 */ + _dma1_channel5_isr, /* 15 */ + _dma1_channel6_isr, /* 16 */ + _dma1_channel7_isr, /* 17 */ + _adc1_2_isr, /* 18 ADC Channel 1 & 2 */ + _usb_hp_can_tx_isr, /* 19 USB high priority / CAN tx */ + _usb_lp_can_rx0_isr, /* 20 USB low priority / CAN rx0 */ + _can_rx1_isr, /* 21 CAN rx1 */ + _can_sce_isr, /* 22 */ + _exti9_5_isr, /* 23 */ + _tim1_brk_isr, /* 24 */ + _tim1_up_isr, /* 25 */ + _tim1_trg_com_isr, /* 26 */ + _tim1_cc_isr, /* 27 */ + _tim2_isr, /* 28 */ + _tim3_isr, /* 29 */ + _tim4_isr, /* 30 */ + _i2c1_ev_isr, /* 31 */ + _i2c1_er_isr, /* 32 */ + _i2c2_ev_isr, /* 33 */ + _i2c2_er_isr, /* 34 */ + _spi1_isr, /* 35 */ + _spi2_isr, /* 36 */ + _usart1_isr, /* 37 */ + _usart2_isr, /* 38 */ + _usart3_isr, /* 39 */ + _exti15_10_isr, /* 40 */ + _rtc_alarm_isr, /* 41 */ + _usb_wakeup_isr, /* 42 */ + _tim8_brk_isr, /* 43 */ + _tim8_up_isr, /* 44 */ + _tim8_trg_com_isr, /* 45 */ + _tim8_cc_isr, /* 46 */ + _adc3_isr, /* 47 */ + _fsmc_isr, /* 48 */ + _sdio_isr, /* 49 */ + _tim5_isr, /* 50 */ + _spi3_isr, /* 51 */ + _uart4_isr, /* 52 */ + _uart5_isr, /* 53 */ + _tim6_isr, /* 54 */ + _tim7_isr, /* 55 */ + _dma2_channel1_isr, /* 56 */ + _dma2_channel2_isr, /* 57 */ + _dma2_channel3_isr, /* 58 */ + _dma2_channel4_5_isr, /* 59 */ + 0, /* Reserved */ + 0, /* Reserved */ + 0, /* Reserved */ + 0, /* Reserved */ + 0, /* Reserved */ + 0, /* Reserved */ + 0, /* Reserved */ + 0, /* Reserved */ }; From e39a601818e15b3aab29efd2ec13166a7c86423d Mon Sep 17 00:00:00 2001 From: Rafael Silva Date: Sat, 25 Jun 2022 20:59:53 +0100 Subject: [PATCH 07/13] platform/sam3u: initial wdt Signed-off-by: Rafael Silva --- config/families/sam3u.toml | 1 + src/platform/sam3u/wdt.c | 13 +++++++++++++ src/platform/sam3u/wdt.h | 8 ++++++++ 3 files changed, 22 insertions(+) create mode 100644 src/platform/sam3u/wdt.c create mode 100644 src/platform/sam3u/wdt.h diff --git a/config/families/sam3u.toml b/config/families/sam3u.toml index f47e940b..13eb9d64 100644 --- a/config/families/sam3u.toml +++ b/config/families/sam3u.toml @@ -29,6 +29,7 @@ ld_flags = [ ] source = [ 'startup.c', + 'wdt.c', ] [dependencies] diff --git a/src/platform/sam3u/wdt.c b/src/platform/sam3u/wdt.c new file mode 100644 index 00000000..24561429 --- /dev/null +++ b/src/platform/sam3u/wdt.c @@ -0,0 +1,13 @@ +/* + * SPDX-License-Identifier: MIT + * SPDX-FileCopyrightText: 2021 Rafael Silva + */ + +#include + +#include "platform/sam3u/wdt.h" + +void wdt_disable() +{ + WDT->WDT_MR = WDT_MR_WDDIS; +} diff --git a/src/platform/sam3u/wdt.h b/src/platform/sam3u/wdt.h new file mode 100644 index 00000000..a1d40b0c --- /dev/null +++ b/src/platform/sam3u/wdt.h @@ -0,0 +1,8 @@ +/* + * SPDX-License-Identifier: MIT + * SPDX-FileCopyrightText: 2021 Rafael Silva + */ + +#pragma once + +void wdt_disable(); From 1a74c1c6a937071df69f22d21812e699efde60ac Mon Sep 17 00:00:00 2001 From: Rafael Silva Date: Sat, 25 Jun 2022 21:00:25 +0100 Subject: [PATCH 08/13] platform/sam3u: initial eefc Signed-off-by: Rafael Silva --- config/families/sam3u.toml | 1 + src/platform/sam3u/eefc.c | 31 +++++++++++++++++++++++++++++++ src/platform/sam3u/eefc.h | 12 ++++++++++++ 3 files changed, 44 insertions(+) create mode 100644 src/platform/sam3u/eefc.c create mode 100644 src/platform/sam3u/eefc.h diff --git a/config/families/sam3u.toml b/config/families/sam3u.toml index 13eb9d64..689ecf85 100644 --- a/config/families/sam3u.toml +++ b/config/families/sam3u.toml @@ -29,6 +29,7 @@ ld_flags = [ ] source = [ 'startup.c', + 'eefc.c', 'wdt.c', ] diff --git a/src/platform/sam3u/eefc.c b/src/platform/sam3u/eefc.c new file mode 100644 index 00000000..e02cfe0b --- /dev/null +++ b/src/platform/sam3u/eefc.c @@ -0,0 +1,31 @@ +/* + * SPDX-License-Identifier: MIT + * SPDX-FileCopyrightText: 2021 Rafael Silva + */ + +#include + +#include "platform/sam3u/eefc.h" + +void eefc_config_waitstates(const u32 frequency) +{ + if (frequency <= 27000000UL) + EFC0->EEFC_FMR = (EFC0->EEFC_FMR & ~EEFC_FMR_FWS_Msk) | (0 << EEFC_FMR_FWS_Pos); + else if (frequency <= 47000000UL) + EFC0->EEFC_FMR = (EFC0->EEFC_FMR & ~EEFC_FMR_FWS_Msk) | (1 << EEFC_FMR_FWS_Pos); + else if (frequency <= 84000000UL) + EFC0->EEFC_FMR = (EFC0->EEFC_FMR & ~EEFC_FMR_FWS_Msk) | (2 << EEFC_FMR_FWS_Pos); + else + EFC0->EEFC_FMR = (EFC0->EEFC_FMR & ~EEFC_FMR_FWS_Msk) | (3 << EEFC_FMR_FWS_Pos); + +#ifdef _SAM3U_EFC1_INSTANCE_ + if (frequency <= 27000000UL) + EFC1->EEFC_FMR = (EFC0->EEFC_FMR & ~EEFC_FMR_FWS_Msk) | (0 << EEFC_FMR_FWS_Pos); + else if (frequency <= 47000000UL) + EFC1->EEFC_FMR = (EFC0->EEFC_FMR & ~EEFC_FMR_FWS_Msk) | (1 << EEFC_FMR_FWS_Pos); + else if (frequency <= 84000000UL) + EFC1->EEFC_FMR = (EFC0->EEFC_FMR & ~EEFC_FMR_FWS_Msk) | (2 << EEFC_FMR_FWS_Pos); + else + EFC1->EEFC_FMR = (EFC0->EEFC_FMR & ~EEFC_FMR_FWS_Msk) | (3 << EEFC_FMR_FWS_Pos); +#endif /* _SAM3U_EFC1_INSTANCE_ */ +} diff --git a/src/platform/sam3u/eefc.h b/src/platform/sam3u/eefc.h new file mode 100644 index 00000000..e69c13c5 --- /dev/null +++ b/src/platform/sam3u/eefc.h @@ -0,0 +1,12 @@ +/* + * SPDX-License-Identifier: MIT + * SPDX-FileCopyrightText: 2021 Rafael Silva + */ + +#pragma once + +#include + +#include "util/types.h" + +void eefc_config_waitstates(const u32 frequency); From acf1cb195532e7c099c2cdd5adb25afe939b3105 Mon Sep 17 00:00:00 2001 From: Rafael Silva Date: Sat, 25 Jun 2022 21:00:44 +0100 Subject: [PATCH 09/13] platform/sam3u: initial pmc Signed-off-by: Rafael Silva --- config/families/sam3u.toml | 1 + src/platform/sam3u/pmc.c | 254 +++++++++++++++++++++++++++++++++++++ src/platform/sam3u/pmc.h | 73 +++++++++++ 3 files changed, 328 insertions(+) create mode 100644 src/platform/sam3u/pmc.c create mode 100644 src/platform/sam3u/pmc.h diff --git a/config/families/sam3u.toml b/config/families/sam3u.toml index 689ecf85..e35a935c 100644 --- a/config/families/sam3u.toml +++ b/config/families/sam3u.toml @@ -31,6 +31,7 @@ source = [ 'startup.c', 'eefc.c', 'wdt.c', + 'pmc.c', ] [dependencies] diff --git a/src/platform/sam3u/pmc.c b/src/platform/sam3u/pmc.c new file mode 100644 index 00000000..f5671642 --- /dev/null +++ b/src/platform/sam3u/pmc.c @@ -0,0 +1,254 @@ +/* + * SPDX-License-Identifier: MIT + * SPDX-FileCopyrightText: 2021 Rafael Silva + */ + +#include + +#include "util/data.h" + +#include "platform/sam3u/eefc.h" +#include "platform/sam3u/pmc.h" + +static struct pmc_clock_tree_t pmc_clock_tree; + +void pmc_init(u32 hfxo_freq, u32 lfxo_freq) +{ + if (hfxo_freq != 12000000UL) // this is a preset for 12MHz Crystal + return; + + pmc_clock_tree.hfxo_freq = hfxo_freq; + pmc_clock_tree.lfxo_freq = lfxo_freq; + + /* Configure flash waitstates */ + eefc_config_waitstates(96000000); + + /* 12MHz external xtal, maximum possible startup time */ + pmc_hfxo_enable(false, 0xFF); + + /* Select as main oscillator */ + pmc_mainck_source_set(PMC_MAINCK_HFXO); + pmc_mck_source_set(PMC_MCK_MAINCK, 1); + + /* Multiply by 8 for 96MHz */ + pmc_pllack_enable(8, 1); + pmc_upllck_enable(); + + /* Select as MCK source */ + pmc_mck_source_set(PMC_MCK_PLLACK, 1); +} + +void pmc_update_clock_tree() +{ + pmc_clock_tree.lfrco_freq = CHIP_FREQ_SLCK_RC; + + switch (SUPC->SUPC_SR & SUPC_SR_OSCSEL) { + case SUPC_SR_OSCSEL_RC: + pmc_clock_tree.slck_freq = pmc_clock_tree.lfrco_freq; + break; + case SUPC_SR_OSCSEL_CRYST: + pmc_clock_tree.slck_freq = pmc_clock_tree.lfxo_freq; + break; + } + + switch (PMC->CKGR_MOR & CKGR_MOR_MOSCRCF_Msk) { + case CKGR_MOR_MOSCRCF_4_MHz: + pmc_clock_tree.hfrco_freq = CHIP_FREQ_MAINCK_RC_4MHZ; + break; + case CKGR_MOR_MOSCRCF_8_MHz: + pmc_clock_tree.hfrco_freq = CHIP_FREQ_MAINCK_RC_8MHZ; + break; + case CKGR_MOR_MOSCRCF_12_MHz: + pmc_clock_tree.hfrco_freq = CHIP_FREQ_MAINCK_RC_12MHZ; + break; + } + + switch (PMC->CKGR_MOR & CKGR_MOR_MOSCSEL) { + case 0: + pmc_clock_tree.mainck_freq = pmc_clock_tree.hfrco_freq; + break; + case CKGR_MOR_MOSCSEL: + pmc_clock_tree.mainck_freq = pmc_clock_tree.hfxo_freq; + break; + } + + float plla_div = (PMC->CKGR_PLLAR & CKGR_PLLAR_DIVA_Msk) >> CKGR_PLLAR_DIVA_Pos; + float plla_mul = (PMC->CKGR_PLLAR & CKGR_PLLAR_MULA_Msk) >> CKGR_PLLAR_MULA_Pos; + + if (plla_div == 0 || plla_mul == 0) + pmc_clock_tree.pllack_freq = 0; + else + pmc_clock_tree.pllack_freq = (uint32_t) (((float) pmc_clock_tree.mainck_freq / plla_div) * (plla_mul + 1.f)); + + if (!(PMC->CKGR_UCKR & CKGR_UCKR_UPLLEN)) + pmc_clock_tree.upllck_freq = 0; + else + pmc_clock_tree.upllck_freq = CHIP_FREQ_UTMIPLL; + + switch (PMC->PMC_MCKR & PMC_MCKR_CSS_Msk) { + case PMC_MCKR_CSS_SLOW_CLK: + pmc_clock_tree.mck_freq = pmc_clock_tree.slck_freq; + break; + case PMC_MCKR_CSS_MAIN_CLK: + pmc_clock_tree.mck_freq = pmc_clock_tree.mainck_freq; + break; + case PMC_MCKR_CSS_UPLL_CLK: + pmc_clock_tree.mck_freq = pmc_clock_tree.upllck_freq / 2; + break; + case PMC_MCKR_CSS_PLLA_CLK: + pmc_clock_tree.mck_freq = pmc_clock_tree.pllack_freq; + break; + } + + switch (PMC->PMC_MCKR & PMC_MCKR_PRES_Msk) { + case PMC_MCKR_PRES_CLK_1: + pmc_clock_tree.mck_freq >>= 0; + break; + case PMC_MCKR_PRES_CLK_2: + pmc_clock_tree.mck_freq >>= 1; + break; + case PMC_MCKR_PRES_CLK_4: + pmc_clock_tree.mck_freq >>= 2; + break; + case PMC_MCKR_PRES_CLK_8: + pmc_clock_tree.mck_freq >>= 3; + break; + case PMC_MCKR_PRES_CLK_16: + pmc_clock_tree.mck_freq >>= 4; + break; + case PMC_MCKR_PRES_CLK_32: + pmc_clock_tree.mck_freq >>= 5; + break; + case PMC_MCKR_PRES_CLK_64: + pmc_clock_tree.mck_freq >>= 6; + break; + case PMC_MCKR_PRES_CLK_3: + pmc_clock_tree.mck_freq /= 3; + break; + } + + pmc_clock_tree.fclk_freq = pmc_clock_tree.mck_freq; +} + +const struct pmc_clock_tree_t *pmc_get_clock_tree() +{ + return (const struct pmc_clock_tree_t *) &pmc_clock_tree; +} + +void pmc_hfxo_enable(bool bypass, u8 startup_time) +{ + if (bypass) { + PMC->CKGR_MOR = (PMC->CKGR_MOR & ~(CKGR_MOR_MOSCXTEN)) | CKGR_MOR_KEY_PASSWD | CKGR_MOR_MOSCXTBY; + } else { + PMC->CKGR_MOR = (PMC->CKGR_MOR & ~(CKGR_MOR_MOSCXTST_Msk | CKGR_MOR_MOSCXTBY)) | CKGR_MOR_KEY_PASSWD | + CKGR_MOR_MOSCXTEN | CKGR_MOR_MOSCXTST(startup_time); + } + + while (!(PMC->PMC_SR & PMC_SR_MOSCXTS)) continue; +} + +void pmc_hfxo_disable() +{ + PMC->CKGR_MOR = (PMC->CKGR_MOR & ~(CKGR_MOR_MOSCXTBY | CKGR_MOR_MOSCXTEN)) | CKGR_MOR_KEY_PASSWD; +} + +void pmc_hfrco_enable(enum pmc_hfrco_freq_t freq) +{ + PMC->CKGR_MOR |= (CKGR_MOR_KEY_PASSWD | CKGR_MOR_MOSCRCEN); + + while (!(PMC->PMC_SR & PMC_SR_MOSCRCS)) continue; + + PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCRCF_Msk) | CKGR_MOR_KEY_PASSWD | CKGR_MOR_MOSCRCF(freq); + + while (!(PMC->PMC_SR & PMC_SR_MOSCRCS)) continue; +} + +void pmc_hfrco_disable() +{ + PMC->CKGR_MOR = (PMC->CKGR_MOR & ~(CKGR_MOR_MOSCRCEN | CKGR_MOR_MOSCRCF_Msk)) | CKGR_MOR_KEY_PASSWD; +} + +void pmc_pllack_enable(u8 mul, u8 div) +{ + pmc_pllack_disable(); + + if (!mul || !div) + mul = div = 1; + + PMC->CKGR_PLLAR = CKGR_PLLAR_ONE | CKGR_PLLAR_MULA(mul - 1) | CKGR_PLLAR_DIVA(div) | CKGR_PLLAR_PLLACOUNT(63); + + while (!(PMC->PMC_SR & PMC_SR_LOCKA)) continue; +} + +void pmc_pllack_disable() +{ + PMC->CKGR_PLLAR = CKGR_PLLAR_ONE | CKGR_PLLAR_MULA(0) | CKGR_PLLAR_DIVA(0); +} + +void pmc_upllck_enable() +{ + pmc_upllck_disable(); + + PMC->CKGR_UCKR = CKGR_UCKR_UPLLCOUNT(255) | CKGR_UCKR_UPLLEN; + + while (!(PMC->PMC_SR & PMC_SR_LOCKU)) continue; +} + +void pmc_upllck_disable() +{ + PMC->CKGR_UCKR &= ~CKGR_UCKR_UPLLEN; +} + +void pmc_slck_source_set(enum pmc_slck_src_t src) +{ + if (src == PMC_SCLK_LFXO_BYPASS) + SUPC->SUPC_MR |= (SUPC_MR_KEY_PASSWD | SUPC_MR_OSCBYPASS); + else + SUPC->SUPC_MR = (SUPC->SUPC_MR & ~SUPC_MR_OSCBYPASS) | SUPC_MR_KEY_PASSWD; + + if (src == PMC_SCLK_LFRCO) + SUPC->SUPC_CR = (SUPC->SUPC_CR & ~SUPC_CR_XTALSEL) | SUPC_CR_KEY_PASSWD; + else + SUPC->SUPC_CR |= (SUPC_CR_KEY_PASSWD | SUPC_CR_XTALSEL); +} + +void pmc_mainck_source_set(enum pmc_mainck_src_t src) +{ + u32 ckgr_mor_val = 0; + + if (src == PMC_MAINCK_HFXO) + ckgr_mor_val = CKGR_MOR_MOSCSEL; + + PMC->CKGR_MOR = (PMC->CKGR_MOR & ~CKGR_MOR_MOSCSEL) | CKGR_MOR_KEY_PASSWD | ckgr_mor_val; +} + +void pmc_mck_source_set(enum pmc_mck_src_t src, u8 prescaler) +{ + if (!prescaler) + prescaler = 1; + + u32 pmc_mckr_val = 0; + if (src == PMC_MCK_UPLLCK2) + pmc_mckr_val = PMC_MCKR_UPLLDIV2; + + PMC->PMC_MCKR = (PMC->PMC_MCKR & ~(PMC_MCKR_PRES_Msk | PMC_MCKR_CSS_Msk)) | PMC_MCKR_CSS(src) | + PMC_MCKR_PRES(prescaler - 1) | pmc_mckr_val; + + while (!(PMC->PMC_SR & PMC_SR_MCKRDY)) continue; +} + +void pmc_peripheral_clock_enable(u8 pid) +{ + if (pid > 31) + return; + + PMC->PMC_PCER0 = 1 << pid; +} + +void pmc_peripheral_clock_disable(u8 pid) +{ + if (pid > 31) + return; + + PMC->PMC_PCDR0 = 1 << pid; +} diff --git a/src/platform/sam3u/pmc.h b/src/platform/sam3u/pmc.h new file mode 100644 index 00000000..d7b7e24b --- /dev/null +++ b/src/platform/sam3u/pmc.h @@ -0,0 +1,73 @@ +/* + * SPDX-License-Identifier: MIT + * SPDX-FileCopyrightText: 2021 Rafael Silva + */ + +#pragma once + +#include "sam.h" + +#include + +#include "util/types.h" + +struct pmc_clock_tree_t { + u32 hfxo_freq; + u32 hfrco_freq; + u32 lfxo_freq; + u32 lfrco_freq; + u32 slck_freq; + u32 mainck_freq; + u32 pllack_freq; + u32 upllck_freq; + u32 mck_freq; + u32 fclk_freq; +}; + +enum pmc_hfrco_freq_t { + PMC_HFRCO_4MHZ = 0x0u, + PMC_HFRCO_8MHZ = 0x1u, + PMC_HFRCO_12MHZ = 0x2u, +}; + +enum pmc_slck_src_t { + PMC_SCLK_LFRCO = 0, + PMC_SCLK_LFXO = 1, + PMC_SCLK_LFXO_BYPASS = 2, +}; + +enum pmc_mainck_src_t { + PMC_MAINCK_HFRCO = 0, + PMC_MAINCK_HFXO = 1, +}; + +enum pmc_mck_src_t { + PMC_MCK_SLCK = 0x0u, + PMC_MCK_MAINCK = 0x1u, + PMC_MCK_PLLACK = 0x2u, + PMC_MCK_UPLLCK2 = 0x3u, +}; + +void pmc_init(u32 hfxo_freq, u32 lfxo_freq); + +void pmc_update_clock_tree(); +const struct pmc_clock_tree_t *pmc_get_clock_tree(); + +void pmc_hfxo_enable(bool bypass, u8 startup_time); +void pmc_hfxo_disable(); + +void pmc_hfrco_enable(enum pmc_hfrco_freq_t freq); +void pmc_hfrco_disable(); + +void pmc_pllack_enable(u8 mul, u8 div); +void pmc_pllack_disable(); + +void pmc_upllck_enable(); +void pmc_upllck_disable(); + +void pmc_slck_source_set(enum pmc_slck_src_t src); +void pmc_mainck_source_set(enum pmc_mainck_src_t src); +void pmc_mck_source_set(enum pmc_mck_src_t src, u8 prescaler); + +void pmc_peripheral_clock_enable(u8 pid); +void pmc_peripheral_clock_disable(u8 pid); From 0fca29721159438455edc0fbdef4cfbb7dd35357 Mon Sep 17 00:00:00 2001 From: Rafael Silva Date: Sat, 2 Jul 2022 04:27:59 +0100 Subject: [PATCH 10/13] platform/sam3u: add exception handlers Signed-off-by: Rafael Silva --- config/families/sam3u.toml | 1 + src/platform/sam3u/exceptions.c | 80 +++++++++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 src/platform/sam3u/exceptions.c diff --git a/config/families/sam3u.toml b/config/families/sam3u.toml index e35a935c..66116596 100644 --- a/config/families/sam3u.toml +++ b/config/families/sam3u.toml @@ -32,6 +32,7 @@ source = [ 'eefc.c', 'wdt.c', 'pmc.c', + 'exceptions.c', ] [dependencies] diff --git a/src/platform/sam3u/exceptions.c b/src/platform/sam3u/exceptions.c new file mode 100644 index 00000000..a95639e2 --- /dev/null +++ b/src/platform/sam3u/exceptions.c @@ -0,0 +1,80 @@ +/* + * SPDX-License-Identifier: MIT + * SPDX-FileCopyrightText: 2021 Rafael Silva + */ + +#include + +#include "util/types.h" + +void __attribute__((naked, aligned(4))) _hardfault_isr() +{ + __asm__ volatile(" tst lr, #4 \n" + " ite eq \n" + " mrseq r0, msp \n" + " mrsne r0, psp \n" + " ldr r1, [r0, #24] \n" + " ldr r2, hardfault_trace_stack_addr \n" + " bx r2 \n" + " hardfault_trace_stack_addr: .word hardfault_trace_stack \n"); +} + +void __attribute__((naked, aligned(4))) _memmanage_isr() +{ + __asm__ volatile(" tst lr, #4 \n" + " ite eq \n" + " mrseq r0, msp \n" + " mrsne r0, psp \n" + " ldr r1, [r0, #24] \n" + " ldr r2, memmanage_trace_stack_addr \n" + " bx r2 \n" + " memmanage_trace_stack_addr: .word memmanage_trace_stack \n"); +} + +void __attribute__((naked, aligned(4))) _busfault_isr() +{ + __asm__ volatile(" tst lr, #4 \n" + " ite eq \n" + " mrseq r0, msp \n" + " mrsne r0, psp \n" + " ldr r1, [r0, #24] \n" + " ldr r2, busfault_trace_stack_addr \n" + " bx r2 \n" + " busfault_trace_stack_addr: .word busfault_trace_stack \n"); +} + +void __attribute__((naked, aligned(4))) _usagefault_isr() +{ + __asm__ volatile(" tst lr, #4 \n" + " ite eq \n" + " mrseq r0, msp \n" + " mrsne r0, psp \n" + " ldr r1, [r0, #24] \n" + " ldr r2, usagefault_trace_stack_addr \n" + " bx r2 \n" + " usagefault_trace_stack_addr: .word usagefault_trace_stack \n"); +} + +void hardfault_trace_stack(u32 *pulFaultStackAddress) +{ + (void) pulFaultStackAddress; + while (1) continue; +} + +void memmanage_trace_stack(u32 *pulFaultStackAddress) +{ + (void) pulFaultStackAddress; + while (1) continue; +} + +void busfault_trace_stack(u32 *pulFaultStackAddress) +{ + (void) pulFaultStackAddress; + while (1) continue; +} + +void usagefault_trace_stack(u32 *pulFaultStackAddress) +{ + (void) pulFaultStackAddress; + while (1) continue; +} From d6aed0c352275a3ea176ddbda4b6cb6a6a29b68f Mon Sep 17 00:00:00 2001 From: Rafael Silva Date: Sat, 2 Jul 2022 04:30:23 +0100 Subject: [PATCH 11/13] target: add initial russian woodpecker port Signed-off-by: Rafael Silva --- .../russian-woodpecker/russian-woodpecker.ld | 2 + config/targets/russian-woodpecker.toml | 2 + .../config/russian-woodpecker.h | 13 ++++++ src/targets/russian-woodpecker/main.c | 24 +++++++++++ src/targets/russian-woodpecker/tusb_config.h | 42 +++++++++++++++++++ 5 files changed, 83 insertions(+) create mode 100644 config/linker/russian-woodpecker/russian-woodpecker.ld create mode 100644 config/targets/russian-woodpecker.toml create mode 100644 src/targets/russian-woodpecker/config/russian-woodpecker.h create mode 100644 src/targets/russian-woodpecker/main.c create mode 100644 src/targets/russian-woodpecker/tusb_config.h diff --git a/config/linker/russian-woodpecker/russian-woodpecker.ld b/config/linker/russian-woodpecker/russian-woodpecker.ld new file mode 100644 index 00000000..423f9eaa --- /dev/null +++ b/config/linker/russian-woodpecker/russian-woodpecker.ld @@ -0,0 +1,2 @@ + +INCLUDE sam3u/sam3u2.ld diff --git a/config/targets/russian-woodpecker.toml b/config/targets/russian-woodpecker.toml new file mode 100644 index 00000000..786ed47c --- /dev/null +++ b/config/targets/russian-woodpecker.toml @@ -0,0 +1,2 @@ +family = 'sam3u' +has-config = true diff --git a/src/targets/russian-woodpecker/config/russian-woodpecker.h b/src/targets/russian-woodpecker/config/russian-woodpecker.h new file mode 100644 index 00000000..11049465 --- /dev/null +++ b/src/targets/russian-woodpecker/config/russian-woodpecker.h @@ -0,0 +1,13 @@ +/* + * SPDX-License-Identifier: MIT + * SPDX-FileCopyrightText: 2021 Rafael Silva + */ + +/* clang-format off */ + +/* General Config */ + +#define __SAM3U2C__ + +/* Clock Config */ +#define EXTERNAL_CLOCK_VALUE 12000000UL diff --git a/src/targets/russian-woodpecker/main.c b/src/targets/russian-woodpecker/main.c new file mode 100644 index 00000000..1f2312c2 --- /dev/null +++ b/src/targets/russian-woodpecker/main.c @@ -0,0 +1,24 @@ +/* + * SPDX-License-Identifier: MIT + * SPDX-FileCopyrightText: 2022 Rafael Silva + */ + +#include "util/data.h" +#include "util/types.h" + +#include "platform/sam3u/eefc.h" +#include "platform/sam3u/pmc.h" +#include "platform/sam3u/wdt.h" + +void main() +{ + pmc_init(EXTERNAL_CLOCK_VALUE, 0UL); + pmc_update_clock_tree(); + + wdt_disable(); + + // systick_init(); + + for (;;) { + } +} diff --git a/src/targets/russian-woodpecker/tusb_config.h b/src/targets/russian-woodpecker/tusb_config.h new file mode 100644 index 00000000..cd88788e --- /dev/null +++ b/src/targets/russian-woodpecker/tusb_config.h @@ -0,0 +1,42 @@ +/* + * SPDX-License-Identifier: MIT + * SPDX-FileCopyrightText: 2021 Rafael Silva + */ + +/* Common Configuration */ + +#define CFG_TUSB_MCU OPT_MCU_SAM3U + +#define CFG_TUSB_OS OPT_OS_NONE + +#define CFG_TUSB_RHPORT0_MODE (OPT_MODE_DEVICE | OPT_MODE_HIGH_SPEED) + +/* + * USB DMA on some MCUs can only access a specific SRAM region with restriction on alignment. + * Tinyusb use follows macros to declare transferring memory so that they can be put + * into those specific section. + * e.g + * - CFG_TUSB_MEM SECTION : __attribute__ (( section(".usb_ram") )) + * - CFG_TUSB_MEM_ALIGN : __attribute__ ((aligned(4))) + */ +#ifndef CFG_TUSB_MEM_SECTION +#define CFG_TUSB_MEM_SECTION +#endif + +#ifndef CFG_TUSB_MEM_ALIGN +#define CFG_TUSB_MEM_ALIGN __attribute__((aligned(4))) +#endif + +/* Device Configuration */ + +#define CFG_TUD_ENDPOINT0_SIZE 64 + +/* Class */ +#define CFG_TUD_HID 3 +#define CFG_TUD_CDC 0 +#define CFG_TUD_MSC 0 +#define CFG_TUD_MIDI 0 +#define CFG_TUD_VENDOR 0 + +/* HID buffer size Should be sufficient to hold ID (if any) + Data */ +#define CFG_TUD_HID_BUFSIZE 64 From d92b304f558f4f8a153066e3091f2f6733b531a8 Mon Sep 17 00:00:00 2001 From: Rafael Silva Date: Sat, 2 Jul 2022 04:51:24 +0100 Subject: [PATCH 12/13] platform/sam3u: gpio initial implrmentqt Signed-off-by: Rafael Silva --- src/platform/sam3u/pio.c | 198 +++++++++++++++++++++++++++++++++++++++ src/platform/sam3u/pio.h | 65 +++++++++++++ 2 files changed, 263 insertions(+) create mode 100644 src/platform/sam3u/pio.c create mode 100644 src/platform/sam3u/pio.h diff --git a/src/platform/sam3u/pio.c b/src/platform/sam3u/pio.c new file mode 100644 index 00000000..3a32f7ff --- /dev/null +++ b/src/platform/sam3u/pio.c @@ -0,0 +1,198 @@ +/* + * SPDX-License-Identifier: MIT + * SPDX-FileCopyrightText: 2021 Rafael Silva + */ + +#include + +#include "platform/sam3u/pio.h" +#include "platform/sam3u/pmc.h" +#include "util/data.h" + +/* + * resolves to the base address of the PIO peripheral + * 0x00000200 is the size/offset of each PIO peripheral in memory + */ +#define _PIO(port) ((Pio *) ((u32) PIOA + (u32) (port * 0x00000200UL))) + +void pio_init() +{ + /** + * PORT A + */ + pmc_peripheral_clock_enable(ID_PIOA); // Enable peripheral clock + + /** OUTPUT **/ + /* Multi-drive (open-drain) enable (ER) or disable (DR) */ + PIOA->PIO_MDDR = 0xFFFFFFFF; + /* Output set enable (ER) or disable (DR) */ + PIOA->PIO_OWDR = 0xFFFFFFFF; + /* Output enable (ER) or disable (DR) */ + PIOA->PIO_ODR = 0xFFFFFFFF; + + /** INPUT **/ + /* Input filter enable (ER) or disable (DR) */ + PIOA->PIO_IFDR = 0xFFFFFFFF; + + /** PULL **/ + /* Pull-up enable (ER) or disable (DR) */ + PIOA->PIO_PUDR = 0xFFFFFFFF; + + /** PERIPHERALS **/ + /* GPIO (ER) or Peripheral control (DR) */ + PIOA->PIO_PER = 0xFFFFFFFF; + + /** INTERRUPTS **/ + /* Interrupt enable (ER) / disable (DR) */ + PIOA->PIO_IDR = 0xFFFFFFFF; + /* Advanced interrupt enable (ER) or disable (DR) */ + PIOA->PIO_AIMDR = 0xFFFFFFFF; + + /** + * PORT B + */ + pmc_peripheral_clock_enable(ID_PIOB); // Enable peripheral clock + + /** OUTPUT **/ + /* Multi-drive (open-drain) enable (ER) or disable (DR) */ + PIOB->PIO_MDDR = 0xFFFFFFFF; + /* Output set enable (ER) or disable (DR) */ + PIOB->PIO_OWDR = 0xFFFFFFFF; + /* Output enable (ER) or disable (DR) */ + PIOB->PIO_ODR = 0xFFFFFFFF; + + /** INPUT **/ + /* Input filter enable (ER) or disable (DR) */ + PIOB->PIO_IFDR = 0xFFFFFFFF; + + /** PULL **/ + /* Pull-up enable (ER) or disable (DR) */ + PIOB->PIO_PUDR = 0xFFFFFFFF; + + /** PERIPHERALS **/ + /* GPIO (ER) or Peripheral control (DR) */ + PIOB->PIO_PER = 0xFFFFFFFF; + + /** INTERRUPTS **/ + /* Interrupt enable (ER) / disable (DR) */ + PIOB->PIO_IDR = 0xFFFFFFFF; + /* Advanced interrupt enable (ER) or disable (DR) */ + PIOB->PIO_AIMDR = 0xFFFFFFFF; + +/** + * PORT C + */ +#if defined(PIOC) + pmc_peripheral_clock_gate(ID_PIOC); // Enable peripheral clock + + /** OUTPUT **/ + /* Multi-drive (open-drain) enable (ER) or disable (DR) */ + PIOC->PIO_MDDR = 0xFFFFFFFF; + /* Output set enable (ER) or disable (DR) */ + PIOC->PIO_OWDR = 0xFFFFFFFF; + /* Output enable (ER) or disable (DR) */ + PIOC->PIO_ODR = 0xFFFFFFFF; + + /** INPUT **/ + /* Input filter enable (ER) or disable (DR) */ + PIOC->PIO_IFDR = 0xFFFFFFFF; + /* Slow filter enable (ER) or disable (DR) */ + PIOC->PIO_IFSCDR = 0xFFFFFFFF; + + /** PULL **/ + /* Pull-up enable (ER) or disable (DR) */ + PIOC->PIO_PUDR = 0xFFFFFFFF; + /* Pull-down enable (ER) or disable (DR) */ + PIOC->PIO_PPDER = 0xFFFFFFFF; + + /** PERIPHERALS **/ + /* GPIO (ER) or Peripheral control (DR) */ + PIOC->PIO_PER = 0xFFFFFFFF; + + /** INTERRUPTS **/ + /* Interrupt enable (ER) / disable (DR) */ + PIOC->PIO_IDR = 0xFFFFFFFF; + /* Advanced interrupt enable (ER) or disable (DR) */ + PIOC->PIO_AIMDR = 0xFFFFFFFF; + +#endif +} + +void pio_config( + struct pio_pin_t pin, + enum pio_direction_t direction, + u8 out_data, + enum pio_pull_t pull, + enum pio_mux_t mux, + enum pio_config_flags_t config) +{ + pio_direction(pin, direction); + pio_pull(pin, pull); + + if (config & PIO_OPEN_DRAIN) { + _PIO(pin.port)->PIO_MDER = BIT(pin.pin); + } else { + _PIO(pin.port)->PIO_MDDR = BIT(pin.pin); + } + + if (config & PIO_FILTER) { + _PIO(pin.port)->PIO_IFER = BIT(pin.pin); + } else { + _PIO(pin.port)->PIO_IFDR = BIT(pin.pin); + } + + pio_set(pin, out_data); + pio_peripheral_mux(pin, mux); + pio_peripheral_control(pin, config & PIO_PERIPHERAL_CTRL); +} + +void pio_peripheral_mux(struct pio_pin_t pin, enum pio_mux_t mux) +{ + _PIO_PERI_MUX_SELECT(pin.port, pin.pin, mux); +} + +void pio_peripheral_control(struct pio_pin_t pin, u8 enable) +{ + if (enable) { + _PIO(pin.port)->PIO_PDR = BIT(pin.pin); + } else { + _PIO(pin.port)->PIO_PER = BIT(pin.pin); + } +} + +void pio_direction(struct pio_pin_t pin, enum pio_direction_t direction) +{ + if (direction) // 1 = input + { + _PIO(pin.port)->PIO_ODR = BIT(pin.pin); + } else { + _PIO(pin.port)->PIO_OER = BIT(pin.pin); + } +} + +void pio_pull(struct pio_pin_t pin, enum pio_pull_t pull) +{ + if (pull & PIO_PULL_UP) + _PIO(pin.port)->PIO_PUER = BIT(pin.pin); + else + _PIO(pin.port)->PIO_PUDR = BIT(pin.pin); + + if (pull & PIO_PULL_DOWN) + _PIO(pin.port)->PIO_PPDER = BIT(pin.pin); + else + _PIO(pin.port)->PIO_PPDDR = BIT(pin.pin); +} + +void pio_set(struct pio_pin_t pin, u8 state) +{ + if (state) { + _PIO(pin.port)->PIO_SODR = BIT(pin.pin); + } else { + _PIO(pin.port)->PIO_CODR = BIT(pin.pin); + } +} + +u8 pio_get(struct pio_pin_t pin) +{ + return !!(_PIO(pin.port)->PIO_PDSR & BIT(pin.pin)); +} diff --git a/src/platform/sam3u/pio.h b/src/platform/sam3u/pio.h new file mode 100644 index 00000000..aa4c88fa --- /dev/null +++ b/src/platform/sam3u/pio.h @@ -0,0 +1,65 @@ +/* + * SPDX-License-Identifier: MIT + * SPDX-FileCopyrightText: 2021 Rafael Silva + */ + +#pragma once + +#include "util/types.h" + +/* ports */ +enum pio_port_t { + PIO_PORT_A = 0, + PIO_PORT_B = 1, +#if defined(PIOC) + PIO_PORT_C = 2, +#endif +}; + +struct pio_pin_t { + u8 port; + u8 pin; +}; + +enum pio_mux_t { + PIO_MUX_A = 0, + PIO_MUX_B = 1, +}; + +enum pio_pull_t { + PIO_PULL_NONE = 0x0, + PIO_PULL_UP = 0x1, +}; + +enum pio_direction_t { + PIO_DIRECTION_OUT = 0, + PIO_DIRECTION_IN = 1, +}; + +enum pio_config_flags_t { + PIO_OPEN_DRAIN = 0x4, // bit 3 + PIO_FILTER = 0x10, // bit 5 + PIO_PERIPHERAL_CTRL = 0x40, // bit 7 +}; + +void pio_init(); + +void pio_config( + struct pio_pin_t pin, + enum pio_direction_t direction, + u8 out_data, + enum pio_pull_t pull, + enum pio_mux_t mux, + enum pio_config_flags_t config); + +void pio_peripheral_mux(struct pio_pin_t pin, enum pio_mux_t mux); + +void pio_peripheral_control(struct pio_pin_t pin, u8 enable); + +void pio_direction(struct pio_pin_t pin, enum pio_direction_t direction); + +void pio_pull(struct pio_pin_t pin, enum pio_pull_t pull); + +void pio_set(struct pio_pin_t pin, u8 state); + +u8 pio_get(struct pio_pin_t pin); From 96c87e140ac89010c7f680c89f372c5e12ee3eeb Mon Sep 17 00:00:00 2001 From: Rafael Silva Date: Thu, 7 Jul 2022 00:52:35 +0100 Subject: [PATCH 13/13] temp commit Signed-off-by: Rafael Silva --- config/families/sam3u.toml | 4 ++ src/platform/sam3u/atomic.h | 46 ++++++++++++ src/platform/sam3u/pio.c | 7 +- src/platform/sam3u/systick.c | 63 +++++++++++++++++ src/platform/sam3u/systick.h | 13 ++++ src/platform/samx7x/pio.h | 2 - .../config/russian-woodpecker.h | 5 ++ src/targets/russian-woodpecker/main.c | 70 ++++++++++++++++++- 8 files changed, 201 insertions(+), 9 deletions(-) create mode 100644 src/platform/sam3u/atomic.h create mode 100644 src/platform/sam3u/systick.c create mode 100644 src/platform/sam3u/systick.h diff --git a/config/families/sam3u.toml b/config/families/sam3u.toml index 66116596..66e126e1 100644 --- a/config/families/sam3u.toml +++ b/config/families/sam3u.toml @@ -1,5 +1,6 @@ toolchain = 'arm-none-eabi' c_flags = [ + '-g', '-Os', '-nostdlib', '-nostartfiles', @@ -12,6 +13,7 @@ c_flags = [ '-ffreestanding', ] ld_flags = [ + '-g', '-lm', '-lc', '-lgcc', @@ -32,6 +34,8 @@ source = [ 'eefc.c', 'wdt.c', 'pmc.c', + 'pio.c', + 'systick.c', 'exceptions.c', ] diff --git a/src/platform/sam3u/atomic.h b/src/platform/sam3u/atomic.h new file mode 100644 index 00000000..17f0a3be --- /dev/null +++ b/src/platform/sam3u/atomic.h @@ -0,0 +1,46 @@ +/* + * SPDX-License-Identifier: MIT + * SPDX-FileCopyrightText: 2021 Rafael Silva + */ + +#pragma once + +#include + +#include "util/types.h" + +static inline u32 __iEnableIRQRetVal() +{ + __asm__ volatile("cpsie i" ::: "memory"); + + return 1; +} +static inline u32 __iDisableIRQRetVal() +{ + __asm__ volatile("cpsid i" ::: "memory"); + + return 1; +} +static inline void __iEnableIRQParam(const u32 *__s) +{ + __asm__ volatile("cpsie i" ::: "memory"); + (void) __s; +} +static inline void __iDisableIRQParam(const u32 *__s) +{ + __asm__ volatile("cpsid i" ::: "memory"); + (void) __s; +} +static inline void __iRestore(const u32 *__s) +{ + if (!*__s) + __asm__ volatile("cpsie i" ::: "memory"); +} + +#define ATOMIC_BLOCK(type) for (type, __ToDo = __iDisableIRQRetVal(); __ToDo; __ToDo = 0) +#define NONATOMIC_BLOCK(type) for (type, __ToDo = __iEnableIRQRetVal(); __ToDo; __ToDo = 0) + +#define ATOMIC_RESTORESTATE u32 primask_save __attribute__((__cleanup__(__iRestore))) = __get_PRIMASK() +#define ATOMIC_FORCEON u32 primask_save __attribute__((__cleanup__(__iEnableIRQParam))) = 0 +#define NONATOMIC_RESTORESTATE u32 primask_save __attribute__((__cleanup__(__iRestore))) = __get_PRIMASK() +#define NONATOMIC_FORCEOFF u32 primask_save __attribute__((__cleanup__(__iDisableIRQParam))) = 0 diff --git a/src/platform/sam3u/pio.c b/src/platform/sam3u/pio.c index 3a32f7ff..92ae4350 100644 --- a/src/platform/sam3u/pio.c +++ b/src/platform/sam3u/pio.c @@ -148,7 +148,7 @@ void pio_config( void pio_peripheral_mux(struct pio_pin_t pin, enum pio_mux_t mux) { - _PIO_PERI_MUX_SELECT(pin.port, pin.pin, mux); + _PIO(pin.port)->PIO_ABSR = (_PIO(pin.port)->PIO_ABSR & ~BIT(pin.pin)) | (mux << pin.pin); } void pio_peripheral_control(struct pio_pin_t pin, u8 enable) @@ -176,11 +176,6 @@ void pio_pull(struct pio_pin_t pin, enum pio_pull_t pull) _PIO(pin.port)->PIO_PUER = BIT(pin.pin); else _PIO(pin.port)->PIO_PUDR = BIT(pin.pin); - - if (pull & PIO_PULL_DOWN) - _PIO(pin.port)->PIO_PPDER = BIT(pin.pin); - else - _PIO(pin.port)->PIO_PPDDR = BIT(pin.pin); } void pio_set(struct pio_pin_t pin, u8 state) diff --git a/src/platform/sam3u/systick.c b/src/platform/sam3u/systick.c new file mode 100644 index 00000000..9ee16938 --- /dev/null +++ b/src/platform/sam3u/systick.c @@ -0,0 +1,63 @@ +/* + * SPDX-License-Identifier: MIT + * SPDX-FileCopyrightText: 2021 Rafael Silva + */ + +#include + +#include "platform/sam3u/atomic.h" +#include "platform/sam3u/pmc.h" +#include "platform/sam3u/systick.h" +#include "util/data.h" + +static volatile u64 system_tick = 0; + +static u32 systick_clock_freq; + +void _systick_isr() +{ + system_tick++; +} + +void systick_init() +{ + const struct pmc_clock_tree_t *clock_tree = pmc_get_clock_tree(); + + systick_clock_freq = clock_tree->fclk_freq; + + /* ms tick initialization */ + SysTick->LOAD = (systick_clock_freq / 1000) - 1; + SysTick->VAL = 0; + SysTick->CTRL = SysTick_CTRL_TICKINT_Msk | SysTick_CTRL_ENABLE_Msk | SysTick_CTRL_CLKSOURCE_Msk; + + SCB->SHP[11] = 7 << (8 - __NVIC_PRIO_BITS); // Set priority 3,1 (min) + + /* delay us initialization */ + CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; /* Enable TRC */ + DWT->CYCCNT = 0; + DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk; /* Enable clock cycle counter */ +} + +u64 systick_get_ticks() +{ + return system_tick; +} + +void delay_ms(u32 ticks) +{ + NONATOMIC_BLOCK(NONATOMIC_RESTORESTATE) + { + u64 start_tick = system_tick; + + while ((system_tick - start_tick) < ticks) continue; + } +} + +void delay_us(u32 ticks) +{ + u32 start_tick = DWT->CYCCNT; + + ticks *= (systick_clock_freq / 1000000); + + while (DWT->CYCCNT - start_tick < ticks) continue; +} diff --git a/src/platform/sam3u/systick.h b/src/platform/sam3u/systick.h new file mode 100644 index 00000000..0b08ac2b --- /dev/null +++ b/src/platform/sam3u/systick.h @@ -0,0 +1,13 @@ +/* + * SPDX-License-Identifier: MIT + * SPDX-FileCopyrightText: 2021 Rafael Silva + */ + +#pragma once + +#include "util/types.h" + +void systick_init(); +u64 systick_get_ticks(); +void delay_ms(u32 ticks); +void delay_us(u32 ticks); diff --git a/src/platform/samx7x/pio.h b/src/platform/samx7x/pio.h index 07308aee..78c643fe 100644 --- a/src/platform/samx7x/pio.h +++ b/src/platform/samx7x/pio.h @@ -35,8 +35,6 @@ enum pio_mux_t { enum pio_pull_t { PIO_PULL_NONE = 0x0, PIO_PULL_UP = 0x1, // bit 1 - PIO_PULL_DOWN = 0x2, // bit 2 - PIO_PULL_BOTH = 0x3, }; enum pio_direction_t { diff --git a/src/targets/russian-woodpecker/config/russian-woodpecker.h b/src/targets/russian-woodpecker/config/russian-woodpecker.h index 11049465..3acfe27e 100644 --- a/src/targets/russian-woodpecker/config/russian-woodpecker.h +++ b/src/targets/russian-woodpecker/config/russian-woodpecker.h @@ -11,3 +11,8 @@ /* Clock Config */ #define EXTERNAL_CLOCK_VALUE 12000000UL + +/* LED */ +#define LED_R { .port = PIO_PORT_A, .pin = 30 } +#define LED_G { .port = PIO_PORT_A, .pin = 1 } +#define LED_B { .port = PIO_PORT_B, .pin = 5 } diff --git a/src/targets/russian-woodpecker/main.c b/src/targets/russian-woodpecker/main.c index 1f2312c2..5f9e8e4e 100644 --- a/src/targets/russian-woodpecker/main.c +++ b/src/targets/russian-woodpecker/main.c @@ -7,18 +7,86 @@ #include "util/types.h" #include "platform/sam3u/eefc.h" +#include "platform/sam3u/pio.h" #include "platform/sam3u/pmc.h" +#include "platform/sam3u/systick.h" #include "platform/sam3u/wdt.h" +#include + void main() { pmc_init(EXTERNAL_CLOCK_VALUE, 0UL); pmc_update_clock_tree(); + systick_init(); + wdt_disable(); - // systick_init(); + pio_init(); + + const struct pio_pin_t red_led_io = LED_R; + const struct pio_pin_t green_led_io = LED_G; + const struct pio_pin_t blue_led_io = LED_B; + + pio_config(red_led_io, PIO_DIRECTION_OUT, 1, PIO_PULL_NONE, PIO_MUX_A, PIO_PERIPHERAL_CTRL); + pio_peripheral_mux(red_led_io, PIO_MUX_B); + + pio_config(green_led_io, PIO_DIRECTION_OUT, 1, PIO_PULL_NONE, PIO_MUX_A, PIO_PERIPHERAL_CTRL); + pio_peripheral_mux(green_led_io, PIO_MUX_A); + + pio_config(blue_led_io, PIO_DIRECTION_OUT, 1, PIO_PULL_NONE, PIO_MUX_A, PIO_PERIPHERAL_CTRL); + pio_peripheral_mux(blue_led_io, PIO_MUX_A); + + // pio_set((struct pio_pin_t)LED_R, 0); + + TC0->TC_CHANNEL[0].TC_CCR = TC_CCR_CLKDIS; /* Disable TC clock. */ + TC0->TC_CHANNEL[0].TC_IDR = 0xFFFFFFFF; /* Disable interrupts. */ + TC0->TC_CHANNEL[0].TC_SR; /* Clear status register. */ + TC0->TC_CHANNEL[0].TC_CMR; /* Set mode. */ + + TC0->TC_CHANNEL[1].TC_CCR = TC_CCR_CLKDIS; /* Disable TC clock. */ + TC0->TC_CHANNEL[1].TC_IDR = 0xFFFFFFFF; /* Disable interrupts. */ + TC0->TC_CHANNEL[1].TC_CMR; /* Set mode. */ + + TC0->TC_CHANNEL[2].TC_CCR = TC_CCR_CLKDIS; /* Disable TC clock. */ + TC0->TC_CHANNEL[2].TC_IDR = 0xFFFFFFFF; /* Disable interrupts. */ + TC0->TC_CHANNEL[2].TC_CMR; /* Set mode. */ + + TC0->TC_CHANNEL[0].TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG; /* Set mode. */ + TC0->TC_CHANNEL[1].TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG; /* Set mode. */ + TC0->TC_CHANNEL[2].TC_CCR = TC_CCR_CLKEN | TC_CCR_SWTRG; /* Set mode. */ + + TC0->TC_CHANNEL[0].TC_RA = 128; /* Set RA. */ + TC0->TC_CHANNEL[1].TC_RA = 128; + TC0->TC_CHANNEL[2].TC_RA = 128; for (;;) { + // static uint8_t curr_led; + + // switch (curr_led) { + // case 0: + // LED_R_PORT->PIO_CODR = (1 << LED_R_PIN); + // LED_G_PORT->PIO_SODR = (1 << LED_G_PIN); + // LED_B_PORT->PIO_SODR = (1 << LED_B_PIN); + // break; + + // case 1: + // LED_R_PORT->PIO_SODR = (1 << LED_R_PIN); + // LED_G_PORT->PIO_CODR = (1 << LED_G_PIN); + // LED_B_PORT->PIO_SODR = (1 << LED_B_PIN); + // break; + + // case 2: + // LED_R_PORT->PIO_SODR = (1 << LED_R_PIN); + // LED_G_PORT->PIO_SODR = (1 << LED_G_PIN); + // LED_B_PORT->PIO_CODR = (1 << LED_B_PIN); + // break; + // } + + // curr_led++; + // curr_led %= 3; + + delay_ms(100); } }