SWM050: Finishes GPIO, IAP flash, sysclock, sleep/stop, and the sysctl memory map.

Updates the main memory map and the makefile.
Adds the SWM050 to devices.data, so that a linker script can be automatically generated.

Reviewed-by: Karl Palsson <karlp@tweak.net.au>
This commit is contained in:
Caleb Szalacinski 2019-09-21 15:43:50 -05:00 committed by Karl Palsson
parent 1fbfdecb17
commit 3c4ee6f4c0
14 changed files with 760 additions and 89 deletions

View File

@ -0,0 +1,55 @@
/** @defgroup clk_defines Clock Defines
*
* @brief <b>Defined Constants and Types for the SWM050 System Clock</b>
*
* @ingroup SWM050_defines
*
* LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2019 Caleb Szalacinski <contact@skiboy.net>
*
* 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 <http://www.gnu.org/licenses/>.
*/
/**@{*/
#ifndef LIBOPENCM3_CLK_H
#define LIBOPENCM3_CLK_H
#include <libopencm3/cm3/common.h>
#include <libopencm3/swm050/memorymap.h>
/* Clock speed definitions */
/** @defgroup clk_speeds Base Clock Speeds
@{*/
enum clk_speeds {
CLK_18MHZ,
CLK_36MHZ
};
/*@}*/
/* Clock divider mask */
/** @defgroup clk_mask Mask used to set the clock divider
@{*/
#define CLK_MASK 0xFFFFFC00
/*@}*/
BEGIN_DECLS
void clk_speed(enum clk_speeds mhz, uint16_t div);
END_DECLS
#endif
/**@}*/

View File

@ -0,0 +1,42 @@
/** @defgroup flash_defines Flash Defines
*
* @brief <b>Defined Constants and Types for the SWM050 Flash API</b>
*
* @ingroup SWM050_defines
*
* LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2019 Caleb Szalacinski <contact@skiboy.net>
*
* 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 <http://www.gnu.org/licenses/>.
*/
/**@{*/
#ifndef LIBOPENCM3_FLASH_H
#define LIBOPENCM3_FLASH_H
#include <libopencm3/cm3/common.h>
BEGIN_DECLS
uint32_t flash_write(uint32_t *dest, uint32_t *src, uint8_t cnt);
uint32_t flash_read(uint32_t *src, uint32_t *dest, uint8_t cnt);
uint32_t flash_erase(void);
END_DECLS
#endif
/**@}*/

View File

