From 54eff24e7c0fe3e0eba69f414452033ebc90fb9b Mon Sep 17 00:00:00 2001 From: Icenowy Zheng Date: Tue, 19 Feb 2019 01:25:12 +0800 Subject: [PATCH] swm050: new MCU family SWM050 is a series of MCU made by Foshan Synwit Tech. It contains a Cortex-M0 CPU core, 8KiB of Flash and 1KiB of SRAM. The only peripherals are GPIO, Timer and WDT. There's only two parts in this series, with either TSSOP-8 or SSOP-16 packages. This commit introduces the interrupt vector and GPIO support for them. Signed-off-by: Icenowy Zheng --- Makefile | 3 +- include/libopencm3/dispatch/nvic.h | 3 + include/libopencm3/swm050/gpio.h | 86 +++++++++ include/libopencm3/swm050/irq.json | 21 +++ include/libopencm3/swm050/memorymap.h | 35 ++++ include/libopencmsis/dispatch/irqhandlers.h | 2 + include/libopencmsis/swm050/irqhandlers.h | 22 +++ lib/dispatch/vector_nvic.c | 3 + lib/swm050/Makefile | 41 +++++ lib/swm050/gpio.c | 190 ++++++++++++++++++++ 10 files changed, 405 insertions(+), 1 deletion(-) create mode 100644 include/libopencm3/swm050/gpio.h create mode 100644 include/libopencm3/swm050/irq.json create mode 100644 include/libopencm3/swm050/memorymap.h create mode 100644 include/libopencmsis/swm050/irqhandlers.h create mode 100644 lib/swm050/Makefile create mode 100644 lib/swm050/gpio.c diff --git a/Makefile b/Makefile index 36e1f2f6..02a46bfe 100644 --- a/Makefile +++ b/Makefile @@ -37,7 +37,8 @@ TARGETS ?= stm32/f0 stm32/f1 stm32/f2 stm32/f3 stm32/f4 stm32/f7 \ efm32/ezr32wg \ sam/3a sam/3n sam/3s sam/3u sam/3x sam/4l \ sam/d \ - vf6xx + vf6xx \ + swm050 # Be silent per default, but 'make V=1' will show all compiler calls. ifneq ($(V),1) diff --git a/include/libopencm3/dispatch/nvic.h b/include/libopencm3/dispatch/nvic.h index 62be168c..b7e2810b 100644 --- a/include/libopencm3/dispatch/nvic.h +++ b/include/libopencm3/dispatch/nvic.h @@ -75,6 +75,9 @@ #elif defined(VF6XX) # include +#elif defined(SWM050) +# include + #else # warning"no interrupts defined for chipset; NVIC_IRQ_COUNT = 0" diff --git a/include/libopencm3/swm050/gpio.h b/include/libopencm3/swm050/gpio.h new file mode 100644 index 00000000..f31689a9 --- /dev/null +++ b/include/libopencm3/swm050/gpio.h @@ -0,0 +1,86 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2019 Icenowy Zheng + * + * 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 + +/* GPIO number definitions (for convenience) */ +/** @defgroup gpio_pin_id GPIO Pin Identifiers +@ingroup gpio_defines + +@{*/ +#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 GPIO_ALL 0x3ff +/**@}*/ + +/* GPIO direction definitions */ +/** @defgroup gpio_dir GPIO Pin Direction +@ingroup gpio_defines +@{*/ +#define GPIO_INPUT 0x0 +#define GPIO_OUTPUT 0x1 +/**@}*/ + +#define GPIO_DATA MMIO32(GPIO_BASE + 0x0) +#define GPIO_DIR MMIO32(GPIO_BASE + 0x4) +#define GPIO_EXT MMIO32(GPIO_BASE + 0x4c) + +#define GPIO_INTEN MMIO32(GPIO_BASE + 0x30) +#define GPIO_INTMASK MMIO32(GPIO_BASE + 0x34) +#define GPIO_INTLEVEL MMIO32(GPIO_BASE + 0x38) +#define GPIO_INTPOLARITY MMIO32(GPIO_BASE + 0x3c) +#define GPIO_INTSTATUS MMIO32(GPIO_BASE + 0x40) +#define GPIO_INTRAWSTATUS MMIO32(GPIO_BASE + 0x44) +#define GPIO_INTEOI MMIO32(GPIO_BASE + 0x48) + +#define SWD_SEL MMIO32(SYSTEM_CON_BASE + 0x30) +#define GPIO_SEL MMIO32(SYSTEM_CON_BASE + 0x80) +#define GPIO_PULLUP MMIO32(SYSTEM_CON_BASE + 0x90) +#define GPIO_INEN MMIO32(SYSTEM_CON_BASE + 0xe0) + +BEGIN_DECLS + +void gpio_set(uint16_t gpios); +void gpio_clear(uint16_t gpios); +uint16_t gpio_get(uint16_t gpios); +void gpio_toggle(uint16_t gpios); + +void gpio_input(uint16_t gpios); +void gpio_output(uint16_t gpios); +void gpio_sel_af(uint16_t gpios, bool af_en); +void gpio_pullup(uint16_t gpios, bool en); +void gpio_in_en(uint16_t gpios, bool en); + +void gpio_sel_swd(bool en); + +END_DECLS + +#endif diff --git a/include/libopencm3/swm050/irq.json b/include/libopencm3/swm050/irq.json new file mode 100644 index 00000000..339d81eb --- /dev/null +++ b/include/libopencm3/swm050/irq.json @@ -0,0 +1,21 @@ +{ + "irqs": [ + "timer_se0", + "timer_se1", + "wdt", + "cp", + "gpioa0", + "gpioa1", + "gpioa2", + "gpioa3", + "gpioa4", + "gpioa5", + "gpioa6", + "gpioa7", + "gpioa8", + "gpioa9" + ], + "partname_humanreadable": "SWM050 series", + "partname_doxygen": "SWM050", + "includeguard": "LIBOPENCM3_SWM050_NVIC_H" +} diff --git a/include/libopencm3/swm050/memorymap.h b/include/libopencm3/swm050/memorymap.h new file mode 100644 index 00000000..97fe23df --- /dev/null +++ b/include/libopencm3/swm050/memorymap.h @@ -0,0 +1,35 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2019 Icenowy Zheng + * + * 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_MEMORYMAP_H +#define LIBOPENCM3_MEMORYMAP_H + +#include + +/* Memory map for all buses */ +#define PERIPH_BASE (0x40000000U) + +#define SYSTEM_CON_BASE (PERIPH_BASE + 0x0) +#define GPIO_BASE (PERIPH_BASE + 0x1000) +#define TIMER_SE0_BASE (PERIPH_BASE + 0x2000) +#define TIMER_SE1_BASE (PERIPH_BASE + 0x2400) +#define WDT_BASE (PERIPH_BASE + 0x19000) +#define SYSCTL_BASE (PERIPH_BASE + 0xf0000) + +#endif diff --git a/include/libopencmsis/dispatch/irqhandlers.h b/include/libopencmsis/dispatch/irqhandlers.h index f7b039e4..e8ac859f 100644 --- a/include/libopencmsis/dispatch/irqhandlers.h +++ b/include/libopencmsis/dispatch/irqhandlers.h @@ -59,6 +59,8 @@ /* Yes, we use the same interrupt table for both LM3S and LM4F */ # include +#elif defined(SWM050) +# include #else # warning"no chipset defined; user interrupts are not redirected" diff --git a/include/libopencmsis/swm050/irqhandlers.h b/include/libopencmsis/swm050/irqhandlers.h new file mode 100644 index 00000000..ef8c95db --- /dev/null +++ b/include/libopencmsis/swm050/irqhandlers.h @@ -0,0 +1,22 @@ +/* This file is part of the libopencm3 project. + * + * It was generated by the irq2nvic_h script. + * + * These definitions bend every interrupt handler that is defined CMSIS style + * to the weak symbol exported by libopencm3. + */ + +#define TIMER_SE0_IRQHandler timer_se0_isr +#define TIMER_SE1_IRQHandler timer_se1_isr +#define WDT_IRQHandler wdt_isr +#define CP_IRQHandler cp_isr +#define GPIOA0_IRQHandler gpioa0_isr +#define GPIOA1_IRQHandler gpioa1_isr +#define GPIOA2_IRQHandler gpioa2_isr +#define GPIOA3_IRQHandler gpioa3_isr +#define GPIOA4_IRQHandler gpioa4_isr +#define GPIOA5_IRQHandler gpioa5_isr +#define GPIOA6_IRQHandler gpioa6_isr +#define GPIOA7_IRQHandler gpioa7_isr +#define GPIOA8_IRQHandler gpioa8_isr +#define GPIOA9_IRQHandler gpioa9_isr diff --git a/lib/dispatch/vector_nvic.c b/lib/dispatch/vector_nvic.c index c7221c87..0d4dd519 100644 --- a/lib/dispatch/vector_nvic.c +++ b/lib/dispatch/vector_nvic.c @@ -71,6 +71,9 @@ #elif defined(MSP432E4) # include "../msp432/e4/vector_nvic.c" +#elif defined(SWM050) +# include "../swm050/vector_nvic.c" + #else # warning "no interrupts defined for chipset;"\ "not allocating space in the vector table" diff --git a/lib/swm050/Makefile b/lib/swm050/Makefile new file mode 100644 index 00000000..ccbf14a7 --- /dev/null +++ b/lib/swm050/Makefile @@ -0,0 +1,41 @@ +## +## This file is part of the libopencm3 project. +## +## Copyright (C) 2019 Icenowy Zheng +## +## 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_swm050 +SRCLIBDIR ?= .. + +PREFIX ?= arm-none-eabi + +CC = $(PREFIX)-gcc +AR = $(PREFIX)-ar +TGT_CFLAGS = -Os \ + -Wall -Wextra -Wimplicit-function-declaration \ + -Wredundant-decls -Wmissing-prototypes -Wstrict-prototypes \ + -Wundef -Wshadow \ + -I../../include -fno-common \ + -mcpu=cortex-m0 $(FP_FLAGS) -mthumb -Wstrict-prototypes \ + -ffunction-sections -fdata-sections -MD -DSWM050 +TGT_CFLAGS += $(DEBUG_FLAGS) +TGT_CFLAGS += $(STANDARD_FLAGS) +ARFLAGS = rcs +OBJS = gpio.o + +VPATH += ../cm3 + +include ../Makefile.include diff --git a/lib/swm050/gpio.c b/lib/swm050/gpio.c new file mode 100644 index 00000000..31ee3969 --- /dev/null +++ b/lib/swm050/gpio.c @@ -0,0 +1,190 @@ +/* + * This file is part of the libopencm3 project. + * + * Copyright (C) 2019 Icenowy Zheng + * + * 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 Set a Group of Pins + +Set one or more pins of GPIO to 1. Please note that this chip doesn't support +atomic pin setting. + +@param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id + If multiple pins are to be changed, use bitwise OR '|' to separate + them. +*/ +void gpio_set(uint16_t gpios) +{ + GPIO_DATA |= gpios; +} + +/*---------------------------------------------------------------------------*/ +/** @brief Clear a Group of Pins + +Set one or more pins of GPIO to 0. Please note that this chip doesn't support +atomic pin setting. + +@param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id + If multiple pins are to be changed, use bitwise OR '|' to separate + them. +*/ +void gpio_clear(uint16_t gpios) +{ + GPIO_DATA &= ~gpios; +} + +/*---------------------------------------------------------------------------*/ +/** @brief Read a Group of Pins. + +@param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id + If multiple pins are to be read, use bitwise OR '|' to separate + them. +@return Unsigned int16 value of the pin values. The bit position of the pin + value returned corresponds to the pin number. +*/ +uint16_t gpio_get(uint16_t gpios) +{ + return GPIO_EXT & gpios; +} + +/*---------------------------------------------------------------------------*/ +/** @brief Toggle a Group of Pins + +Toggle one or more pins of GPIO. The non-toggled pins are not affected. + +@param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id + If multiple pins are to be changed, use bitwise OR '|' to separate + them. +*/ +void gpio_toggle(uint16_t gpios) +{ + uint32_t curr_status = GPIO_DATA & gpios; + GPIO_DATA = (GPIO_DATA & (~gpios)) | (~curr_status); +} + +/*---------------------------------------------------------------------------*/ +/** @brief Set the direction of a Group of Pins to Input + +Set the direction of one or more pins of GPIO to input. + +@param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id + If multiple pins are to be changed, use bitwise OR '|' to separate + them. +*/ +void gpio_input(uint16_t gpios) +{ + GPIO_DIR &= ~gpios; +} + +/*---------------------------------------------------------------------------*/ +/** @brief Set the direction of a Group of Pins to Output + +Set the direction of one or more pins of GPIO to output. + +@param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id + If multiple pins are to be changed, use bitwise OR '|' to separate + them. +*/ +void gpio_output(uint16_t gpios) +{ + GPIO_DIR |= gpios; +} + +/*---------------------------------------------------------------------------*/ +/** @brief Select the alternative function of a Group of Pins + +Select the alternative function of one or more pins of GPIO. + +@param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id + If multiple pins are to be changed, use bitwise OR '|' to separate + them. +@param[in] af_en Bool. Whether alternative function is selected +*/ +void gpio_sel_af(uint16_t gpios, bool af_en) +{ + if (gpios & GPIO0) { + GPIO_SEL = (GPIO_SEL & (~0x3)) | (af_en ? 0x1 : 0x0); + } + if (gpios & GPIO1) { + GPIO_SEL = (GPIO_SEL & (~0xc)) | (af_en ? 0x4 : 0x0); + } + if (gpios & GPIO2) { + GPIO_SEL = (GPIO_SEL & (~0x30)) | (af_en ? 0x10 : 0x0); + } + if (gpios & GPIO7) { + GPIO_SEL = (GPIO_SEL & (~0xc000)) | (af_en ? 0x4000 : 0x0); + } +} + +/*---------------------------------------------------------------------------*/ +/** @brief Enable the internal pull-up of a Group of Pins + +Enable or disable the internal pull-up of one or more pins of GPIO. + +@param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id + If multiple pins are to be changed, use bitwise OR '|' to separate + them. +@param[in] en Bool. Whether pull-up is enabled +*/ +void gpio_pullup(uint16_t gpios, bool en) +{ + if (en) { + GPIO_PULLUP |= gpios; + } else { + GPIO_PULLUP &= ~gpios; + } +} + +/*---------------------------------------------------------------------------*/ +/** @brief Enable the input function of a Group of Pins + +Enable or disable the input function of one or more pins of GPIO. Disabling +the input function of pins can decrease the power usage of the MCU. + +@param[in] gpios Unsigned int16. Pin identifiers @ref gpio_pin_id + If multiple pins are to be changed, use bitwise OR '|' to separate + them. +@param[in] en Bool. Whether input function is enabled +*/ +void gpio_in_en(uint16_t gpios, bool en) +{ + if (en) { + GPIO_INEN &= ~gpios; + } else { + GPIO_INEN |= gpios; + } +} + + +/*---------------------------------------------------------------------------*/ +/** @brief Select the SWD function of GPIO 1/2 + +Enable or disable the SWD debugging port at GPIO 1/2. When SWD debugging port +is enabled, GPIO and AF of the SWD pins will be both unavailable. + +@param[in] en Bool. Whether SWD is enabled +*/ +void gpio_sel_swd(bool en) +{ + if (en) { + SWD_SEL = 1; + } else { + SWD_SEL = 0; + } +}