diff --git a/Makefile b/Makefile index 5a176b88..654e5ab3 100644 --- a/Makefile +++ b/Makefile @@ -32,7 +32,7 @@ TARGETS ?= stm32/f0 stm32/f1 stm32/f2 stm32/f3 stm32/f4 stm32/f7 \ lpc13xx lpc17xx lpc43xx/m4 lpc43xx/m0 \ lm3s lm4f \ efm32/tg efm32/g efm32/lg efm32/gg efm32/hg \ - sam/3a sam/3n sam/3s sam/3u sam/3x \ + sam/3a sam/3n sam/3s sam/3u sam/3x sam/4l \ sam/d \ vf6xx diff --git a/include/libopencm3/dispatch/nvic.h b/include/libopencm3/dispatch/nvic.h index b664c1b1..62a6be46 100644 --- a/include/libopencm3/dispatch/nvic.h +++ b/include/libopencm3/dispatch/nvic.h @@ -51,6 +51,8 @@ # include #elif defined(SAM3X) # include +#elif defined(SAM4L) +# include #elif defined(SAMD) # include diff --git a/include/libopencm3/sam/4l/adcife.h b/include/libopencm3/sam/4l/adcife.h new file mode 100644 index 00000000..c0cfb5db --- /dev/null +++ b/include/libopencm3/sam/4l/adcife.h @@ -0,0 +1,259 @@ +/* + * This file is part of the libopencm3 project. + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#ifndef LIBOPENCM3_SAM4L_ADCIFE_H +#define LIBOPENCM3_SAM4L_ADCIFE_H + +#include + + +/* Analog to Digital Converter Interface (ADCIFE) registers. */ + +/* 0x0000 Control Register CR Write-Only 0x00000000 */ +#define ADCIFE_CR MMIO32(ADCIFE_BASE + 0x0000) + +/* 0x0004 Configuration Register CFG Read/Write 0x00000000 */ +#define ADCIFE_CFG MMIO32(ADCIFE_BASE + 0x0004) + +/* 0x0008 Status Register SR Read-Only 0x00000000 */ +#define ADCIFE_SR MMIO32(ADCIFE_BASE + 0x008) + +/* 0x000C Status Clear Register SCR Write-Only 0x00000000 */ +#define ADCIFE_SCR MMIO32(ADCIFE_BASE + 0x000C) + +/* 0x0014 Sequencer Configuration Register SEQCFG Read/Write 0x00000000 */ +#define ADCIFE_SEQCFG MMIO32(ADCIFE_BASE + 0x0014) + +/* 0x0018 Configuration Direct Memory Access Register CDMA Write-Only 0x00000000 */ +#define ADCIFE_CDMA MMIO32(ADCIFE_BASE + 0x0018) + +/* 0x001C Timing Configuration Register TIM Read/Write 0x00000000 */ +#define ADCIFE_TIM MMIO32(ADCIFE_BASE + 0x001C) + +/* 0x0020 Internal Timer Register ITIMER Read/Write 0x00000000 */ +#define ADCIFE_ITIMER MMIO32(ADCIFE_BASE + 0x0020) + +/* 0x0024 Window Monitor Configuration Register WCFG Read/Write 0x00000000 */ +#define ADCIFE_WCFG MMIO32(ADCIFE_BASE + 0x0024) + +/* 0x0028 Window Monitor Threshold Configuration Register WTH Read/Write 0x00000000 */ +#define ADCIFE_WTH MMIO32(ADCIFE_BASE + 0x0028) + +/* 0x002C Sequencer Last Converted Value Register LCV Read-Only 0x00000000 */ +#define ADCIFE_LCV MMIO32(ADCIFE_BASE + 0x002C) + +/* 0x0030 Interrupt Enable Register IER Write-Only 0x00000000 */ +#define ADCIFE_IER MMIO32(ADCIFE_BASE + 0x0030) + +/* 0x0034 Interrupt Disable Register IDR Write-Only 0x00000000 */ +#define ADCIFE_IDR MMIO32(ADCIFE_BASE + 0x0034) + +/* 0x0038 Interrupt Mask Register IMR Read-Only 0x00000000 */ +#define ADCIFE_IMR MMIO32(ADCIFE_BASE + 0x0038) + +/* 0x003C Calibration Register CALIB Read/Write 0x00000000 */ +#define ADCIFE_CALIB MMIO32(ADCIFE_BASE + 0x003C) + +/* 0x0040 Version Register VERSION Read-Only - */ +#define ADCIFE_VERSION MMIO32(ADCIFE_BASE + 0x0040) + +/* 0x0044 Parameter Register PARAMETER Read-Only - */ +#define ADCIFE_PARAMETER MMIO32(ADCIFE_BASE + 0x0044) + + +/* --------- Register Contents --------------------------- */ +#define ADCIFE_CR_SWRST (1 << 0) +#define ADCIFE_CR_TSTOP (1 << 1) +#define ADCIFE_CR_TSTART (1 << 2) +#define ADCIFE_CR_STRIG (1 << 3) +#define ADCIFE_CR_REFBUFEN (1 << 4) +#define ADCIFE_CR_REFBUFDIS (1 << 5) +#define ADCIFE_CR_EN (1 << 8) +#define ADCIFE_CR_DIS (1 << 9) +#define ADCIFE_CR_BGREQEN (1 << 10) +#define ADCIFE_CR_BGREQDIS (1 << 11) + +#define _MASKED_VALUE(V, S, M) (((V) << (S)) & (M)) + +#define ADCIFE_CFG_REFSEL_SHIFT (1) +#define ADCIFE_CFG_REFSEL_MASK (7 << ADCIFE_CFG_REFSEL_SHIFT) +#define ADCIFE_CFG_REFSEL_MASKED(V) _MASKED_VALUE((V), ADCIFE_CFG_REFSEL_SHIFT, ADCIFE_CFG_REFSEL_MASK) +#define ADCIFE_CFG_SPEED_SHIFT (4) +#define ADCIFE_CFG_SPEED_MASK (3 << ADCIFE_CFG_SPEED_SHIFT) +#define ADCIFE_CFG_SPEED_MASKED(V) _MASKED_VALUE((V), ADCIFE_CFG_SPEED_SHIFT, ADCIFE_CFG_SPEED_MASK) +#define ADCIFE_CFG_CLKSEL (1 << 6) +#define ADCIFE_CFG_PRESCAL_SHIFT (8) +#define ADCIFE_CFG_PRESCAL_MASK (3 << ADCIFE_CFG_PRESCAL_SHIFT) +#define ADCIFE_CFG_PRESCAL_MASKED(V) _MASKED_VALUE((V), ADCIFE_CFG_PRESCAL_SHIFT, ADCIFE_CFG_PRESCAL_MASK) + +#define ADCIFE_SR_SEOC (1 << 0) +#define ADCIFE_SR_LOVR (1 << 1) +#define ADCIFE_SR_WM (1 << 2) +#define ADCIFE_SR_SMTRG (1 << 3) +#define ADCIFE_SR_TTO (1 << 5) +#define ADCIFE_SR_EN (1 << 24) +#define ADCIFE_SR_TBUSY (1 << 25) +#define ADCIFE_SR_SBUSY (1 << 26) +#define ADCIFE_SR_CBUSY (1 << 27) +#define ADCIFE_SR_REFBUF (1 << 28) +#define ADCIFE_SR_BGREQ (1 << 30) + +#define ADCIFE_IR_SEOC (1 << 0) +#define ADCIFE_IR_LOVR (1 << 1) +#define ADCIFE_IR_WM (1 << 2) +#define ADCIFE_IR_SMTRG (1 << 3) +#define ADCIFE_IR_TTO (1 << 5) + +#define ADCIFE_SEQCFG_HWLA (1 << 0) +#define ADCIFE_SEQCFG_BIPOLAR (1 << 2) +#define ADCIFE_SEQCFG_GAIN_SHIFT (4) +#define ADCIFE_SEQCFG_GAIN_MASK (7 << ADCIFE_SEQCFG_GAIN_SHIFT) +#define ADCIFE_SEQCFG_GAIN_MASKED(V) _MASKED_VALUE((V), ADCIFE_SEQCFG_GAIN_SHIFT, ADCIFE_SEQCFG_GAIN_MASK) +#define ADCIFE_SEQCFG_GCOMP (1 << 7) +#define ADCIFE_SEQCFG_TRGSEL_SHIFT (8) +#define ADCIFE_SEQCFG_TRGSEL_MASK (7 << ADCIFE_SEQCFG_TRGSEL_SHIFT) +#define ADCIFE_SEQCFG_TRGSEL_MASKED(V) _MASKED_VALUE((V), ADCIFE_SEQCFG_TRGSEL_SHIFT, ADCIFE_SEQCFG_TRGSEL_MASK) +#define ADCIFE_SEQCFG_RES (1 << 12) +#define ADCIFE_SEQCFG_INTERNAL_SHIFT (14) +#define ADCIFE_SEQCFG_INTERNAL_MASK (3 << ADCIFE_SEQCFG_INTERNAL_SHIFT) +#define ADCIFE_SEQCFG_INTERNAL_MASKED(V) _MASKED_VALUE((V), ADCIFE_SEQCFG_INTERNAL_SHIFT, ADCIFE_SEQCFG_INTERNAL_MASK) +#define ADCIFE_SEQCFG_MUXPOS_SHIFT (16) +#define ADCIFE_SEQCFG_MUXPOS_MASK (0xf << ADCIFE_SEQCFG_MUXPOS_SHIFT) +#define ADCIFE_SEQCFG_MUXPOS_MASKED(V) _MASKED_VALUE((V), ADCIFE_SEQCFG_MUXPOS_SHIFT, ADCIFE_SEQCFG_MUXPOS_MASK) +#define ADCIFE_SEQCFG_MUXNEG_SHIFT (20) +#define ADCIFE_SEQCFG_MUXNEG_MASK (7 << ADCIFE_SEQCFG_MUXNEG_SHIFT) +#define ADCIFE_SEQCFG_MUXNEG_MASKED(V) _MASKED_VALUE((V), ADCIFE_SEQCFG_MUXNEG_SHIFT, ADCIFE_SEQCFG_MUXNEG_MASK) +#define ADCIFE_SEQCFG_ZOOMRANGE_SHIFT (28) +#define ADCIFE_SEQCFG_ZOOMRANGE_MASK (7 << ADCIFE_SEQCFG_ZOOMRANGE_SHIFT) +#define ADCIFE_SEQCFG_ZOOMRANGE_MASKED(V) _MASKED_VALUE((V), ADCIFE_SEQCFG_ZOOMRANGE_SHIFT, ADCIFE_SEQCFG_ZOOMRANGE_MASK) + +/* If x is of type enum adcife_prescal, the prescale value is 2^(x + 2) */ +enum adcife_prescal { + ADCIFE_PRESCAL_DIV4, + ADCIFE_PRESCAL_DIV8, + ADCIFE_PRESCAL_DIV16, + ADCIFE_PRESCAL_DIV32, + ADCIFE_PRESCAL_DIV64, + ADCIFE_PRESCAL_DIV128, + ADCIFE_PRESCAL_DIV256, + ADCIFE_PRESCAL_DIV512, +}; + +enum adcife_speed { + ADCIFE_SPEED_300KSPS, + ADCIFE_SPEED_225KSPS, + ADCIFE_SPEED_150KSPS, + ADCIFE_SPEED_75KSPS, +}; + +enum adcife_refsel { + ADCIFE_REFSEL_INTERNAL1V, + ADCIFE_REFSEL_0_625xVCC, + ADCIFE_REFSEL_EXTERNAL1, + ADCIFE_REFSEL_EXTERNAL2, + ADCIFE_REFSEL_HALF_VCC, +}; + +enum adcife_clk { + ADCIFE_CLK_GENERIC, + ADCIFE_CLK_APB = ADCIFE_CFG_CLKSEL, +}; + +enum adcife_channel { + ADCIFE_CHANNEL_AD0, + ADCIFE_CHANNEL_AD1, + ADCIFE_CHANNEL_AD2, + ADCIFE_CHANNEL_AD3, + ADCIFE_CHANNEL_AD4, + ADCIFE_CHANNEL_AD5, + ADCIFE_CHANNEL_AD6, + ADCIFE_CHANNEL_AD7, + ADCIFE_CHANNEL_AD8, + ADCIFE_CHANNEL_AD9, + ADCIFE_CHANNEL_AD10, + ADCIFE_CHANNEL_AD11, + ADCIFE_CHANNEL_AD12, + ADCIFE_CHANNEL_AD13, + ADCIFE_CHANNEL_AD14, +}; + +enum adcife_resolution { + ADCIFE_RESOLUTION_12BITS, + ADCIFE_RESOLUTION_8BITS, +}; + +enum adcife_trigger { + ADCIFE_TRIGGER_SW, + ADCIFE_TRIGGER_IADC_TMR, + ADCIFE_TRIGGER_ITS, + ADCIFE_TRIGGER_CONT, + ADCIFE_TRIGGER_EXT_RIS, + ADCIFE_TRIGGER_EXT_FALL, + ADCIFE_TRIGGER_EXT_BOTH, +}; + +enum adcife_gain { + ADCIFE_GAIN_1X, + ADCIFE_GAIN_2X, + ADCIFE_GAIN_4X, + ADCIFE_GAIN_8X, + ADCIFE_GAIN_16X, + ADCIFE_GAIN_32X, + ADCIFE_GAIN_64X, + ADCIFE_GAIN_0_5X, +}; + +struct adcife_lcv { + union { + uint32_t lcv; + struct { + uint16_t value; + uint8_t channel; + uint8_t reserved; + } _lc_s; + } _lc_u; +}; + +#define lc_channel _lc_u._lc_s.channel +#define lc_value _lc_u._lc_s.value + +BEGIN_DECLS + +void adcife_enable_sync(void); +void adcife_configure( + enum adcife_refsel ref, + enum adcife_speed speed, + enum adcife_clk clk, + enum adcife_prescal prescal); +void adcife_select_channel(enum adcife_channel ad); +void adcife_set_resolution(enum adcife_resolution res); +void adcife_select_trigger(enum adcife_trigger trig); +void adcife_set_gain(enum adcife_gain gain); +void adcife_set_bipolar(bool enable); +void adcife_set_left_adjust(bool enable); +void adcife_start_conversion(void); +void adcife_wait_conversion(void); +struct adcife_lcv adcife_get_lcv(void); +void adcife_enable_interrupts(uint32_t imask); +void adcife_disable_interrupts(uint32_t imask); +void adcife_timer_start(void); +void adcife_timer_stop(void); +void adcife_timer_set_timeout(uint16_t timeout); + +END_DECLS + +#endif diff --git a/include/libopencm3/sam/4l/gpio.h b/include/libopencm3/sam/4l/gpio.h new file mode 100644 index 00000000..315b802f --- /dev/null +++ b/include/libopencm3/sam/4l/gpio.h @@ -0,0 +1,180 @@ +/* + * This file is part of the libopencm3 project. + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#ifndef LIBOPENCM3_GPIO_H +#define LIBOPENCM3_GPIO_H + +#include +#include +#include + +#define GPIOA (GPIO_BASE) +#define GPIOB (GPIO_BASE + 0x200) +#define GPIOC (GPIO_BASE + 0x400) + +#define GPIO0 (1 << 0) +#define GPIO1 (1 << 1) +#define GPIO2 (1 << 2) +#define GPIO3 (1 << 3) +#define GPIO4 (1 << 4) +#define GPIO5 (1 << 5) +#define GPIO6 (1 << 6) +#define GPIO7 (1 << 7) +#define GPIO8 (1 << 8) +#define GPIO9 (1 << 9) +#define GPIO10 (1 << 10) +#define GPIO11 (1 << 11) +#define GPIO12 (1 << 12) +#define GPIO13 (1 << 13) +#define GPIO14 (1 << 14) +#define GPIO15 (1 << 15) +#define GPIO16 (1 << 16) +#define GPIO17 (1 << 17) +#define GPIO18 (1 << 18) +#define GPIO19 (1 << 19) +#define GPIO20 (1 << 20) +#define GPIO21 (1 << 21) +#define GPIO22 (1 << 22) +#define GPIO23 (1 << 23) +#define GPIO24 (1 << 24) +#define GPIO25 (1 << 25) +#define GPIO26 (1 << 26) +#define GPIO27 (1 << 27) +#define GPIO28 (1 << 28) +#define GPIO29 (1 << 29) +#define GPIO30 (1 << 30) +#define GPIO31 (1 << 31) + + +#define GPIO_GPER(X) MMIO32(X) +#define GPIO_GPERS(X) MMIO32((X) + 0x004) +#define GPIO_GPERC(X) MMIO32((X) + 0x008) +#define GPIO_GPERT(X) MMIO32((X) + 0x00C) + +#define GPIO_PMR(P, I) MMIO32((P) + (0x10*(1 + (I)))) +#define GPIO_PMR_SETVAL(P, I, S) MMIO32((P) + (0x10*(1 + (I)) + ((S) ? 0x04 : 0x08))) + +#define GPIO_PMR0(X) MMIO32((X) + 0x010) +#define GPIO_PMR0S(X) MMIO32((X) + 0x014) +#define GPIO_PMR0C(X) MMIO32((X) + 0x018) +#define GPIO_PMR0T(X) MMIO32((X) + 0x01C) + +#define GPIO_PMR1(X) MMIO32((X) + 0x020) +#define GPIO_PMR1S(X) MMIO32((X) + 0x024) +#define GPIO_PMR1C(X) MMIO32((X) + 0x028) +#define GPIO_PMR1T(X) MMIO32((X) + 0x02C) + +#define GPIO_PMR2(X) MMIO32((X) + 0x030) +#define GPIO_PMR2S(X) MMIO32((X) + 0x034) +#define GPIO_PMR2C(X) MMIO32((X) + 0x038) +#define GPIO_PMR2T(X) MMIO32((X) + 0x03C) + +#define GPIO_ODER(X) MMIO32((X) + 0x040) +#define GPIO_ODERS(X) MMIO32((X) + 0x044) +#define GPIO_ODERC(X) MMIO32((X) + 0x048) +#define GPIO_ODERT(X) MMIO32((X) + 0x04C) + +#define GPIO_OVR(X) MMIO32((X) + 0x050) +#define GPIO_OVRS(X) MMIO32((X) + 0x054) +#define GPIO_OVRC(X) MMIO32((X) + 0x058) +#define GPIO_OVRT(X) MMIO32((X) + 0x05C) + +#define GPIO_PVR(X) MMIO32((X) + 0x060) + +#define GPIO_PUER(X) MMIO32((X) + 0x070) +#define GPIO_PUERS(X) MMIO32((X) + 0x074) +#define GPIO_PUERC(X) MMIO32((X) + 0x078) +#define GPIO_PUERT(X) MMIO32((X) + 0x07C) + +#define GPIO_PDER(X) MMIO32((X) + 0x080) +#define GPIO_PDERS(X) MMIO32((X) + 0x084) +#define GPIO_PDERC(X) MMIO32((X) + 0x088) +#define GPIO_PDERT(X) MMIO32((X) + 0x08C) + +#define GPIO_IER(X) MMIO32((X) + 0x090) +#define GPIO_IERS(X) MMIO32((X) + 0x094) +#define GPIO_IERC(X) MMIO32((X) + 0x098) +#define GPIO_IERT(X) MMIO32((X) + 0x09C) + +#define GPIO_IMR0(X) MMIO32((X) + 0x0A0) +#define GPIO_IMR0S(X) MMIO32((X) + 0x0A4) +#define GPIO_IMR0C(X) MMIO32((X) + 0x0A8) +#define GPIO_IMR0T(X) MMIO32((X) + 0x0AC) + +#define GPIO_IMR1(X) MMIO32((X) + 0x0B0) +#define GPIO_IMR1S(X) MMIO32((X) + 0x0B4) +#define GPIO_IMR1C(X) MMIO32((X) + 0x0B8) +#define GPIO_IMR1T(X) MMIO32((X) + 0x0BC) + +#define GPIO_GFER(X) MMIO32((X) + 0x0C0) +#define GPIO_GFERS(X) MMIO32((X) + 0x0C4) +#define GPIO_GFERC(X) MMIO32((X) + 0x0C8) +#define GPIO_GFERT(X) MMIO32((X) + 0x0CC) + +#define GPIO_IFR(X) MMIO32((X) + 0x0D0) +#define GPIO_IFRC(X) MMIO32((X) + 0x0D8) + +#define GPIO_ODCR0(X) MMIO32((X) + 0x100) +#define GPIO_ODCR0S(X) MMIO32((X) + 0x104) +#define GPIO_ODCR0C(X) MMIO32((X) + 0x108) +#define GPIO_ODCR0T(X) MMIO32((X) + 0x10C) + +#define GPIO_ODCR1(X) MMIO32((X) + 0x110) +#define GPIO_ODCR1S(X) MMIO32((X) + 0x114) +#define GPIO_ODCR1C(X) MMIO32((X) + 0x118) +#define GPIO_ODCR1T(X) MMIO32((X) + 0x11C) + +#define GPIO_OSRR0(X) MMIO32((X) + 0x130) +#define GPIO_OSRR0S(X) MMIO32((X) + 0x134) +#define GPIO_OSRR0C(X) MMIO32((X) + 0x138) +#define GPIO_OSRR0T(X) MMIO32((X) + 0x13C) + +#define GPIO_STER(X) MMIO32((X) + 0x160) +#define GPIO_STERS(X) MMIO32((X) + 0x164) +#define GPIO_STERC(X) MMIO32((X) + 0x168) +#define GPIO_STERT(X) MMIO32((X) + 0x16C) + +#define GPIO_EVER(X) MMIO32((X) + 0x180) +#define GPIO_EVERS(X) MMIO32((X) + 0x184) +#define GPIO_EVERC(X) MMIO32((X) + 0x188) +#define GPIO_EVERT(X) MMIO32((X) + 0x18C) + +#define GPIO_PARAMETER(X) MMIO32((X) + 0x1f8) +#define GPIO_VERSION(X) MMIO32((X) + 0x1fc) + +enum gpio_mode { + // Peripherals + GPIO_MODE_A = 0, + GPIO_MODE_B, + GPIO_MODE_C, + GPIO_MODE_D, + GPIO_MODE_E, + GPIO_MODE_F, + GPIO_MODE_G, + GPIO_MODE_H, + GPIO_MODE_IN, + GPIO_MODE_OUT, +}; + +BEGIN_DECLS + +void gpio_enable(uint32_t gpioport, uint32_t gpios, enum gpio_mode mode); +void gpio_disable(uint32_t gpioport, uint32_t gpios); + +END_DECLS + +#endif diff --git a/include/libopencm3/sam/4l/irq.json b/include/libopencm3/sam/4l/irq.json new file mode 100644 index 00000000..5bf9534f --- /dev/null +++ b/include/libopencm3/sam/4l/irq.json @@ -0,0 +1,87 @@ +{ + "irqs": [ + "hflashc", + "pdca0", + "pdca1", + "pdca2", + "pdca3", + "pdca4", + "pdca5", + "pdca6", + "pdca7", + "pdca8", + "pdca9", + "pdca10", + "pdca11", + "pdca12", + "pdca13", + "pdca14", + "pdca15", + "crccu", + "usbc", + "pevc_tr", + "pevc_ov", + "aesa", + "pm", + "scim", + "freqm", + "gpio0", + "gpio1", + "gpio2", + "gpio3", + "gpio4", + "gpio5", + "gpio6", + "gpio7", + "gpio8", + "gpio9", + "gpio10", + "gpio11", + "bpm", + "bscif", + "ast_alarm", + "ast_per", + "ast_ovf", + "ast_ready", + "ast_clkready", + "wdt", + "eic1", + "eic2", + "eic3", + "eic4", + "eic5", + "eic6", + "eic7", + "eic8", + "iisc", + "spi", + "tc00", + "tc01", + "tc02", + "tc10", + "tc11", + "tc12", + "twim0", + "twis0", + "twim1", + "twis1", + "usart0", + "usart1", + "usart2", + "usart3", + "adcife", + "dacc", + "acifc", + "abdacb", + "trng", + "parc", + "catb", + "reserved0", + "twim2", + "twim3", + "lcdca" + ], + "partname_humanreadable": "Atmel SAM4L series", + "partname_doxygen": "SAM4L", + "includeguard": "LIBOPENCM3_SAM4L_NVIC_H" +} diff --git a/include/libopencm3/sam/4l/memorymap.h b/include/libopencm3/sam/4l/memorymap.h new file mode 100644 index 00000000..807f3f02 --- /dev/null +++ b/include/libopencm3/sam/4l/memorymap.h @@ -0,0 +1,86 @@ +/* + * This file is part of the libopencm3 project. + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#ifndef SAM4L_MEMORYMAP_H +#define SAM4L_MEMORYMAP_H + +#include + +#define PERIPH_BASE (0x40000000U) + +/* --- SAM4L peripheral bridge A -------------------------------------------- */ +#define PERIPH_PBA_BASE PERIPH_BASE +/* (PERIPH_PBA_BASE + 0x4000) RESERVED */ +#define I2SC_BASE (PERIPH_PBA_BASE + 0x04000) +#define SPI_BASE (PERIPH_PBA_BASE + 0x08000) +/* (PERIPH_PBA_BASE + 0x0C000) RESERVED */ +#define TC0_BASE (PERIPH_PBA_BASE + 0x10000) +#define TC1_BASE (PERIPH_PBA_BASE + 0x14000) +#define TWIMS0_BASE (PERIPH_PBA_BASE + 0x18000) +#define TWIMS1_BASE (PERIPH_PBA_BASE + 0x1C000) +/* (PERIPH_PBA_BASE + 0x20000) RESERVED */ +#define USART0_BASE (PERIPH_PBA_BASE + 0x24000) +#define USART1_BASE (PERIPH_PBA_BASE + 0x28000 +#define USART2_BASE (PERIPH_PBA_BASE + 0x2C000) +#define USART3_BASE (PERIPH_PBA_BASE + 0x30000) +/* (PERIPH_PBA_BASE + 0x34000) RESERVED */ +#define ADCIFE_BASE (PERIPH_PBA_BASE + 0x38000) +#define DACC_BASE (PERIPH_PBA_BASE + 0x3C000) +#define ACIFC_BASE (PERIPH_PBA_BASE + 0x40000) +/* (PERIPH_PBA_BASE + 0x44000) to (PERIPH_PBA_BASE + 0x5C000) RESERVED */ +#define GLOC_BASE (PERIPH_PBA_BASE + 0x60000) +#define ABDACB_BASE (PERIPH_PBA_BASE + 0x64000) +#define TRNG_BASE (PERIPH_PBA_BASE + 0x68000) +#define PARC_BASE (PERIPH_PBA_BASE + 0x6C000) +#define CATB_BASE (PERIPH_PBA_BASE + 0x70000) +/* (PERIPH_PBA_BASE + 0x74000) RESERVED */ +#define TWIM2_BASE (PERIPH_PBA_BASE + 0x78000) +#define TWIM3_BASE (PERIPH_PBA_BASE + 0x7C000) +#define LCDCA_BASE (PERIPH_PBA_BASE + 0x80000) + +/* --- SAM4L peripheral bridge B -------------------------------------------- */ +#define PERIPH_PBB_BASE (PERIPH_BASE + 0xA0000U) +#define FLASHCALW_BASE (PERIPH_PBB_BASE) +#define PICOCACHE_BASE (PERIPH_PBB_BASE + 0x400) +#define HMATRIX_BASE (PERIPH_PBB_BASE + 0x1000) +#define PDCA_BASE (PERIPH_PBB_BASE + 0x2000) +#define SMAP_BASE (PERIPH_PBB_BASE + 0x3000) +#define CRCCU_BASE (PERIPH_PBB_BASE + 0x4000) +#define USBC_BASE (PERIPH_PBB_BASE + 0x5000) +#define PEVC_BASE (PERIPH_PBB_BASE + 0x6000) + +/* --------- Advanced Encryption Standard (AESA) ------------- */ +#define AESA_BASE (PERIPH_BASE + 0xB0000) + +/* --- SAM4L peripheral bridge C -------------------------------------------- */ +#define PERIPH_PBC_BASE (PERIPH_BASE + 0xE0000) +#define PM_BASE (PERIPH_PBC_BASE) +#define CHIPID_BASE (PERIPH_PBC_BASE + 0x740) +#define SCIF_BASE (PERIPH_PBC_BASE + 0x800) +#define FREQM_BASE (PERIPH_PBC_BASE + 0xC00) +#define GPIO_BASE (PERIPH_PBC_BASE + 0x1000) + +/* --- SAM4L peripheral bridge D -------------------------------------------- */ +#define PERIPH_PBD_BASE (PERIPH_BASE + 0xF0000U) +#define BPM_BASE (PERIPH_PBD_BASE) +#define BSCIF_BASE (PERIPH_PBD_BASE + 0x400) +#define AST_BASE (PERIPH_PBD_BASE + 0x800) +#define WDT_BASE (PERIPH_PBD_BASE + 0xC00) +#define EIC_BASE (PERIPH_PBD_BASE + 0x1000) +#define PICOUART_BASE (PERIPH_PBD_BASE + 0x1400) + +#endif diff --git a/include/libopencm3/sam/4l/pm.h b/include/libopencm3/sam/4l/pm.h new file mode 100644 index 00000000..fb7224d9 --- /dev/null +++ b/include/libopencm3/sam/4l/pm.h @@ -0,0 +1,278 @@ +/* + * This file is part of the libopencm3 project. + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#ifndef LIBOPENCM3_PM_H +#define LIBOPENCM3_PM_H + +#include + +/* --- Power Manager (PM) registers ----------------------- */ + +/* Main Clock Control MCCTRL Read/Write */ +#define PM_MCCTRL MMIO32(PM_BASE + 0x000) +#define PM_MCCTRL_KEY (PM_UNLOCK_KEY) + +/* CPU & PBx Clock Select, Read/Write */ +#define PM_CKSEL(I) MMIO32(PM_BASE + 0x004 + (0x004 * (I))) +#define PM_CKSEL_KEY(I) (PM_UNLOCK_KEY | (0x004 + (0x004 * (I)))) + +#define PM_MASK(I) MMIO32(PM_BASE + 0x020 + (0x004) * (I)) +#define PM_MASK_KEY(I) (PM_UNLOCK_KEY | (0x020 + (0x004) * (I))) + +/* CPU Mask CPUMASK Read/Write */ +#define PM_CPUMASK MMIO32(PM_BASE + 0x020) + +/* HSB Mask HSBMASK Read/Write */ +#define PM_HSBMASK MMIO32(PM_BASE + 0x024) + +/* PBA Mask PBAMASK Read/Write */ +#define PM_PBAMASK MMIO32(PM_BASE + 0x028) +#define PM_PBAMASK_KEY (PM_UNLOCK_KEY | 0x028) + +/* PBB Mask PBBMASK Read/Write */ +#define PM_PBBMASK MMIO32(PM_BASE + 0x02C) + +/* PBC Mask PBCMASK Read/Write */ +#define PM_PBCMASK MMIO32(PM_BASE + 0x030) + +/* PBD Mask PBDMASK Read/Write */ +#define PM_PBDMASK MMIO32(PM_BASE + 0x034) + +/* PBA Divided Mask PBADIVMASK Read/Write */ +#define PM_PBADIVMASK MMIO32(PM_BASE + 0x040) +#define PM_PBADIVMASK_KEY (PM_UNLOCK_KEY | 0x040) + +/* Clock Failure Detector Control CFDCTRL Read/Write */ +#define PM_CFDCTRL MMIO32(PM_BASE + 0x054) + +/* Unlock Register UNLOCK Write-only */ +#define PM_UNLOCK MMIO32(PM_BASE + 0x058) +#define PM_UNLOCK_KEY (0xAA << 24) + +/* Interrupt Enable Register IER Write-only */ +#define PM_IER MMIO32(PM_BASE + 0x0C0) + +/* Interrupt Disable Register IDR Write-only */ +#define PM_IDR MMIO32(PM_BASE + 0x0C4) + +/* Interrupt Mask Register IMR Read-only */ +#define PM_IMR MMIO32(PM_BASE + 0x0C8) + +/* Interrupt Status Register ISR Read-only */ +#define PM_ISR MMIO32(PM_BASE + 0x0CC) + +/* Interrupt Clear Register ICR Write-only */ +#define PM_ICR MMIO32(PM_BASE + 0x0D0) + +/* Status Register SR Read-only */ +#define PM_SR MMIO32(PM_BASE + 0x0D4) + +/* Peripheral Power Control Register PPCR Read/Write */ +#define PM_PPCR MMIO32(PM_BASE + 0x160) + +/* Reset Cause Register RCAUSE Read-only */ +#define PM_RCAUSE MMIO32(PM_BASE + 0x180) + +/* Wake Cause Register WCAUSE Read-only */ +#define PM_WCAUSE MMIO32(PM_BASE + 0x184) + +/* Asynchronous Wake Enable AWEN Read/Write */ +#define PM_AWEN MMIO32(PM_BASE + 0x188) + +/* Protection Control Register PROTCTRL Read/Write */ +#define PM_PROTCTRL MMIO32(PM_BASE + 0x18C) + +/* Fast Sleep Register FASTSLEEP Read/Write */ +#define PM_FASTSLEEP MMIO32(PM_BASE + 0x194) + +/* Configuration Register CONFIG Read-only */ +#define PM_CONFIG MMIO32(PM_BASE + 0x3F8) + +/* Version Register VERSION Read-only */ +#define PM_VERSION MMIO32(PM_BASE + 0x3FC) + + +/* --- Register contents --------------------------------------------------- */ +#define PM_MCCTRL_MCSEL_SHIFT 0 +#define PM_MCCTRL_MCSEL_MASK 3 + +// Values common for CPUSEL and PBxSEL +#define PM_CKSEL_DIV (1 << 7) +#define PM_CKSEL_MASK (3) + +#define PM_CPUMASK_OSC (1 << 0) + +#define PM_HSBMASK_PDCA (1 << 0) +#define PM_HSBMASK_FLASHCALW (1 << 1) +#define PM_HSBMASK_FLASHCALW_PICO (1 << 2) +#define PM_HSBMASK_USBC (1 << 3) +#define PM_HSBMASK_CRCCU (1 << 4) +#define PM_HSBMASK_APBA (1 << 5) +#define PM_HSBMASK_APBB (1 << 6) +#define PM_HSBMASK_APBC (1 << 7) +#define PM_HSBMASK_APBD (1 << 8) +#define PM_HSBMASK_AESA (1 << 9) + +#define PM_PBAMASK_IISC (1 << 0) +#define PM_PBAMASK_SPI (1 << 1) +#define PM_PBAMASK_TC0 (1 << 2) +#define PM_PBAMASK_TC1 (1 << 3) +#define PM_PBAMASK_TWIM0 (1 << 4) +#define PM_PBAMASK_TWIS0 (1 << 5) +#define PM_PBAMASK_TWIM1 (1 << 6) +#define PM_PBAMASK_TWIS1 (1 << 7) +#define PM_PBAMASK_USART0 (1 << 8) +#define PM_PBAMASK_USART1 (1 << 9) +#define PM_PBAMASK_USART2 (1 << 10) +#define PM_PBAMASK_USART3 (1 << 11) +#define PM_PBAMASK_ADCIFE (1 << 12) +#define PM_PBAMASK_DACC (1 << 13) +#define PM_PBAMASK_ACIFC (1 << 14) +#define PM_PBAMASK_GLOC (1 << 15) +#define PM_PBAMASK_ABDACB (1 << 16) +#define PM_PBAMASK_TRNG (1 << 17) +#define PM_PBAMASK_PARC (1 << 18) +#define PM_PBAMASK_CATB (1 << 19) +/* -- */ +#define PM_PBAMASK_TWIM2 (1 << 21) +#define PM_PBAMASK_TWIM3 (1 << 22) +#define PM_PBAMASK_LCDCA (1 << 23) + +#define PM_PBBMASK_FLASHCALW (1 << 0) +#define PM_PBBMASK_HRAMC1 (1 << 1) +#define PM_PBBMASK_HMATRIX (1 << 2) +#define PM_PBBMASK_PDCA (1 << 3) +#define PM_PBBMASK_CRCCU (1 << 4) +#define PM_PBBMASK_USBC (1 << 5) +#define PM_PBBMASK_PEVC (1 << 6) + +#define PM_PBCMASK_PM (1 << 0) +#define PM_PBCMASK_CHIPID (1 << 1) +#define PM_PBCMASK_SCIF (1 << 2) +#define PM_PBCMASK_FREQM (1 << 3) +#define PM_PBCMASK_GPIO (1 << 4) + +#define PM_PBDMASK_BPM (1 << 0) +#define PM_PBDMASK_BSCIF (1 << 1) +#define PM_PBDMASK_AST (1 << 2) +#define PM_PBDMASK_WDT (1 << 3) +#define PM_PBDMASK_EIC (1 << 4) +#define PM_PBDMASK_PICOUART (1 << 5) + +#define PM_PBADIVMASK_TC2 (1 << 0) +#define PM_PBADIVMASK_USART0 (1 << 2) +#define PM_PBADIVMASK_USART1 (1 << 2) +#define PM_PBADIVMASK_USART2 (1 << 2) +#define PM_PBADIVMASK_USART3 (1 << 2) +#define PM_PBADIVMASK_TC3 (1 << 2) +#define PM_PBADIVMASK_TC4 (1 << 4) +#define PM_PBADIVMASK_TC5 (1 << 6) + +#define PM_SR_CFD (1 << 0) +#define PM_SR_CKRDY (1 << 5) +#define PM_SR_WAKE (1 << 8) + +enum mck_src { + MCK_SRC_RCSYS = 0, + MCK_SRC_OSC0, + MCK_SRC_PLL, + MCK_SRC_DFLL, + MCK_SRC_RC80M, + MCK_SRC_RCFAST, + MCK_SRC_RC1M, +}; + +enum pm_cksel { + PM_CKSEL_CPU = 0, + PM_CKSEL_PBA = 2, + PM_CKSEL_PBB, + PM_CKSEL_PBC, + PM_CKSEL_PBD, +}; + +/* + * Ids are designed such that + * PM_MASK(id/32) = (1 << id % 32) + * would enable the peripheral clock. + */ +enum pm_peripheral { + PM_PERIPHERAL_OCD = 0, + PM_PERIPHERAL_PDCA = 32, + PM_PERIPHERAL_FLASHCALW, + PM_PERIPHERAL_FLASHCALW_PICORAM, + PM_PERIPHERAL_USBC, + PM_PERIPHERAL_CRCCU, + PM_PERIPHERAL_APBA_BRIDGE, + PM_PERIPHERAL_APBB_BRIDGE, + PM_PERIPHERAL_APBC_BRIDGE, + PM_PERIPHERAL_APBD_BRIDGE, + PM_PERIPHERAL_AESA, + PM_PERIPHERAL_IISC = 64, + PM_PERIPHERAL_SPI, + PM_PERIPHERAL_TC0, + PM_PERIPHERAL_TC1, + PM_PERIPHERAL_TWIM0, + PM_PERIPHERAL_TWIS0, + PM_PERIPHERAL_TWIM1, + PM_PERIPHERAL_TWIS1, + PM_PERIPHERAL_USART0, + PM_PERIPHERAL_USART1, + PM_PERIPHERAL_USART2, + PM_PERIPHERAL_USART3, + PM_PERIPHERAL_ADCIFE, + PM_PERIPHERAL_DACC, + PM_PERIPHERAL_ACIFC, + PM_PERIPHERAL_GLOC, + PM_PERIPHERAL_ABDACB, + PM_PERIPHERAL_TRNG, + PM_PERIPHERAL_PARC, + PM_PERIPHERAL_CATB, + PM_PERIPHERAL_RESERVED1, + PM_PERIPHERAL_TWIM2, + PM_PERIPHERAL_TWIM3, + PM_PERIPHERAL_LCDCA, + PM_PERIPHERAL_FLASHCALW_ALT = 96, + PM_PERIPHERAL_HRAMC1, + PM_PERIPHERAL_HMATRIX, + PM_PERIPHERAL_PDCA_ALT, + PM_PERIPHERAL_CRCCU_ALT, + PM_PERIPHERAL_USBC_ALT, + PM_PERIPHERAL_PEVC, + PM_PERIPHERAL_PM = 128, + PM_PERIPHERAL_CHIPID, + PM_PERIPHERAL_SCIF, + PM_PERIPHERAL_FREQM, + PM_PERIPHERAL_GPIO, + PM_PERIPHERAL_BPM = 160, + PM_PERIPHERAL_BSCIF, + PM_PERIPHERAL_AST, + PM_PERIPHERAL_WDT, + PM_PERIPHERAL_EIC, + PM_PERIPHERAL_PICOUART, +}; + +BEGIN_DECLS + +void pm_select_main_clock(enum mck_src source_clock); +void pm_enable_clock_div(enum pm_cksel sel_target, uint8_t div); +void pm_set_divmask_clock(uint8_t mask); +void pm_enable_peripheral_clock(enum pm_peripheral periph); +void pm_disable_peripheral_clock(enum pm_peripheral periph); + +END_DECLS + +#endif diff --git a/include/libopencm3/sam/4l/scif.h b/include/libopencm3/sam/4l/scif.h new file mode 100644 index 00000000..416837bb --- /dev/null +++ b/include/libopencm3/sam/4l/scif.h @@ -0,0 +1,328 @@ +/* + * This file is part of the libopencm3 project. + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#ifndef LIBOPENCM3_SCIF_H +#define LIBOPENCM3_SCIF_H + +#include +#include + +/* ------------ SCIF Registers ------------------------------ */ + +/* Interrupt Enable Register IER Write Only */ +#define SCIF_IER MMIO32(SCIF_BASE) + +/* Interrupt Disable Register IDR Write Only */ +#define SCIF_IDR MMIO32(SCIF_BASE + 0x0004) + +/* Interrupt Mask Register IMR Read Only */ +#define SCIF_IMR MMIO32(SCIF_BASE + 0x0008) + +/* Interrupt Status Register ISR Read Only */ +#define SCIF_ISR MMIO32(SCIF_BASE + 0x000C) + +/* Interrupt Clear Register ICR Write Only */ +#define SCIF_ICR MMIO32(SCIF_BASE + 0x0010) + +/* Power and Clocks Status Register PCLKSR Read Only */ +#define SCIF_PCLKSR MMIO32(SCIF_BASE + 0x0014) + +/* Unlock Register UNLOCK Write Only */ +#define SCIF_UNLOCK MMIO32(SCIF_BASE + 0x0018) +#define SCIF_UNLOCK_KEY (0xaa << 24) + +/* Chip Specific Configuration Register CSCR Read/Write */ +#define SCIF_CSCR MMIO32(SCIF_BASE + 0x001C) + +/* Oscillator Control Register OSCCTRL0 Read/Write */ +#define SCIF_OSCCTRL0 MMIO32(SCIF_BASE + 0x0020) +#define SCIF_OSCCTRL0_KEY (SCIF_UNLOCK_KEY | 0x0020) + +/* PLL0 Control Register PLL0 Read/Write */ +#define SCIF_PLL0 MMIO32(SCIF_BASE + 0x0024) +#define SCIF_PLL0_KEY (SCIF_UNLOCK_KEY | 0x0024) + +/* DFLL0 Config Register DFLL0CONF Read/Write */ +#define SCIF_DFLL0CONF MMIO32(SCIF_BASE + 0x0028) + +/* DFLL Value Register DFLL0VAL Read/Write */ +#define SCIF_DFLL0VAL MMIO32(SCIF_BASE + 0x002C) + +/* DFLL0 Multiplier Register DFLL0MUL Read/Write */ +#define SCIF_DFLL0MUL MMIO32(SCIF_BASE + 0x0030) + +/* DFLL0 Step Register DFLL0STEP Read/Write */ +#define SCIF_DFLL0STEP MMIO32(SCIF_BASE + 0x0034) + +/* DFLL0 Spread Spectrum Generator Control Register DFLL0SSG Read/Write */ +#define SCIF_DFLL0SSG MMIO32(SCIF_BASE + 0x0038) + +/* DFLL0 Ratio Register DFLL0RATIO Read Only */ +#define SCIF_DFLL0RATIO MMIO32(SCIF_BASE + 0x003C) + +/* DFLL0 Synchronization Register DFLL0SYNC Write Only */ +#define SCIF_DFLL0SYNC MMIO32(SCIF_BASE + 0x0040) + +/* System RC Oscillator Calibration Register RCCR Read/Write */ +#define SCIF_RCCR MMIO32(SCIF_BASE + 0x0044) + +/* 4/8/12MHz RC Oscillator Configuration Register RCFASTCFG Read/Write */ +#define SCIF_RCFASTCFG MMIO32(SCIF_BASE + 0x0048) + +/* 4/8/12MHz RC Oscillator Status Register RCFASTSR Read Only */ +#define SCIF_RCFASTSR MMIO32(SCIF_BASE + 0x004C) + +/* 80MHz RC Oscillator Register RC80MCR Read/Write */ +#define SCIF_RC80MCR MMIO32(SCIF_BASE + 0x0050) + +/* High Resolution Prescaler Control Register HRPCR Read/Write */ +#define SCIF_HPPCR MMIO32(SCIF_BASE + 0x0064) + +/* Fractional Prescaler Control Register FPCR Read/Write */ +#define SCIF_FPCR MMIO32(SCIF_BASE + 0x0068) + +/* Fractional Prescaler Multiplier Register FPMUL Read/Write */ +#define SCIF_FPMUL MMIO32(SCIF_BASE + 0x006C) + +/* Fractional Prescaler DIVIDER Register FPDIV Read/Write */ +#define SCIF_FPDIV MMIO32(SCIF_BASE + 0x006C) + +/* Generic Clock Control1 GCCTRL0 Read/Write */ +#define SCIF_GCCTRL0 MMIO32(SCIF_BASE + 0x0074) + +/* Generic Clock Control1 GCCTRL1 Read/Write */ +#define SCIF_GCCTRL1 MMIO32(SCIF_BASE + 0x0078) + +/* Generic Clock Control2 GCCTRL2 Read/Write */ +#define SCIF_GCCTRL2 MMIO32(SCIF_BASE + 0x007C) + +/* Generic Clock Control3 GCCTRL3 Read/Write */ +#define SCIF_GCCTRL3 MMIO32(SCIF_BASE + 0x0080) + +/* Generic Clock Control4 GCCTRL4 Read/Write */ +#define SCIF_GCCTRL4 MMIO32(SCIF_BASE + 0x0084) + +/* Generic Clock Control5 GCCTRL5 Read/Write */ +#define SCIF_GCCTRL5 MMIO32(SCIF_BASE + 0x0088) + +/* Generic Clock Control6 GCCTRL6 Read/Write */ +#define SCIF_GCCTRL6 MMIO32(SCIF_BASE + 0x008C) + +/* Generic Clock Control7 GCCTRL7 Read/Write */ +#define SCIF_GCCTRL7 MMIO32(SCIF_BASE + 0x0090) + +/* Generic Clock Control8 GCCTRL8 Read/Write */ +#define SCIF_GCCTRL8 MMIO32(SCIF_BASE + 0x0094) + +/* Generic Clock Control9 GCCTRL9 Read/Write */ +#define SCIF_GCCTRL9 MMIO32(SCIF_BASE + 0x0098) + +/* Generic Clock Control10 GCCTRL10 Read/Write */ +#define SCIF_GCCTRL10 MMIO32(SCIF_BASE + 0x009C) + +/* Generic Clock Control11 GCCTRL11 Read/Write */ +#define SCIF_GCCTRL11 MMIO32(SCIF_BASE + 0x00A0) + +#define SCIF_GCTRL(N) MMIO32(SCIF_BASE + 0x0074 + 0x0004 * (N)) +#define SCIF_GCLK_MAX_NUM 11 + +/* 4/8/12MHz RC Oscillator Version Register RCFASTVERSION Read-only */ +#define SCIF_RCFASTVERSION MMIO32(SCIF_BASE + 0x03D8) + +/* Generic Clock Prescaler Version Register GCLKPRESCVERSION Read-only */ +#define SCIF_GCLKPRESCVERSION MMIO32(SCIF_BASE + 0x03DC) + +/* PLL Version Register PLLIFAVERSION Read-only */ +#define SCIF_PLLIFAVERSION MMIO32(SCIF_BASE + 0x03E0) + +/* Oscillator0 Version Register OSCIFAVERSION Read-only */ +#define SCIF_OSCIFAVERSION MMIO32(SCIF_BASE + 0x03E4) + +/* DFLL Version Register DFLLIFBVERSION Read-only */ +#define SCIF_DFLLIFBVERSION MMIO32(SCIF_BASE + 0x03E8) + +/* System RC Oscillator Version Register RCOSCIFAVERSION Read-only */ +#define SCIF_RCOSCIFAVERSION MMIO32(SCIF_BASE + 0x03EC) + +/* 80MHz RC Oscillator Version Register RC80MVERSION Read-only */ +#define SCIF_RC80MVERSION MMIO32(SCIF_BASE + 0x03F4) + +/* Generic Clock Version Register GCLKVERSION Read-only */ +#define SCIF_GCLKVERSION MMIO32(SCIF_BASE + 0x03F8) + +/* SCIF Version Register VERSION Read-Only */ +#define SCIF_VERSION MMIO32(SCIF_BASE + 0x03FC) + + +/* ---------------- SCIF Registers' Contents ------------------- */ + +/* Interrupt Enable/Disable/Mask/Status/Clear registers and PCLKSR + * have the same bit configuration */ +#define SCIF_OSC0RDY (1 << 0) +#define SCIF_DFLL0LOCKC (1 << 1) +#define SCIF_DFLL0LOCKF (1 << 2) +#define SCIF_DFLL0RDY (1 << 3) +#define SCIF_DFLL0RCS (1 << 4) +#define SCIF_PLL0LOCK (1 << 6) +#define SCIF_PLL0LOCKLOST (1 << 7) +#define SCIF_RCFASTLOCK (1 << 13) +#define SCIF_RCFASTLOCKLOST (1 << 14) + +#define SCIF_OSCCTRL_MODE (1 << 0) +#define SCIF_OSCCTRL_GAIN_SHIFT 1 +#define SCIF_OSCCTRL_GAIN_MASK (3 << SCIF_OSCCTRL_GAIN_SHIFT) +#define SCIF_OSCCTRL_AGC (1 << 3) +#define SCIF_OSCCTRL_STARTUP_SHIFT 8 +#define SCIF_OSCCTRL_STARTUP_MASK (0xf << SCIF_OSCCTRL_STARTUP_SHIFT) +#define SCIF_OSCCTRL_OSCEN (1 << 16) + +#define _MASKED_VALUE(V, S, M) (((V) << (S)) & (M)) + +#define SCIF_PLL0_PLLEN (1 << 0) +#define SCIF_PLL0_PLLOSC_SHIFT 1 +#define SCIF_PLL0_PLLOSC_MASK (3 << SCIF_PLL0_PLLOSC_SHIFT) +#define SCIF_PLL0_PLLOSC_MASKED(V) _MASKED_VALUE((V), SCIF_PLL0_PLLOSC_SHIFT, SCIF_PLL0_PLLOSC_MASK) + +#define SCIF_PLL0_PLLOPT_SHIFT 3 +#define SCIF_PLL0_PLLOPT_MASK (7 << SCIF_PLL0_PLLOPT_SHIFT) +#define SCIF_PLL0_PLLOPT_MASKED(V) _MASKED_VALUE((V), SCIF_PLL0_PLLOPT_SHIFT, SCIF_PLL0_PLLOPT_MASK) + +#define SCIF_PLL0_PLLDIV_SHIFT 8 +#define SCIF_PLL0_PLLDIV_MASK (0xf << SCIF_PLL0_PLLDIV_SHIFT) +#define SCIF_PLL0_PLLDIV_MASKED(V) _MASKED_VALUE((V), SCIF_PLL0_PLLDIV_SHIFT, SCIF_PLL0_PLLDIV_MASK) + +#define SCIF_PLL0_PLLMUL_SHIFT 16 +#define SCIF_PLL0_PLLMUL_MASK (0xf << SCIF_PLL0_PLLMUL_SHIFT) +#define SCIF_PLL0_PLLMUL_MASKED(V) _MASKED_VALUE((V), SCIF_PLL0_PLLMUL_SHIFT, SCIF_PLL0_PLLMUL_MASK) + +#define SCIF_PLL0_PLLCOUNT_SHIFT 24 +#define SCIF_PLL0_PLLCOUNT_MASK (0x3f << SCIF_PLL0_PLLCOUNT_SHIFT) +#define SCIF_PLL0_PLLCOUNT_MASKED(V) _MASKED_VALUE((V), SCIF_PLL0_PLLCOUNT_SHIFT, SCIF_PLL0_PLLCOUNT_MASK) + + +#define SCIF_GCCTRL_CEN (1 << 0) +#define SCIF_GCCTRL_DIVEN (1 << 1) +#define SCIF_GCCTRL_OSCSEL_SHIFT 8 +#define SCIF_GCCTRL_OSCSEL_MASK (0x1f << SCIF_GCCTRL_OSCSEL_SHIFT) +#define SCIF_GCCTRL_OSCSEL_MASKED(V) _MASKED_VALUE(V, SCIF_GCCTRL_OSCSEL_SHIFT, SCIF_GCCTRL_OSCSEL_MASK) +#define SCIF_GCCTRL_DIV_SHIFT 16 +#define SCIF_GCCTRL_DIV_MASK (0xffff << SCIF_GCCTRL_DIV_SHIFT) +#define SCIF_GCCTRL_DIV_MASKED(V) _MASKED_VALUE(V, SCIF_GCCTRL_DIV_SHIFT, SCIF_GCCTRL_DIV_MASK) + + +enum osc_mode { + OSC_MODE_XIN = 0, + OSC_MODE_XIN_XOUT, +}; + +enum osc_startup { + OSC_STARTUP_0 = 0, + OSC_STARTUP_4 = 8, + OSC_STARTUP_8 = 9, + OSC_STARTUP_16 = 10, + OSC_STARTUP_32 = 11, + OSC_STARTUP_64 = 1, + OSC_STARTUP_128 = 2, + OSC_STARTUP_256 = 12, + OSC_STARTUP_512 = 13, + OSC_STARTUP_1K = 14, + OSC_STARTUP_2K = 3, + OSC_STARTUP_4K = 4, + OSC_STARTUP_8K = 5, + OSC_STARTUP_16K = 6, + OSC_STARTUP_32K = 7, +}; + +enum pll_clk_src { + PLL_CLK_SRC_OSC0 = 0, + PLL_CLK_SRC_GCLK9, +}; + +/* Generic Clock Source + * 0 RCSYS System RC oscillator clock + * 1 OSC32K Output clock from OSC32K + * 2 DFLL0 Output clock from DFLL0 + * 3 OSC0 Output clock from Oscillator0 + * 4 RC80M Output from 80MHz RCOSC + * 5 RCFAST Output from 4,8,12MHz RCFAST + * 6 RC1M Output from 1MHz RC1M + * 7 CLK_CPU The clock the CPU runs on + * 8 CLK_HSB High Speed Bus clock + * 9 CLK_PBA Peripheral Bus A clock + * 10 CLK_PBB Peripheral Bus B clock + * 11 CLK_PBC Peripheral Bus C clock + * 12 CLK_PBD Peripheral Bus D clock + * 13 RC32K Output from 32kHz RCOSC + * 14 Reserved + * 15 CLK_1K 1kHz output clock from OSC32K + * 16 PLL0 Output clock from PLL0 + * 17 HRP High Resolution Prescaler Output + * 18 FP Fractionnal Prescaler Output + * 19-20 GCLK_IN[0-1] GCLK_IN[0-1] pins, digital clock input + * 21 GCLK11 Generic Clock 11. Can not be use as input to itself. + */ +enum gclk_src { + GCLK_SRC_RCSYS, + GCLK_SRC_OSC32K, + GCLK_SRC_DFLL0, + GCLK_SRC_OSC0, + GCLK_SRC_RC80M, + GCLK_SRC_RCFAST, + GCLK_SRC_RC1M, + GCLK_SRC_CLK_CPU, + GCLK_SRC_CLK_HSB, + GCLK_SRC_CLK_PBA, + GCLK_SRC_CLK_PBB, + GCLK_SRC_CLK_PBC, + GCLK_SRC_CLK_PBD, + GCLK_SRC_RC32K, + GCLK_SRC_RESERVED_, + GCLK_SRC_CLK_1K, + GCLK_SRC_PLL0, + GCLK_SRC_HRP, + GCLK_SRC_FP, + GCLK_SRC_GCLK_IN0, + GCLK_SRC_GCLK_IN1, + GCLK_SRC_GCLK11, +}; + +enum generic_clock { + GENERIC_CLOCK0, + GENERIC_CLOCK1, + GENERIC_CLOCK2, + GENERIC_CLOCK3, + GENERIC_CLOCK4, + GENERIC_CLOCK5, + GENERIC_CLOCK6, + GENERIC_CLOCK7, + GENERIC_CLOCK8, + GENERIC_CLOCK9, + GENERIC_CLOCK10, + GENERIC_CLOCK_ADCIFE = GENERIC_CLOCK10, + GENERIC_CLOCK11, +}; + +BEGIN_DECLS + +int scif_osc_enable(enum osc_mode mode, uint32_t freq, enum osc_startup startup); +int scif_enable_pll(uint8_t delay, uint8_t mul, uint8_t div, uint8_t pll_opt, enum pll_clk_src source_clock); +void scif_enable_gclk(enum generic_clock gclk, enum gclk_src source_clock, uint16_t div); + +END_DECLS + + +#endif /* LIBOPENCM3_SCIF_H */ diff --git a/include/libopencm3/sam/adcife.h b/include/libopencm3/sam/adcife.h new file mode 100644 index 00000000..805e5be7 --- /dev/null +++ b/include/libopencm3/sam/adcife.h @@ -0,0 +1,27 @@ +/* + * This file is part of the libopencm3 project. + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#ifndef SAM_ADCIFE_H +#define SAM_ADCIFE_H + +#if defined(SAM4L) +# include +#else +# error "ADC interface is not defined for your processor family" +#endif + +#endif diff --git a/include/libopencm3/sam/common/gpio_common_all.h b/include/libopencm3/sam/common/gpio_common_all.h index 375e429c..5873b724 100644 --- a/include/libopencm3/sam/common/gpio_common_all.h +++ b/include/libopencm3/sam/common/gpio_common_all.h @@ -29,10 +29,13 @@ specific memorymap.h header before including this header file.*/ #include +BEGIN_DECLS + void gpio_set(uint32_t gpioport, uint32_t gpios); void gpio_clear(uint32_t gpioport, uint32_t gpios); void gpio_toggle(uint32_t gpioport, uint32_t gpios); +END_DECLS #endif diff --git a/include/libopencm3/sam/gpio.h b/include/libopencm3/sam/gpio.h index 79128987..852f6f58 100644 --- a/include/libopencm3/sam/gpio.h +++ b/include/libopencm3/sam/gpio.h @@ -29,6 +29,8 @@ # include #elif defined(SAM3X) # include +#elif defined(SAM4L) +# include #else # error "sam family not defined." #endif diff --git a/include/libopencm3/sam/memorymap.h b/include/libopencm3/sam/memorymap.h index 67f1def3..ad0bb4d9 100644 --- a/include/libopencm3/sam/memorymap.h +++ b/include/libopencm3/sam/memorymap.h @@ -31,6 +31,8 @@ # include #elif defined(SAM3X) # include +#elif defined(SAM4L) +# include #elif defined(SAMD) # include #else diff --git a/include/libopencm3/sam/pm.h b/include/libopencm3/sam/pm.h new file mode 100644 index 00000000..4db62789 --- /dev/null +++ b/include/libopencm3/sam/pm.h @@ -0,0 +1,24 @@ +/* This provides unification of code over SAM subfamilies */ + +/* + * This file is part of the libopencm3 project. + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#if defined(SAM4L) +# include +#else +# error "PM undefined for your processor family." +#endif diff --git a/include/libopencm3/sam/scif.h b/include/libopencm3/sam/scif.h new file mode 100644 index 00000000..d6ebbcd2 --- /dev/null +++ b/include/libopencm3/sam/scif.h @@ -0,0 +1,24 @@ +/* This provides unification of code over SAM subfamilies */ + +/* + * This file is part of the libopencm3 project. + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#if defined(SAM4L) +# include +#else +# error "SCIF undefined for your processor family." +#endif diff --git a/include/libopencm3/sam/usart.h b/include/libopencm3/sam/usart.h index 757e93dd..97a8ddb1 100644 --- a/include/libopencm3/sam/usart.h +++ b/include/libopencm3/sam/usart.h @@ -17,8 +17,8 @@ * along with this library. If not, see . */ -#ifndef SAM3X_USART_H -#define SAM3X_USART_H +#ifndef SAM_USART_H +#define SAM_USART_H #include #include @@ -43,7 +43,6 @@ /* 0x002C:0x003C - Reserved */ #define USART_FIDI(x) MMIO32((x) + 0x0040) #define USART_NER(x) MMIO32((x) + 0x0044) -#define USART_NER(x) MMIO32((x) + 0x0044) /* 0x0048 - Reserved */ #define USART_IF(x) MMIO32((x) + 0x004C) #define USART_MAN(x) MMIO32((x) + 0x0050) @@ -117,12 +116,14 @@ /* Bits [8:0] - Reserved */ #define USART_MR_SYNC (0x01 << 8) #define USART_MR_CPHA (0x01 << 8) -#define USART_MR_CHRL_MASK (0x03 << 6) -#define USART_MR_CHRL_5BIT (0x00 << 6) -#define USART_MR_CHRL_6BIT (0x01 << 6) -#define USART_MR_CHRL_7BIT (0x02 << 6) -#define USART_MR_CHRL_8BIT (0x03 << 6) -#define USART_MR_USCLKS_MASK (0x03 << 4) +#define USART_MR_CHRL_SHIFT (6) +#define USART_MR_CHRL_MASK (0x03 << USART_MR_CHRL_SHIFT) +#define USART_MR_CHRL_5BIT (0x00 << USART_MR_CHRL_SHIFT) +#define USART_MR_CHRL_6BIT (0x01 << USART_MR_CHRL_SHIFT) +#define USART_MR_CHRL_7BIT (0x02 << USART_MR_CHRL_SHIFT) +#define USART_MR_CHRL_8BIT (0x03 << USART_MR_CHRL_SHIFT) +#define USART_MR_USCLKS_SHIFT (4) +#define USART_MR_USCLKS_MASK (0x03 << USART_MR_USCLKS_SHIFT) #define USART_MR_USCLKS_MCK (0x00 << 4) #define USART_MR_USCLKS_DIV (0x01 << 4) #define USART_MR_USCLKS_SCK (0x03 << 4) @@ -169,6 +170,9 @@ #define USART_CSR_TXRDY (0x01 << 1) #define USART_CSR_RXRDY (0x01 << 0) +#define USART_WPMR_KEY (0x555341 << 8) +#define USART_WPMR_WPEN (0x01 << 0) + enum usart_stopbits { USART_STOPBITS_1, USART_STOPBITS_1_5, @@ -196,11 +200,27 @@ enum usart_flowcontrol { USART_FLOWCONTROL_RTS_CTS, }; +enum usart_clock { + USART_CLOCK_CLK_USART, + USART_CLOCK_CLK_USART_DIV, + USART_CLOCK_CLK = 3, +}; + +enum usart_chrl { + USART_CHRL_5BIT, + USART_CHRL_6BIT, + USART_CHRL_7BIT, + USART_CHRL_8BIT, +}; + +BEGIN_DECLS + void usart_set_baudrate(uint32_t usart, uint32_t baud); void usart_set_databits(uint32_t usart, int bits); void usart_set_stopbits(uint32_t usart, enum usart_stopbits); void usart_set_parity(uint32_t usart, enum usart_parity); void usart_set_mode(uint32_t usart, enum usart_mode); +void usart_set_character_length(uint32_t usart, enum usart_chrl chrl); void usart_set_flow_control(uint32_t usart, enum usart_flowcontrol); void usart_enable(uint32_t usart); void usart_disable(uint32_t usart); @@ -212,6 +232,11 @@ void usart_send_blocking(uint32_t usart, uint16_t data); uint16_t usart_recv_blocking(uint32_t usart); void usart_enable_rx_interrupt(uint32_t usart); void usart_disable_rx_interrupt(uint32_t usart); +void usart_wp_disable(uint32_t usart); +void usart_wp_enable(uint32_t usart); +void usart_select_clock(uint32_t usart, enum usart_clock clk); + +END_DECLS #endif diff --git a/ld/devices.data b/ld/devices.data index 3815e7a4..a2b95ac1 100644 --- a/ld/devices.data +++ b/ld/devices.data @@ -229,6 +229,13 @@ sam3x8e* sam3xnfc ROM=512K RAM=64K RAM1=32K samd10?13* samd ROM=8K RAM=4K samd10?14* samd ROM=16K RAM=4K +################################################################################ +# the SAM4 chips + +sam4l?8* sam4l ROM=512K RAM=64K RAM1=4K +sam4l?4* sam4l ROM=256K RAM=32K RAM1=4K +sam4l?2* sam4l ROM=128K RAM=32K RAM1=4K + ################################################################################ # the lpc chips @@ -460,6 +467,10 @@ sam3u END ROM_OFF=0x00080000 RAM_OFF=0x20000000 RAM1_OFF=0x20080000 NFCRAM=4K NF sam3x END ROM_OFF=0x00080000 RAM_OFF=0x20000000 RAM1_OFF=0x20080000 CPU=cortex-m3 FPU=soft samd END ROM_OFF=0x00000000 RAM_OFF=0x20000000 CPU=cortex-m0plus FPU=soft +################################################################################ +# the SAM4 families +sam4l END ROM_OFF=0x00000000 RAM_OFF=0x20000000 RAM1_OFF=0x21000000 + ################################################################################ # the lpc families diff --git a/lib/dispatch/vector_nvic.c b/lib/dispatch/vector_nvic.c index 22d5a82f..06cad5cb 100644 --- a/lib/dispatch/vector_nvic.c +++ b/lib/dispatch/vector_nvic.c @@ -47,6 +47,8 @@ # include "../sam/3u/vector_nvic.c" #elif defined(SAM3X) # include "../sam/3x/vector_nvic.c" +#elif defined(SAM4L) +# include "../sam/4l/vector_nvic.c" #elif defined(SAMD) # include "../sam/d/vector_nvic.c" diff --git a/lib/sam/3a/Makefile b/lib/sam/3a/Makefile index 7f24e228..5b9293d7 100644 --- a/lib/sam/3a/Makefile +++ b/lib/sam/3a/Makefile @@ -31,7 +31,7 @@ TGT_CFLAGS += $(DEBUG_FLAGS) TGT_CFLAGS += $(STANDARD_FLAGS) # ARFLAGS = rcsv ARFLAGS = rcs -OBJS = gpio_common_all.o gpio_common_3a3u3x.o pmc.o usart.o +OBJS = gpio_common_all.o gpio_common_3a3u3x.o pmc.o usart_common_all.o usart_common_3.o VPATH += ../../usb:../../cm3:../common diff --git a/lib/sam/3n/Makefile b/lib/sam/3n/Makefile index 815cf037..2baa2ee2 100644 --- a/lib/sam/3n/Makefile +++ b/lib/sam/3n/Makefile @@ -31,7 +31,7 @@ TGT_CFLAGS += $(DEBUG_FLAGS) TGT_CFLAGS += $(STANDARD_FLAGS) # ARFLAGS = rcsv ARFLAGS = rcs -OBJS = gpio_common_all.o gpio_common_3n3s.o pmc.o usart.o +OBJS = gpio_common_all.o gpio_common_3n3s.o pmc.o usart_common_all.o usart_common_3.o VPATH += ../../cm3:../common diff --git a/lib/sam/3s/Makefile b/lib/sam/3s/Makefile index d998bef1..4ec0b12b 100644 --- a/lib/sam/3s/Makefile +++ b/lib/sam/3s/Makefile @@ -32,7 +32,7 @@ TGT_CFLAGS += $(DEBUG_FLAGS) TGT_CFLAGS += $(STANDARD_FLAGS) # ARFLAGS = rcsv ARFLAGS = rcs -OBJS = gpio_common_all.o gpio_common_3n3s.o pmc.o usart.o +OBJS = gpio_common_all.o gpio_common_3n3s.o pmc.o usart_common_all.o usart_common_3.o VPATH += ../../usb:../../cm3:../common diff --git a/lib/sam/3u/Makefile b/lib/sam/3u/Makefile index f77bbd85..4b0ab0ce 100644 --- a/lib/sam/3u/Makefile +++ b/lib/sam/3u/Makefile @@ -32,7 +32,7 @@ TGT_CFLAGS += $(DEBUG_FLAGS) TGT_CFLAGS += $(STANDARD_FLAGS) # ARFLAGS = rcsv ARFLAGS = rcs -OBJS = gpio_common_all.o gpio_common_3a3u3x.o pmc.o usart.o +OBJS = gpio_common_all.o gpio_common_3a3u3x.o pmc.o usart_common_all.o usart_common_3.o VPATH += ../../usb:../../cm3:../common diff --git a/lib/sam/3x/Makefile b/lib/sam/3x/Makefile index 50b99900..c3dbc02d 100644 --- a/lib/sam/3x/Makefile +++ b/lib/sam/3x/Makefile @@ -31,7 +31,7 @@ TGT_CFLAGS += $(DEBUG_FLAGS) TGT_CFLAGS += $(STANDARD_FLAGS) # ARFLAGS = rcsv ARFLAGS = rcs -OBJS = gpio_common_all.o gpio_common_3a3u3x.o pmc.o usart.o +OBJS = gpio_common_all.o gpio_common_3a3u3x.o pmc.o usart_common_all.o usart_common_3.o VPATH += ../../usb:../../cm3:../common diff --git a/lib/sam/4l/Makefile b/lib/sam/4l/Makefile new file mode 100644 index 00000000..42a507f0 --- /dev/null +++ b/lib/sam/4l/Makefile @@ -0,0 +1,37 @@ +## +## This file is part of the libopencm3 project. +## +## This library is free software: you can redistribute it and/or modify +## it under the terms of the GNU Lesser General Public License as published by +## the Free Software Foundation, either version 3 of the License, or +## (at your option) any later version. +## +## This library is distributed in the hope that it will be useful, +## but WITHOUT ANY WARRANTY; without even the implied warranty of +## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +## GNU Lesser General Public License for more details. +## +## You should have received a copy of the GNU Lesser General Public License +## along with this library. If not, see . +## + +LIBNAME = libopencm3_sam4l +SRCLIBDIR ?= ../.. + +PREFIX ?= arm-none-eabi +FP_FLAGS ?= -msoft-float + +CC = $(PREFIX)-gcc +AR = $(PREFIX)-ar +TGT_CFLAGS = -Os -Wall -Wextra -I../../../include -fno-common \ + -mcpu=cortex-m4 -mthumb $(FP_FLAGS) -Wstrict-prototypes \ + -ffunction-sections -fdata-sections -MD -DSAM4L +TGT_CFLAGS += $(DEBUG_FLAGS) +# ARFLAGS = rcsv +ARFLAGS = rcs +OBJS = adcife.o gpio.o scif.o pm.o usart_common_all.o usart.o + +VPATH += ../../usb:../../cm3:../common + +include ../../Makefile.include + diff --git a/lib/sam/4l/adcife.c b/lib/sam/4l/adcife.c new file mode 100644 index 00000000..8f30678e --- /dev/null +++ b/lib/sam/4l/adcife.c @@ -0,0 +1,121 @@ +/** @addtogroup scif + * + * @brief Access functions for the SAM4 Analog to Digital Converter Interface (ADCIFE) + * @ingroup SAM4 + * LGPL License Terms @ref lgpl_license + * @author @htmlonly © @endhtmlonly 2016 + * Maxim Sloyko + * + */ + +#include + +/** @brief Enable ADC interface. Must be done before any other configuration. + * + * This function does it synchronously and returns only when the interface is + * actually enabled. + */ +void adcife_enable_sync(void) +{ + ADCIFE_CR = ADCIFE_CR_EN; + while (!(ADCIFE_SR & ADCIFE_SR_EN)); +} + +void adcife_configure( + enum adcife_refsel ref, + enum adcife_speed speed, + enum adcife_clk clk, + enum adcife_prescal prescal) +{ + ADCIFE_CFG = ADCIFE_CFG_REFSEL_MASKED(ref) + | ADCIFE_CFG_SPEED_MASKED(speed) + | ADCIFE_CFG_PRESCAL_MASKED(prescal) + | clk; +} + +void adcife_select_channel(enum adcife_channel ad) +{ + ADCIFE_SEQCFG |= ADCIFE_SEQCFG_MUXPOS_MASKED(ad); +} + +void adcife_set_resolution(enum adcife_resolution res) +{ + if (ADCIFE_RESOLUTION_12BITS == res) { + ADCIFE_SEQCFG &= ~ADCIFE_SEQCFG_RES; + } else { + ADCIFE_SEQCFG |= ADCIFE_SEQCFG_RES; + } +} + +void adcife_select_trigger(enum adcife_trigger trig) +{ + ADCIFE_SEQCFG &= ~ADCIFE_SEQCFG_TRGSEL_MASK; + ADCIFE_SEQCFG |= ADCIFE_SEQCFG_TRGSEL_MASKED(trig); +} + +void adcife_set_gain(enum adcife_gain gain) +{ + ADCIFE_SEQCFG &= ~ADCIFE_SEQCFG_GAIN_MASK; + ADCIFE_SEQCFG |= ADCIFE_SEQCFG_GAIN_MASKED(gain); +} + +void adcife_set_bipolar(bool enable) +{ + if (enable) { + ADCIFE_SEQCFG |= ADCIFE_SEQCFG_BIPOLAR; + } else { + ADCIFE_SEQCFG &= ~ADCIFE_SEQCFG_BIPOLAR; + } +} + +void adcife_set_left_adjust(bool enable) +{ + if (enable) { + ADCIFE_SEQCFG |= ADCIFE_SEQCFG_HWLA; + } else { + ADCIFE_SEQCFG &= ~ADCIFE_SEQCFG_HWLA; + } +} + +void adcife_start_conversion(void) +{ + ADCIFE_CR = ADCIFE_CR_STRIG; +} + +void adcife_wait_conversion(void) +{ + while (!(ADCIFE_SR & ADCIFE_SR_SEOC)); + ADCIFE_SCR = ADCIFE_SR_SEOC; +} + +struct adcife_lcv adcife_get_lcv(void) +{ + struct adcife_lcv res; + res._lc_u.lcv = ADCIFE_LCV; + return res; +} + +void adcife_enable_interrupts(uint32_t imask) +{ + ADCIFE_IER = imask; +} + +void adcife_disable_interrupts(uint32_t imask) +{ + ADCIFE_IDR = imask; +} + +void adcife_timer_start(void) +{ + ADCIFE_CR = ADCIFE_CR_TSTART; +} + +void adcife_timer_stop(void) +{ + ADCIFE_CR = ADCIFE_CR_TSTOP; +} + +void adcife_timer_set_timeout(uint16_t timeout) +{ + ADCIFE_TIM = timeout; +} diff --git a/lib/sam/4l/gpio.c b/lib/sam/4l/gpio.c new file mode 100644 index 00000000..ba50ed19 --- /dev/null +++ b/lib/sam/4l/gpio.c @@ -0,0 +1,100 @@ +/** @addtogroup gpio_defines + * + * @brief Access functions for the SAM4 I/O Controller + * @ingroup SAM4_defines + * LGPL License Terms @ref lgpl_license + * @author @htmlonly © @endhtmlonly 2016 + * Maxim Sloyko + * + */ + +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2012 Gareth McMullin + * Copyright (C) 2014 Felix Held + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#include + +/** @brief Atomic set output + * + * @param[in] gpioport uint32_t: GPIO Port base address + * @param[in] gpios uint32_t + */ +void gpio_set(uint32_t gpioport, uint32_t gpios) +{ + GPIO_OVRS(gpioport) = gpios; +} + +/** @brief Atomic clear output + * + * @param[in] gpioport uint32_t: GPIO Port base address + * @param[in] gpios uint32_t + */ +void gpio_clear(uint32_t gpioport, uint32_t gpios) +{ + GPIO_OVRC(gpioport) = gpios; +} + +/** @brief Atomic toggle output + * + * @param[in] gpioport uint32_t: GPIO Port base address + * @param[in] gpios uint32_t + */ +void gpio_toggle(uint32_t gpioport, uint32_t gpios) +{ + GPIO_OVRT(gpioport) = gpios; +} + +/** @brief Enable output pins. + * + * Onlyc the ones where bits are set to "1" are touched, everything else + * remains in the old state. + * + * @param[in] gpioport uint32_t: GPIO Port base address + * @param[in] gpios uint32_t + * @param[in] mode enum gpio_mode GPIO mode. IN, OUT or peripheral function. + */ +void gpio_enable(uint32_t gpioport, uint32_t gpios, enum gpio_mode mode) +{ + if (mode < GPIO_MODE_IN) { + GPIO_GPERC(gpioport) = gpios; + uint8_t i = 0; + for (; i < 3; ++i, mode >>= 1) { + GPIO_PMR_SETVAL(gpioport, i, mode & 1) = gpios; + } + } else if (mode == GPIO_MODE_OUT) { + GPIO_GPERS(gpioport) = gpios; + GPIO_ODERS(gpioport) = gpios; + } else if (mode == GPIO_MODE_IN) { + GPIO_GPERS(gpioport) = gpios; + GPIO_ODERC(gpioport) = gpios; + } +} + +/** @brief Disable output pins. + * + * Onlyc the ones where bits are set to "1" are touched, everything else + * remains in the old state. + * + * @param[in] gpioport uint32_t: GPIO Port base address + * @param[in] gpios uint32_t + */ +void gpio_disable(uint32_t gpioport, uint32_t gpios) +{ + GPIO_GPERC(gpioport) = gpios; +} diff --git a/lib/sam/4l/libopencm3_sam4l.ld b/lib/sam/4l/libopencm3_sam4l.ld new file mode 100644 index 00000000..5dea121b --- /dev/null +++ b/lib/sam/4l/libopencm3_sam4l.ld @@ -0,0 +1,105 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2009 Uwe Hermann + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +/* Generic linker script for SAM4L targets using libopencm3. */ + +/* Memory regions must be defined in the ld script which includes this one. */ + +/* Enforce emmition of the vector table. */ +EXTERN (vector_table) + +/* Define the entry point of the output file. */ +ENTRY(reset_handler) + +/* Define sections. */ +SECTIONS +{ + .text : { + *(.vectors) /* Vector table */ + *(.text*) /* Program code */ + . = ALIGN(4); + *(.rodata*) /* Read-only data */ + . = ALIGN(4); + } >rom + + /* C++ Static constructors/destructors, also used for __attribute__ + * ((constructor)) and the likes */ + .preinit_array : { + . = ALIGN(4); + __preinit_array_start = .; + KEEP (*(.preinit_array)) + __preinit_array_end = .; + } >rom + .init_array : { + . = ALIGN(4); + __init_array_start = .; + KEEP (*(SORT(.init_array.*))) + KEEP (*(.init_array)) + __init_array_end = .; + } >rom + .fini_array : { + . = ALIGN(4); + __fini_array_start = .; + KEEP (*(.fini_array)) + KEEP (*(SORT(.fini_array.*))) + __fini_array_end = .; + } >rom + + /* + * Another section used by C++ stuff, appears when using newlib with + * 64bit (long long) printf support + */ + .ARM.extab : { + *(.ARM.extab*) + } >rom + .ARM.exidx : { + __exidx_start = .; + *(.ARM.exidx*) + __exidx_end = .; + } >rom + + . = ALIGN(4); + _etext = .; + + .data : { + _data = .; + *(.data*) /* Read-write initialized data */ + . = ALIGN(4); + _edata = .; + } >ram AT >rom + _data_loadaddr = LOADADDR(.data); + + .bss : { + *(.bss*) /* Read-write zero initialized data */ + *(COMMON) + . = ALIGN(4); + _ebss = .; + } >ram + + /* + * The .eh_frame section appears to be used for C++ exception handling. + * You may need to fix this if you're using C++. + */ + /DISCARD/ : { *(.eh_frame) } + + . = ALIGN(4); + end = .; +} + +PROVIDE(_stack = ORIGIN(ram) + LENGTH(ram)); diff --git a/lib/sam/4l/pm.c b/lib/sam/4l/pm.c new file mode 100644 index 00000000..2d48068e --- /dev/null +++ b/lib/sam/4l/pm.c @@ -0,0 +1,75 @@ +/** @addtogroup scif + * + * @brief Access functions for the SAM4 Power Manager (PM) + * @ingroup SAM4 + * LGPL License Terms @ref lgpl_license + * @author @htmlonly © @endhtmlonly 2016 + * Maxim Sloyko + * + */ + +/* + * This file is part of the libopencm3 project. + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#include + +void pm_select_main_clock(enum mck_src source_clock) +{ + PM_UNLOCK = PM_MCCTRL_KEY; + PM_MCCTRL = ((source_clock & PM_MCCTRL_MCSEL_MASK) << PM_MCCTRL_MCSEL_SHIFT); + while (!(PM_SR & PM_SR_CKRDY)); +} + +void pm_enable_clock_div(enum pm_cksel sel_target, uint8_t div) +{ + while (!(PM_SR & PM_SR_CKRDY)); + uint32_t reg = (PM_CKSEL_DIV | (div & PM_CKSEL_MASK)); + + PM_UNLOCK = PM_CKSEL_KEY(sel_target); + PM_CKSEL(sel_target) = reg; + while (!(PM_SR & PM_SR_CKRDY)); +} + +void pm_set_divmask_clock(uint8_t mask) +{ + PM_UNLOCK = PM_PBADIVMASK_KEY; + PM_PBADIVMASK = mask; +} + +static void set_peripheral_clock_status(enum pm_peripheral periph, bool on) +{ + uint8_t reg_id = periph/32; + uint8_t bit_offset = periph % 32; + uint32_t reg_mask = PM_MASK(reg_id); + if (on) { + reg_mask |= (1 << bit_offset); + } else { + reg_mask &= ~(1 << bit_offset); + } + PM_UNLOCK = PM_MASK_KEY(reg_id); + PM_MASK(reg_id) = reg_mask; +} + +void pm_enable_peripheral_clock(enum pm_peripheral periph) +{ + set_peripheral_clock_status(periph, true); +} + +void pm_disable_peripheral_clock(enum pm_peripheral periph) +{ + set_peripheral_clock_status(periph, false); +} diff --git a/lib/sam/4l/scif.c b/lib/sam/4l/scif.c new file mode 100644 index 00000000..a161355a --- /dev/null +++ b/lib/sam/4l/scif.c @@ -0,0 +1,133 @@ +/** @addtogroup scif + * + * @brief Access functions for the SAM4 System Controf Interface (SCIF) + * @ingroup SAM4 + * LGPL License Terms @ref lgpl_license + * @author @htmlonly © @endhtmlonly 2016 + * Maxim Sloyko + * + */ + +/* + * This file is part of the libopencm3 project. + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#include + +/** @brief Enable external oscillator. + * + * @param[in] mode enum osc_mode: Oscillator mode (which pins oscillator connected to). + * @param[in] freq uint32_t: External Oscillator frequency, in Hertz. Must be 0.6MHz - 30MHz + * @param[in] startup enum osc_startup: Oscillator start time in RCSYS clock cycles. + * + * @returns zero upon success. + */ +int scif_osc_enable(enum osc_mode mode, uint32_t freq, enum osc_startup startup) +{ + uint8_t gain; + const uint32_t kHz = 1000; + const uint32_t MHz = 1000 * kHz; + + if (freq > 600 * kHz && freq <= 2 * MHz) { + gain = 0; + } else if (freq > 2 * MHz && freq <= 4 * MHz) { + gain = 1; + } else if (freq > 4 * MHz && freq <= 8 * MHz) { + gain = 2; + } else if (freq > 8 * MHz && freq <= 16 * MHz) { + gain = 3; + } else if (freq > 16 * MHz && freq <= 30 * MHz) { + gain = 4; + } else { + return -1; + } + + SCIF_UNLOCK = SCIF_OSCCTRL0_KEY; + SCIF_OSCCTRL0 = mode | SCIF_OSCCTRL_OSCEN | + (gain << SCIF_OSCCTRL_GAIN_SHIFT) | (startup << SCIF_OSCCTRL_STARTUP_SHIFT); + + while (!(SCIF_PCLKSR & SCIF_OSC0RDY)); + return 0; +} + +/** @brief Configure and enable PLL clock. + * + * @param[in] delay uint8_t: Specifies the number of RCSYS clock cycles before + * ISR.PLLLOCKn will be set after PLL has been written, or after PLL has + * been automatically re-enabled after exiting a sleep mode. + * @param[in] mul uint8_t: Multiply factor. + * @param[in] div uint8_t: Division factor.These fields determine the ratio of + * the PLL output frequency to the source oscillator frequency: + * f_vco = (PLLMUL+1)/PLLDIV * f_ref if PLLDIV >0 + * f_vco = 2*(PLLMUL+1) * f_ref if PLLDIV = 0 + * Note that the PLLMUL field should always be greater than 1 or the + * behavior of the PLL will be undefined. + * @param[in] pll_opt uint8_t: PLL Options. + * @param[in] pll_opt uint8_t: PLL Options. + * + * @returns zero upon success. + */ +int scif_enable_pll(uint8_t delay, uint8_t mul, uint8_t div, uint8_t pll_opt, enum pll_clk_src source_clock) +{ + // First, PLL needs to be disabled, otherwise the configuration register + // is unaccessible. + uint32_t pll_val = SCIF_PLL0; + if (pll_val & SCIF_PLL0_PLLEN) { + SCIF_UNLOCK = SCIF_PLL0_KEY; + SCIF_PLL0 = pll_val & (~SCIF_PLL0_PLLEN); + } + + if (mul == 0) + mul = 1; + + pll_val = SCIF_PLL0_PLLOSC_MASKED(source_clock) + | SCIF_PLL0_PLLOPT_MASKED(pll_opt) + | SCIF_PLL0_PLLDIV_MASKED(div) + | SCIF_PLL0_PLLMUL_MASKED(mul) + | SCIF_PLL0_PLLCOUNT_MASKED(delay); + + SCIF_UNLOCK = SCIF_PLL0_KEY; + SCIF_PLL0 = pll_val; + + // Now enable TODO: does this really need to be separate operation? + SCIF_UNLOCK = SCIF_PLL0_KEY; + SCIF_PLL0 = pll_val | SCIF_PLL0_PLLEN; + + while(!(SCIF_PCLKSR & SCIF_PLL0LOCK)); + + return 0; +} + +/** @brief Configure and enable Generic Clock + * + * @param[in] gclk enum generic_clock: Generic Clock to configure and enable. + * @param[in] source_clock enum gclk_src: Source Clock for this Generic Clock. + * @param[in] div uint16_t: Division Factor. Upper 8 bits only used for Generic Clock 11, + * If 0, clock is undivided. + */ +void scif_enable_gclk(enum generic_clock gclk, enum gclk_src source_clock, uint16_t div) +{ + uint32_t reg_val = SCIF_GCCTRL_CEN | SCIF_GCCTRL_OSCSEL_MASKED(source_clock); + if (div) { + if (gclk < GENERIC_CLOCK11) { + div &= 0xf; + } + + reg_val |= SCIF_GCCTRL_DIV_MASKED(div) | SCIF_GCCTRL_DIVEN; + } + + SCIF_GCTRL(gclk) = reg_val; +} diff --git a/lib/sam/4l/usart.c b/lib/sam/4l/usart.c new file mode 100644 index 00000000..87680201 --- /dev/null +++ b/lib/sam/4l/usart.c @@ -0,0 +1,26 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2013 Gareth McMullin + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#include + +void usart_set_baudrate(uint32_t usart, uint32_t baud) +{ + USART_BRGR(usart) = baud; +} + diff --git a/lib/sam/common/usart_common_3.c b/lib/sam/common/usart_common_3.c new file mode 100644 index 00000000..46e03e6d --- /dev/null +++ b/lib/sam/common/usart_common_3.c @@ -0,0 +1,27 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2013 Gareth McMullin + * + * This library is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library. If not, see . + */ + +#include + +extern uint32_t pmc_mck_frequency; + +void usart_set_baudrate(uint32_t usart, uint32_t baud) +{ + USART_BRGR(usart) = pmc_mck_frequency / (16 * baud); +} diff --git a/lib/sam/common/usart.c b/lib/sam/common/usart_common_all.c similarity index 78% rename from lib/sam/common/usart.c rename to lib/sam/common/usart_common_all.c index 36833f7e..7e87655c 100644 --- a/lib/sam/common/usart.c +++ b/lib/sam/common/usart_common_all.c @@ -18,12 +18,6 @@ */ #include -#include - -void usart_set_baudrate(uint32_t usart, uint32_t baud) -{ - USART_BRGR(usart) = pmc_mck_frequency / (16 * baud); -} void usart_set_databits(uint32_t usart, int bits) { @@ -58,12 +52,12 @@ void usart_set_flow_control(uint32_t usart, enum usart_flowcontrol fc) void usart_enable(uint32_t usart) { - (void)usart; + USART_CR(usart) = USART_CR_TXEN | USART_CR_RXEN; } void usart_disable(uint32_t usart) { - (void)usart; + USART_CR(usart) = USART_CR_TXDIS | USART_CR_RXDIS; } void usart_send(uint32_t usart, uint16_t data) @@ -108,3 +102,25 @@ void usart_disable_rx_interrupt(uint32_t usart) { USART_IDR(usart) = USART_CSR_RXRDY; } + +void usart_wp_enable(uint32_t usart) +{ + USART_WPMR(usart) = USART_WPMR_KEY | USART_WPMR_WPEN; +} + +void usart_wp_disable(uint32_t usart) +{ + USART_WPMR(usart) = USART_WPMR_KEY & (~USART_WPMR_WPEN); +} + +void usart_select_clock(uint32_t usart, enum usart_clock clk) +{ + uint32_t reg_mr = USART_MR(usart) & (~USART_MR_USCLKS_MASK); + USART_MR(usart) = ((clk << USART_MR_USCLKS_SHIFT) & USART_MR_USCLKS_MASK) | reg_mr; +} + +void usart_set_character_length(uint32_t usart, enum usart_chrl chrl) +{ + uint32_t reg_mr = USART_MR(usart) & (~USART_MR_CHRL_MASK); + USART_MR(usart) = reg_mr | (chrl << USART_MR_CHRL_SHIFT); +}