@ -10,6 +10,7 @@
* This file is part of the libopencm3 project.
*
* Copyright (C) 2019 Icenowy Zheng <icenowy@aosc.io>
* Copyright (C) 2019 Caleb Szalacinski <contact@skiboy.net>
*
* 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
@ -24,18 +25,14 @@
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/**@{*/
#ifndef LIBOPENCM3_GPIO_H
#define LIBOPENCM3_GPIO_H
#include <libopencm3/cm3/common.h>
#include <libopencm3/swm050/memorymap.h>
/* GPIO number definitions (for convenience) */
/** @defgroup gpio_pin_id GPIO Pin Identifiers
@{*/
#define GPIO0 (1 << 0)
#define GPIO1 (1 << 1)
@ -53,46 +50,62 @@
/* GPIO direction definitions */
/** @defgroup gpio_dir GPIO Pin Direction
@{*/
#define GPIO_INPUT 0x0
#define GPIO_OUTPUT 0x1
enum gpio_dir {
GPIO_INPUT,
GPIO_OUTPUT
};
/**@}*/
/* GPIO polarity definitions */
/** @defgroup gpio_pol GPIO Polarity
@{*/
enum gpio_pol {
GPIO_POL_LOW,
GPIO_POL_HIGH
};
/*@}*/
/* GPIO interrupt trigger definitions */
/** @defgroup gpio_trig_type GPIO Interrupt Trigger Type
@{*/
enum gpio_trig_type {
GPIO_TRIG_LEVEL,
GPIO_TRIG_EDGE
};
/*@}*/
/* GPIO interrupt mask definitions */
/** @defgroup gpio_int_masked GPIO Interrupt Mask
@{*/
enum gpio_int_masked {
GPIO_UNMASKED,
GPIO_MASKED
};
/*@}*/
/* GPIO Registers */
/** @defgroup gpio_registers GPIO Registers
@{*/
/** Data register */
#define GPIO_DATA MMIO32(GPIO_BASE + 0x0)
#define GPIO_ADATA MMIO32(GPIO_BASE + 0x0)
/** Direction register */
#define GPIO_DIR MMIO32(GPIO_BASE + 0x4)
#define GPIO_ADIR MMIO32(GPIO_BASE + 0x4)
/** Interrupt enable register */
#define GPIO_INTEN MMIO32(GPIO_BASE + 0x30)
#define GPIO_INTEN_A MMIO32(GPIO_BASE + 0x30)
/** Interrupt mask register */
#define GPIO_INTMASK MMIO32(GPIO_BASE + 0x34)
#define GPIO_INTMASK_A MMIO32(GPIO_BASE + 0x34)
/** Interrupt trigger mode register */
#define GPIO_INTLEVEL MMIO32(GPIO_BASE + 0x38)
#define GPIO_INTLEVEL_A MMIO32(GPIO_BASE + 0x38)
/** Interrupt polarity register */
#define GPIO_INTPOLARITY MMIO32(GPIO_BASE + 0x3c)
#define GPIO_INTPOLARITY_A MMIO32(GPIO_BASE + 0x3c)
/** Interrupt status after masking */
#define GPIO_INTSTATUS MMIO32(GPIO_BASE + 0x40)
#define GPIO_INTSTAT_A MMIO32(GPIO_BASE + 0x40)
/** Interrupt status before masking */
#define GPIO_INTRAWSTATUS MMIO32(GPIO_BASE + 0x44)
#define GPIO_RAWINTSTAT_A MMIO32(GPIO_BASE + 0x44)
/** Interrupt clear register */
#define GPIO_INTEOI MMIO32(GPIO_BASE + 0x48)
#define GPIO_INTEOI_A MMIO32(GPIO_BASE + 0x48)
/** External register (wat) */
#define GPIO_EXT MMIO32(GPIO_BASE + 0x4c)
/**@}*/
/** @defgroup syscon_register SYSCON Registers
* @note These registers are really part of the SYSCON system control space
* @{*/
/** SWD Enable register */
#define SWD_SEL MMIO32(SYSTEM_CON_BASE + 0x30)
/** GPIO Alternat function selection register */
#define GPIO_SEL MMIO32(SYSTEM_CON_BASE + 0x80)
/** GPIO Pull up register */
#define GPIO_PULLUP MMIO32(SYSTEM_CON_BASE + 0x90)
/** GPIO Input enable register */
#define GPIO_INEN MMIO32(SYSTEM_CON_BASE + 0xe0)
#define GPIO_AEXT MMIO32(GPIO_BASE + 0x4c)
/*@}*/
BEGIN_DECLS
@ -104,13 +117,16 @@ 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);
void gpio_int_enable(uint16_t gpios, bool en);
void gpio_int_mask(uint16_t gpios, enum gpio_int_masked masked);
void gpio_int_type(uint16_t gpios, enum gpio_trig_type type);
void gpio_int_pol(uint16_t gpios, enum gpio_pol pol);
uint16_t gpio_int_status(void);
uint16_t gpio_int_raw_status(void);
void gpio_int_clear(uint16_t gpios);
END_DECLS
#endif
/**@}*/
/**@}*/

View File

@ -1,3 +1,11 @@
/** @defgroup mmap_defines Memory Map
*
* @brief <b>Defined Constants for the SWM050 Memory Map</b>
*
* @ingroup SWM050_defines
*
* LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
@ -16,13 +24,14 @@
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
/**@{*/
#ifndef LIBOPENCM3_MEMORYMAP_H
#define LIBOPENCM3_MEMORYMAP_H
#include <libopencm3/cm3/memorymap.h>
/* Memory map for all buses */
/** @defgroup memory_map Memory Map for All Buses
@{*/
#define PERIPH_BASE (0x40000000U)
#define SYSTEM_CON_BASE (PERIPH_BASE + 0x0)
@ -31,5 +40,7 @@
#define TIMER_SE1_BASE (PERIPH_BASE + 0x2400)
#define WDT_BASE (PERIPH_BASE + 0x19000)
#define SYSCTL_BASE (PERIPH_BASE + 0xf0000)
/*@}*/
#endif
/**@}*/

View File

@ -0,0 +1,40 @@
/** @defgroup pwr_defines Power/Sleep Defines
*
* @brief <b>Defined Constants and Types for the SWM050 Power/Sleep API</b>
*
* @ingroup SWM050_defines
*
* LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2019 Caleb Szalacinski <contact@skiboy.net>
*
* 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 <http://www.gnu.org/licenses/>.
*/
/**@{*/
#ifndef LIBOPENCM3_PWR_H
#define LIBOPENCM3_PWR_H
#include <libopencm3/cm3/common.h>
#include <libopencm3/swm050/memorymap.h>
BEGIN_DECLS
void pwr_sleep(void);
END_DECLS
#endif
/**@}*/

View File

@ -0,0 +1,57 @@
/** @defgroup syscon_defines SYSCON Defines
*
* @brief <b>Defined Constants and Types for the SWM050 SYSCON peripheral</b>
*
* @ingroup SWM050_defines
*
* LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2019 Icenowy Zheng <icenowy@aosc.io>
* Copyright (C) 2019 Caleb Szalacinski <contact@skiboy.net>
*
* 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 <http://www.gnu.org/licenses/>.
*/
/**@{*/
#ifndef LIBOPENCM3_SYSCON_H
#define LIBOPENCM3_SYSCON_H
#include <libopencm3/cm3/common.h>
#include <libopencm3/swm050/memorymap.h>
/* SYSCON Registers */
/** @defgroup syscon_registers SYSCON Registers
@{*/
/** SWD Enable register */
#define SYSCON_SWD_SEL MMIO32(SYSTEM_CON_BASE + 0x30)
/** Pin Alternate function selection register */
#define SYSCON_PORTA_SEL MMIO32(SYSTEM_CON_BASE + 0x80)
/** Pin Pull up register */
#define SYSCON_PORTA_PULLUP MMIO32(SYSTEM_CON_BASE + 0x90)
/** Pin Input enable register */
#define SYSCON_PORTA_INEN MMIO32(SYSTEM_CON_BASE + 0xe0)
/*@}*/
BEGIN_DECLS
void syscon_sel_af(uint16_t gpios, bool af_en);
void syscon_pullup(uint16_t gpios, bool en);
void syscon_input_enable(uint16_t gpios, bool en);
void syscon_sel_swd(bool en);
END_DECLS
#endif
/**@}*/

View File

@ -0,0 +1,50 @@
/** @defgroup sysctl_defines SYSCTL Defines
*
* @brief <b>Defined Constants and Types for the SWM050 SYSCTL Registers</b>
*
* @ingroup SWM050_defines
*
* LGPL License Terms @ref lgpl_license
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2019 Caleb Szalacinski <contact@skiboy.net>
*
* 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 <http://www.gnu.org/licenses/>.
*/
/**@{*/
#ifndef LIBOPENCM3_SYSCTL_H
#define LIBOPENCM3_SYSCTL_H
#include <libopencm3/cm3/common.h>
#include <libopencm3/swm050/memorymap.h>
/** @defgroup sysctl_register SYSCTL Registers
* @note System configuration registers
* @{*/
/** Clock dividers for TIMERSE and SCLK */
#define SYSCTL_SYS_CFG_0 MMIO32(SYSCTL_BASE + 0x0)
/** TIMERSE0, TIMERSE1, and WDT enable */
#define SYSCTL_SYS_CFG_1 MMIO32(SYSCTL_BASE + 0x4)
/** SCLK multiplier (18Mhz and 36Mhz) */
#define SYSCTL_SYS_DBLF MMIO32(SYSCTL_BASE + 0x8)
/** MOS Disconnect (Synwit says that this subregister is unused), Sleep Mode,
and Internal Oscillator Disconnect. Oscillator Disconnect should probably
not be used on the SWM050, because it has no external oscillator support */
#define SYSCTL_SYS_CFG_2 MMIO32(SYSCTL_BASE + 0xC)
/*@}*/
#endif
/**@}*/

View File

@ -454,6 +454,11 @@ rm46l852* rm46l ROM=1280K RAM=192K
vf610 vf6xx RAM=256K RAM1=256K RAM_OFF=0x1f000000 RAM1_OFF=0x3f040000
################################################################################
# SWM050 chips
swm050* END ROM=8K RAM=1K ROM_OFF=0x00000000 RAM_OFF=0x20000000 CPU=cortex-m0 FPU=soft
################################################################################
################################################################################
################################################################################

View File

@ -33,8 +33,11 @@ TGT_CFLAGS += $(DEBUG_FLAGS)
TGT_CFLAGS += $(STANDARD_FLAGS)
ARFLAGS = rcs
OBJS += clk.o
OBJS += flash.o
OBJS += gpio.o
OBJS += pwr.o
OBJS += syscon.o
VPATH += ../cm3
include ../Makefile.include

84
lib/swm050/clk.c Normal file
View File

@ -0,0 +1,84 @@
/** @addtogroup clk_file Clock peripheral API
* @ingroup peripheral_apis
* LGPL License Terms @ref lgpl_license
* @author @htmlonly &copy; @endhtmlonly 2019
* Caleb Szalacinski <contact@skiboy.net>
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2019 Caleb Szalacinski <contact@skiboy.net>
*
* 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 <http://www.gnu.org/licenses/>.
*/
/**@{*/
#include <libopencm3/swm050/clk.h>
#include <libopencm3/swm050/sysctl.h>
/*---------------------------------------------------------------------------*/
/** @brief Setup and change the system clock multiplier and divider
Change system clock speed and wait for the clock to stabilize. The clock only
needs time to stabilize on the first invocation of this function. This should be
run at startup if you want to have a stable clock before doing anything.
@param[in] mhz Base clock speed @ref clk_speeds
The base clock speed, before the clock divider
@param[in] div Clock divider
Takes values from 0 to 1023 (in reality the possible values are the even
numbers from 2 to 1022, as well as the number 1). Anything more than the
first 10 bits is stripped off of the value. If the value is 0, it will
be treated as a 1. All odd values other than 1 are rounded down to the
closest even value, due to the fact that all odd values are treated by
the register as a 1, which would likely be unexpected. A value of 0
would also normally be treated as a 2, which would also be unexpected
behavior.
*/
void clk_speed(enum clk_speeds mhz, uint16_t div)
{
static bool first_run = true;
if (first_run) {
first_run = false;
clk_speed(CLK_18MHZ, 1);
for (uint16_t i = 0; i < 10000; ++i) {
__asm__("nop");
}
/* The speed doesn't need to be changed
a second time if the user wants 18Mhz. */
if ((mhz == CLK_18MHZ) && (div <= 1)) {
return;
}
if ((mhz == CLK_36MHZ) && (div == 2)) {
return;
}
}
if (mhz == CLK_36MHZ) {
SYSCTL_SYS_DBLF |= BIT0;
} else {
SYSCTL_SYS_DBLF &= ~BIT0;
}
if (div <= 1) {
SYSCTL_SYS_CFG_0 |= BIT0;
} else {
uint32_t masked_reg32 = SYSCTL_SYS_CFG_0 & CLK_MASK;
SYSCTL_SYS_CFG_0 = masked_reg32 | (div & ~(CLK_MASK | 0x1));
}
}
/**@}*/

96
lib/swm050/flash.c Normal file
View File

@ -0,0 +1,96 @@
/** @addtogroup flash_file Flash peripheral API
* @ingroup peripheral_apis
* LGPL License Terms @ref lgpl_license
* @author @htmlonly &copy; @endhtmlonly 2019
* Caleb Szalacinski <contact@skiboy.net>
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2019 Caleb Szalacinski <contact@skiboy.net>
*
* 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 <http://www.gnu.org/licenses/>.
*/
/**@{*/
#include <libopencm3/swm050/flash.h>
/* Internal function pointers to the ROM flash API */
#define IAP_WR (void *)(0x1000AB)
#define IAP_E (void *)(0x100127)
uint32_t (*iap_write_read)(uint32_t *, uint32_t *, uint8_t, uint8_t) = IAP_WR;
uint32_t (*iap_erase)(void) = IAP_E;
/*---------------------------------------------------------------------------*/
/** @brief Write to the user flash
Writes words to the 0.5k user flash area.
Must be performed only when the system clock is 18Mhz.
@param[in] dest Destination address
The memory area to copy to.
From 0x00 - 0x1FC, as long as it is word-aligned
@param[in] src Source address
The memory area to copy from.
@param[in] cnt Number of words to write
From 1-128 as long as (dest + (cnt * 4)) < 0x200
@return 1 if successful, 0 if error
*/
uint32_t flash_write(uint32_t *dest, uint32_t *src, uint8_t cnt)
{
return iap_write_read(dest, src, cnt, 1);
}
/*---------------------------------------------------------------------------*/
/** @brief Read from the user flash
Reads words from the 0.5k user flash area.
Must be performed only when the system clock is 18Mhz.
@param[in] src Source address
The memory area to copy from.
From 0x00 - 0x1FC, as long as it is word-aligned
@param[out] dest Destination address
The memory area to copy to.
@param[in] cnt Number of words to read
From 1 - 128 as long as (src + (cnt * 4)) < 0x200
@return 1 if successful, 0 if error
*/
uint32_t flash_read(uint32_t *src, uint32_t *dest, uint8_t cnt)
{
return iap_write_read(src, dest, cnt, 0);
}
/*---------------------------------------------------------------------------*/
/** @brief Erase the user flash
Erases the entire 0.5k user flash area.
Must be performed only when the system clock is 18Mhz.
@return 1 if successful, 0 if error
*/
uint32_t flash_erase(void)
{
return iap_erase();
}
/**@}*/

View File

@ -1,10 +1,16 @@
/** @addtogroup gpio_file GPIO peripheral API
* @ingroup peripheral_apis
* LGPL License Terms @ref lgpl_license
* @author @htmlonly &copy; @endhtmlonly 2019
* Icenowy Zheng <icenowy@aosc.io>
* @author @htmlonly &copy; @endhtmlonly 2019
* Caleb Szalacinski <contact@skiboy.net>
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2019 Icenowy Zheng <icenowy@aosc.io>
* Copyright (C) 2019 Caleb Szalacinski <contact@skiboy.net>
*
* 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
@ -19,10 +25,8 @@
* You should have received a copy of the GNU Lesser General Public License
* along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#include <libopencm3/swm050/gpio.h>
/**@{*/
#include <libopencm3/swm050/gpio.h>
/*---------------------------------------------------------------------------*/
/** @brief Set a Group of Pins
@ -36,7 +40,7 @@ atomic pin setting.
*/
void gpio_set(uint16_t gpios)
{
GPIO_DATA |= gpios;
GPIO_ADATA |= gpios;
}
/*---------------------------------------------------------------------------*/
@ -51,7 +55,7 @@ atomic pin setting.
*/
void gpio_clear(uint16_t gpios)
{
GPIO_DATA &= ~gpios;
GPIO_ADATA &= ~gpios;
}
/*---------------------------------------------------------------------------*/
@ -65,7 +69,7 @@ void gpio_clear(uint16_t gpios)
*/
uint16_t gpio_get(uint16_t gpios)
{
return GPIO_EXT & gpios;
return GPIO_AEXT & gpios;
}
/*---------------------------------------------------------------------------*/
@ -79,8 +83,8 @@ Toggle one or more pins of GPIO. The non-toggled pins are not affected.
*/
void gpio_toggle(uint16_t gpios)
{
uint32_t curr_status = GPIO_DATA & gpios;
GPIO_DATA = (GPIO_DATA & (~gpios)) | (~curr_status);
uint32_t curr_status = GPIO_ADATA & gpios;
GPIO_ADATA = (GPIO_ADATA & (~gpios)) | (~curr_status);
}
/*---------------------------------------------------------------------------*/
@ -94,7 +98,7 @@ Set the direction of one or more pins of GPIO to input.
*/
void gpio_input(uint16_t gpios)
{
GPIO_DIR &= ~gpios;
GPIO_ADIR &= ~gpios;
}
/*---------------------------------------------------------------------------*/
@ -108,90 +112,142 @@ Set the direction of one or more pins of GPIO to output.
*/
void gpio_output(uint16_t gpios)
{
GPIO_DIR |= gpios;
GPIO_ADIR |= gpios;
}
/*---------------------------------------------------------------------------*/
/** @brief Select the alternative function of a Group of Pins
Select the alternative function of one or more pins of GPIO.
/*---------------------------------------------------------------------------*/
/** @brief Sets the pins as external interrupts, rather than normal GPIO
Enable interrupts on the selected pins. If you want to quickly
switch on and off interrupts, use gpio_int_mask() after calling this.
@param[in] gpios Pin identifiers @ref gpio_pin_id
If multiple pins are to be changed, use bitwise OR '|' to separate
them.
@param[in] af_en Whether alternative function is selected
@param[in] en True to enable, false to disable.
*/
void gpio_sel_af(uint16_t gpios, bool af_en)
void gpio_int_enable(uint16_t gpios, bool 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);
if (en) {
GPIO_INTEN_A |= gpios;
} else {
GPIO_INTEN_A &= ~gpios;
}
}
/*---------------------------------------------------------------------------*/
/** @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.
/*---------------------------------------------------------------------------*/
/** @brief Sets bits in the interrupt mask
When interrupts are masked, it prevents them from being received, which is a
quicker way to turn on and off GPIO interrupts (after calling gpio_int_en()).
@param[in] gpios 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
@param[in] masked Pin mask selection @ref gpio_int_masked
Whether to mask or unmask pins.
*/
void gpio_pullup(uint16_t gpios, bool en)
void gpio_int_mask(uint16_t gpios, enum gpio_int_masked masked)
{
if (en) {
GPIO_PULLUP |= gpios;
if (masked) {
GPIO_INTMASK_A |= gpios;
} else {
GPIO_PULLUP &= ~gpios;
GPIO_INTMASK_A &= ~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 decreases the power usage of the MCU.
/*---------------------------------------------------------------------------*/
/** @brief Sets whether the pins are edge triggered or level triggered
Sets whether the pins are edge triggered or level triggered. Edge-triggered
interrupt bits must be cleared by software.
@param[in] gpios Pin identifiers @ref gpio_pin_id
If multiple pins are to be changed, use bitwise OR '|' to separate
them.
@param[in] en true to enable input function.
@param[in] type Trigger Type @ref gpio_trig_type
Level or edge triggered
*/
void gpio_in_en(uint16_t gpios, bool en)
void gpio_int_type(uint16_t gpios, enum gpio_trig_type type)
{
if (en) {
GPIO_INEN &= ~gpios;
if (type) {
GPIO_INTLEVEL_A |= gpios;
} else {
GPIO_INEN |= gpios;
GPIO_INTLEVEL_A &= ~gpios;
}
}
/*---------------------------------------------------------------------------*/
/** @brief Select the SWD function of GPIO 1/2
/** @brief Sets the interrupt trigger polarity
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.
Sets whether the interrupt is triggered by a high or low level/edge.
@param[in] en true to enable SWD.
@param[in] gpios Pin identifiers @ref gpio_pin_id
If multiple pins are to be changed, use bitwise OR '|' to separate
them.
@param[in] pol Polarity @ref gpio_pol
High or low level/edge
*/
void gpio_sel_swd(bool en)
void gpio_int_pol(uint16_t gpios, enum gpio_pol pol)
{
if (en) {
SWD_SEL = 1;
if (pol) {
GPIO_INTPOLARITY_A |= gpios;
} else {
SWD_SEL = 0;
GPIO_INTPOLARITY_A &= ~gpios;
}
}
/*---------------------------------------------------------------------------*/
/** @brief Gets the masked interrupt status
Returns the pin interrupt status masked with the mask set
in @ref gpio_int_mask().
@return The masked pin interrupt status as a bitfield. The bit position of the
pin value returned corresponds to the pin number.
*/
uint16_t gpio_int_status(void)
{
return GPIO_INTSTAT_A;
}
/*---------------------------------------------------------------------------*/
/** @brief Gets the raw unmasked interrupt status
Returns the raw unmasked interrupt status.
@return The unmasked pin interrupt status as a bitfield. The bit position of the
pin value returned corresponds to the pin number.
*/
uint16_t gpio_int_raw_status(void)
{
return GPIO_RAWINTSTAT_A;
}
/*---------------------------------------------------------------------------*/
/** @brief Clear the specified pin interrupts
Clears the specified pin interrupts. Edge-triggered interrupts must be cleared
by software.
@param[in] gpios Pin identifiers @ref gpio_pin_id
If multiple pins are to be changed, use bitwise OR '|' to separate
them.
*/
void gpio_int_clear(uint16_t gpios)
{
GPIO_INTEOI_A |= gpios;
}
/**@}*/

41
lib/swm050/pwr.c Normal file
View File

@ -0,0 +1,41 @@
/** @addtogroup pwr_file Power/Sleep API
* @ingroup peripheral_apis
* LGPL License Terms @ref lgpl_license
* @author @htmlonly &copy; @endhtmlonly 2019
* Caleb Szalacinski <contact@skiboy.net>
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2019 Caleb Szalacinski <contact@skiboy.net>
*
* 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 <http://www.gnu.org/licenses/>.
*/
/**@{*/
#include <libopencm3/swm050/sysctl.h>
#include <libopencm3/swm050/pwr.h>
/*---------------------------------------------------------------------------*/
/** @brief Go into sleep mode
Goes to sleep and wakes up on when GPIO pin 9 is pulled low. Please give
yourself enough time to connect the debugger before calling this, in order to
not get locked out of the MCU.
*/
void pwr_sleep(void)
{
SYSCTL_SYS_CFG_2 |= (1<<4);
}
/**@}*/

115
lib/swm050/syscon.c Normal file
View File

@ -0,0 +1,115 @@
/** @addtogroup syscon_file SYSCON peripheral API
* @ingroup peripheral_apis
* LGPL License Terms @ref lgpl_license
* @author @htmlonly &copy; @endhtmlonly 2019
* Icenowy Zheng <icenowy@aosc.io>
* @author @htmlonly &copy; @endhtmlonly 2019
* Caleb Szalacinski <contact@skiboy.net>
*/
/*
* This file is part of the libopencm3 project.
*
* Copyright (C) 2019 Icenowy Zheng <icenowy@aosc.io>
* Copyright (C) 2019 Caleb Szalacinski <contact@skiboy.net>
*
* 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 <http://www.gnu.org/licenses/>.
*/
/**@{*/
#include <libopencm3/swm050/syscon.h>
#include <libopencm3/swm050/gpio.h>
/*---------------------------------------------------------------------------*/
/** @brief Select the alternative function of a Group of Pins
Select the alternative function of one or more pins of GPIO.
@param[in] gpios Pin identifiers @ref gpio_pin_id
If multiple pins are to be changed, use bitwise OR '|' to separate
them.
@param[in] af_en Whether alternative function is selected
*/
void syscon_sel_af(uint16_t gpios, bool af_en)
{
uint32_t masked_reg32;
if (gpios & GPIO0) {
masked_reg32 = SYSCON_PORTA_SEL & (~0x3);
SYSCON_PORTA_SEL = masked_reg32 | (af_en ? 0x1 : 0x0);
}
if (gpios & GPIO1) {
masked_reg32 = SYSCON_PORTA_SEL & (~0xc);
SYSCON_PORTA_SEL = masked_reg32 | (af_en ? 0x4 : 0x0);
}
if (gpios & GPIO2) {
masked_reg32 = SYSCON_PORTA_SEL & (~0x30);
SYSCON_PORTA_SEL = masked_reg32 | (af_en ? 0x10 : 0x0);
}
if (gpios & GPIO7) {
masked_reg32 = SYSCON_PORTA_SEL & (~0xc000);
SYSCON_PORTA_SEL = masked_reg32 | (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 Pin identifiers @ref gpio_pin_id
If multiple pins are to be changed, use bitwise OR '|' to separate
them.
@param[in] en True to enable pull-up, false to disable.
*/
void syscon_pullup(uint16_t gpios, bool en)
{
if (en) {
SYSCON_PORTA_PULLUP |= gpios;
} else {
SYSCON_PORTA_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 decreases the power usage of the MCU.
@param[in] gpios Pin identifiers @ref gpio_pin_id
If multiple pins are to be changed, use bitwise OR '|' to separate
them.
@param[in] en True to enable input function.
*/
void syscon_input_enable(uint16_t gpios, bool en)
{
if (en) {
SYSCON_PORTA_INEN &= ~gpios;
} else {
SYSCON_PORTA_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 True to enable SWD.
*/
void syscon_sel_swd(bool en)
{
SYSCON_SWD_SEL = en;
}
/**@}*/