git subrepo clone https://github.com/libopencm3/libopencm3.git
subrepo: subdir: "libopencm3" merged: "88e91c9a7cce" upstream: origin: "https://github.com/libopencm3/libopencm3.git" branch: "master" commit: "88e91c9a7cce" git-subrepo: version: "0.4.3" origin: "???" commit: "???"
This commit is contained in:
49
libopencm3/lib/Makefile.include
Normal file
49
libopencm3/lib/Makefile.include
Normal file
@@ -0,0 +1,49 @@
|
||||
##
|
||||
## This file is part of the libopencm3 project.
|
||||
##
|
||||
## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
## Copyright (C) 2012 Piotr Esden-Tempski <piotr@esden.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/>.
|
||||
##
|
||||
|
||||
# Be silent per default, but 'make V=1' will show all compiler calls.
|
||||
ifneq ($(V),1)
|
||||
Q := @
|
||||
endif
|
||||
|
||||
# common objects
|
||||
OBJS += vector.o systick.o scb.o nvic.o assert.o sync.o dwt.o
|
||||
|
||||
# Slightly bigger .elf files but gains the ability to decode macros
|
||||
DEBUG_FLAGS ?= -ggdb3
|
||||
STANDARD_FLAGS ?= -std=c99
|
||||
|
||||
all: $(SRCLIBDIR)/$(LIBNAME).a
|
||||
|
||||
$(SRCLIBDIR)/$(LIBNAME).a: $(OBJS)
|
||||
@printf " AR $(LIBNAME).a\n"
|
||||
$(Q)$(AR) $(ARFLAGS) "$@" $(OBJS)
|
||||
|
||||
%.o: %.c
|
||||
@printf " CC $(<F)\n"
|
||||
$(Q)$(CC) $(TGT_CFLAGS) $(CFLAGS) -o $@ -c $<
|
||||
|
||||
clean:
|
||||
$(Q)rm -f *.o *.d ../*.o ../*.d
|
||||
$(Q)rm -f $(SRCLIBDIR)/$(LIBNAME).a
|
||||
|
||||
.PHONY: clean
|
||||
|
||||
-include $(OBJS:.o=.d)
|
||||
34
libopencm3/lib/cm3/assert.c
Normal file
34
libopencm3/lib/cm3/assert.c
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2012 Tomaz Solc <tomaz.solc@tablix.org>
|
||||
*
|
||||
* 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/cm3/assert.h>
|
||||
|
||||
void __attribute__((weak)) cm3_assert_failed(void)
|
||||
{
|
||||
while (1);
|
||||
}
|
||||
|
||||
void __attribute__((weak)) cm3_assert_failed_verbose(
|
||||
const char *file __attribute__((unused)),
|
||||
int line __attribute__((unused)),
|
||||
const char *func __attribute__((unused)),
|
||||
const char *assert_expr __attribute__((unused)))
|
||||
{
|
||||
cm3_assert_failed();
|
||||
}
|
||||
105
libopencm3/lib/cm3/dwt.c
Normal file
105
libopencm3/lib/cm3/dwt.c
Normal file
@@ -0,0 +1,105 @@
|
||||
/** @defgroup CM3_dwt_file DWT
|
||||
*
|
||||
* @ingroup CM3_files
|
||||
*
|
||||
* @brief <b>libopencm3 Cortex-M Data Watchpoint and Trace unit</b>
|
||||
*
|
||||
* The DWT provides
|
||||
* * Comparators, that support
|
||||
* * watch points
|
||||
* * data tracing
|
||||
* * signalling to ETM
|
||||
* * PC value tracing
|
||||
* * cycle count matching
|
||||
* * extra PC sampling
|
||||
* * Sampling as a result of a clock count
|
||||
* * external access for sampling
|
||||
* * exception trace
|
||||
* * performance profiling counters.
|
||||
*
|
||||
* Which of these features are available is unfortunately implementation defined.
|
||||
*
|
||||
* @see ARMv7m Architecture Reference Manual (Chapter ARMv7-M Debug)
|
||||
*
|
||||
* LGPL License Terms @ref lgpl_license
|
||||
* @{
|
||||
*/
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2013 Frantisek Burian <BuFran@seznam.cz>
|
||||
*
|
||||
* 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/cm3/scs.h>
|
||||
#include <libopencm3/cm3/dwt.h>
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief DebugTrace Enable the CPU cycle counter
|
||||
*
|
||||
* This function will try to enable the CPU cycle counter that is intended for
|
||||
* benchmarking performance of the code. If function fails, the cycle counter
|
||||
* isn't available on this architecture.
|
||||
*
|
||||
* @return true, if success
|
||||
*/
|
||||
bool dwt_enable_cycle_counter(void)
|
||||
{
|
||||
#if defined(__ARM_ARCH_6M__)
|
||||
return false; /* Not supported on ARMv6M */
|
||||
#endif /* defined(__ARM_ARCH_6M__) */
|
||||
|
||||
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
|
||||
/* Note TRCENA is for 7M and above*/
|
||||
SCS_DEMCR |= SCS_DEMCR_TRCENA;
|
||||
if (DWT_CTRL & DWT_CTRL_NOCYCCNT) {
|
||||
return false; /* Not supported in implementation */
|
||||
}
|
||||
|
||||
DWT_CYCCNT = 0;
|
||||
DWT_CTRL |= DWT_CTRL_CYCCNTENA;
|
||||
return true;
|
||||
#endif /* defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) */
|
||||
|
||||
/* not supported on other architectures */
|
||||
return false;
|
||||
}
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief DebugTrace Read the CPU cycle counter
|
||||
*
|
||||
* This function reads the core cycle counter if it is enabled. It is the
|
||||
* fastest clock running on the system.
|
||||
*
|
||||
* @note The CPU cycle counter must be enabled by @ref dwt_enable_cycle_counter
|
||||
*
|
||||
* @returns 0 if cycle counter is not supported or enabled, the cycle counter
|
||||
* value otherwise.
|
||||
*/
|
||||
uint32_t dwt_read_cycle_counter(void)
|
||||
{
|
||||
#if defined(__ARM_ARCH_6M__)
|
||||
return 0; /* Not supported on ARMv6M */
|
||||
#endif /* defined(__ARM_ARCH_6M__) */
|
||||
|
||||
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
|
||||
if (DWT_CTRL & DWT_CTRL_CYCCNTENA) {
|
||||
return DWT_CYCCNT;
|
||||
} else {
|
||||
return 0; /* not supported or enabled */
|
||||
}
|
||||
#endif /* defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__) */
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
216
libopencm3/lib/cm3/nvic.c
Normal file
216
libopencm3/lib/cm3/nvic.c
Normal file
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2010 Thomas Otto <tommi@viadmin.org>
|
||||
* Copyright (C) 2012 Fergus Noble <fergusnoble@gmail.com>
|
||||
* Copyright (C) 2012 Benjamin Vernoux <titanmkd@gmail.com>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
/** @defgroup CM3_nvic_file NVIC
|
||||
*
|
||||
* @ingroup CM3_files
|
||||
*
|
||||
* @brief <b>libopencm3 Cortex Nested Vectored Interrupt Controller</b>
|
||||
*
|
||||
* @version 1.0.0
|
||||
*
|
||||
* @author @htmlonly © @endhtmlonly 2010 Thomas Otto <tommi@viadmin.org>
|
||||
* @author @htmlonly © @endhtmlonly 2012 Fergus Noble
|
||||
* <fergusnoble@gmail.com>
|
||||
*
|
||||
* @date 18 August 2012
|
||||
*
|
||||
* Cortex processors provide 14 cortex-defined interrupts (NMI, usage faults,
|
||||
* systicks etc.) and varying numbers of implementation defined interrupts
|
||||
* (typically peripherial interrupts and DMA).
|
||||
*
|
||||
* @see Cortex-M3 Devices Generic User Guide
|
||||
* @see STM32F10xxx Cortex-M3 programming manual
|
||||
*
|
||||
* LGPL License Terms @ref lgpl_license
|
||||
*/
|
||||
/**@{*/
|
||||
|
||||
#include <libopencm3/cm3/nvic.h>
|
||||
#include <libopencm3/cm3/scb.h>
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief NVIC Enable Interrupt
|
||||
*
|
||||
* Enables a user interrupt.
|
||||
*
|
||||
* @param[in] irqn Unsigned int8. Interrupt number @ref CM3_nvic_defines_irqs
|
||||
*/
|
||||
|
||||
void nvic_enable_irq(uint8_t irqn)
|
||||
{
|
||||
NVIC_ISER(irqn / 32) = (1 << (irqn % 32));
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief NVIC Disable Interrupt
|
||||
*
|
||||
* Disables a user interrupt.
|
||||
*
|
||||
* @param[in] irqn Unsigned int8. Interrupt number @ref CM3_nvic_defines_irqs
|
||||
*/
|
||||
|
||||
void nvic_disable_irq(uint8_t irqn)
|
||||
{
|
||||
NVIC_ICER(irqn / 32) = (1 << (irqn % 32));
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief NVIC Return Pending Interrupt
|
||||
*
|
||||
* True if the interrupt has occurred and is waiting for service.
|
||||
*
|
||||
* @param[in] irqn Unsigned int8. Interrupt number @ref CM3_nvic_defines_irqs
|
||||
* @return Boolean. Interrupt pending.
|
||||
*/
|
||||
|
||||
uint8_t nvic_get_pending_irq(uint8_t irqn)
|
||||
{
|
||||
return NVIC_ISPR(irqn / 32) & (1 << (irqn % 32)) ? 1 : 0;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief NVIC Set Pending Interrupt
|
||||
*
|
||||
* Force a user interrupt to a pending state. This has no effect if the
|
||||
* interrupt is already pending.
|
||||
*
|
||||
* @param[in] irqn Unsigned int8. Interrupt number @ref CM3_nvic_defines_irqs
|
||||
*/
|
||||
|
||||
void nvic_set_pending_irq(uint8_t irqn)
|
||||
{
|
||||
NVIC_ISPR(irqn / 32) = (1 << (irqn % 32));
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief NVIC Clear Pending Interrupt
|
||||
*
|
||||
* Force remove a user interrupt from a pending state. This has no effect if
|
||||
* the interrupt is actively being serviced.
|
||||
*
|
||||
* @param[in] irqn Unsigned int8. Interrupt number @ref CM3_nvic_defines_irqs
|
||||
*/
|
||||
|
||||
void nvic_clear_pending_irq(uint8_t irqn)
|
||||
{
|
||||
NVIC_ICPR(irqn / 32) = (1 << (irqn % 32));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief NVIC Return Enabled Interrupt
|
||||
*
|
||||
* @param[in] irqn Unsigned int8. Interrupt number @ref CM3_nvic_defines_irqs
|
||||
* @return Boolean. Interrupt enabled.
|
||||
*/
|
||||
|
||||
uint8_t nvic_get_irq_enabled(uint8_t irqn)
|
||||
{
|
||||
return NVIC_ISER(irqn / 32) & (1 << (irqn % 32)) ? 1 : 0;
|
||||
}
|
||||
|
||||
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
|
||||
/** @brief NVIC Set Interrupt Priority
|
||||
*
|
||||
* There are 16 priority levels only, given by the upper four bits of the
|
||||
* priority byte, as required by ARM standards. The priority levels are
|
||||
* interpreted according to the pre-emptive priority grouping set in the
|
||||
* SCB Application Interrupt and Reset Control Register (SCB_AIRCR), as done
|
||||
* in @ref scb_set_priority_grouping,
|
||||
* @param[in] irqn Interrupt number @ref CM3_nvic_defines_irqs
|
||||
* @param[in] priority Interrupt priority (0 ... 255 in steps of 16)
|
||||
*/
|
||||
#else
|
||||
/** NVIC Set Interrupt Priority.
|
||||
*
|
||||
* There are 4 priority levels only, given by the upper two bits of the
|
||||
* priority byte, as required by ARM standards. No grouping available.
|
||||
*
|
||||
* @param[in] irqn Interrupt number @ref CM3_nvic_defines_irqs
|
||||
* @param[in] priority Interrupt priority (0 ... 255 in steps of 16)
|
||||
*/
|
||||
#endif
|
||||
void nvic_set_priority(uint8_t irqn, uint8_t priority)
|
||||
{
|
||||
/* code from lpc43xx/nvic.c -- this is quite a hack and alludes to the
|
||||
* negative interrupt numbers assigned to the system interrupts. better
|
||||
* handling would mean signed integers. */
|
||||
if (irqn >= NVIC_IRQ_COUNT) {
|
||||
/* Cortex-M system interrupts */
|
||||
#if defined(__ARM_ARCH_6M__)
|
||||
/* ARM6M supports only 32bit word access to SHPR registers */
|
||||
irqn = (irqn & 0xF) - 4;
|
||||
uint8_t shift = (irqn & 0x3) << 3;
|
||||
uint8_t reg = irqn >> 2;
|
||||
SCB_SHPR32(reg) = ((SCB_SHPR32(reg) & ~(0xFFUL << shift)) |
|
||||
((uint32_t) priority) << shift);
|
||||
#else
|
||||
SCB_SHPR((irqn & 0xF) - 4) = priority;
|
||||
#endif
|
||||
} else {
|
||||
/* Device specific interrupts */
|
||||
#if defined(__ARM_ARCH_6M__)
|
||||
/* ARM6M supports only 32bit word access to IPR registers */
|
||||
uint8_t shift = (irqn & 0x3) << 3;
|
||||
uint8_t reg = irqn >> 2;
|
||||
NVIC_IPR32(reg) = ((NVIC_IPR32(reg) & ~(0xFFUL << shift)) |
|
||||
((uint32_t) priority) << shift);
|
||||
#else
|
||||
NVIC_IPR(irqn) = priority;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/* Those are defined only on CM3 or CM4 */
|
||||
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief NVIC Return Active Interrupt
|
||||
*
|
||||
* Interrupt has occurred and is currently being serviced.
|
||||
*
|
||||
* @param[in] irqn Unsigned int8. Interrupt number @ref CM3_nvic_defines_irqs
|
||||
* @return Boolean. Interrupt active.
|
||||
*/
|
||||
|
||||
uint8_t nvic_get_active_irq(uint8_t irqn)
|
||||
{
|
||||
return NVIC_IABR(irqn / 32) & (1 << (irqn % 32)) ? 1 : 0;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief NVIC Software Trigger Interrupt
|
||||
*
|
||||
* Generate an interrupt from software. This has no effect for unprivileged
|
||||
* access unless the privilege level has been elevated through the System
|
||||
* Control Registers.
|
||||
*
|
||||
* @param[in] irqn Unsigned int16. Interrupt number (0 ... 239)
|
||||
*/
|
||||
|
||||
void nvic_generate_software_interrupt(uint16_t irqn)
|
||||
{
|
||||
if (irqn <= 239) {
|
||||
NVIC_STIR |= irqn;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/**@}*/
|
||||
69
libopencm3/lib/cm3/scb.c
Normal file
69
libopencm3/lib/cm3/scb.c
Normal file
@@ -0,0 +1,69 @@
|
||||
/** @defgroup CM3_scb_file SCB
|
||||
*
|
||||
* @ingroup CM3_files
|
||||
*
|
||||
* @brief <b>libopencm3 Cortex-M System Control Block</b>
|
||||
*
|
||||
* The System Control Block (SCB) is a section of the System Control Space
|
||||
* which provides status information and control features for the processor core.
|
||||
* It allows, amongst other:
|
||||
* * software reset control
|
||||
* * exception management and grouping
|
||||
* * fault information
|
||||
* * power management
|
||||
* * debug status information
|
||||
*
|
||||
* @see ARMv7m Architecture Reference Manual (Chapter B3.2.1 About the SCB)
|
||||
*
|
||||
* LGPL License Terms @ref lgpl_license
|
||||
* @{
|
||||
*/
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2010 Gareth McMullin <gareth@blacksphere.co.nz>
|
||||
*
|
||||
* 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 <stdlib.h>
|
||||
|
||||
#include <libopencm3/cm3/scb.h>
|
||||
|
||||
/* Those are defined only on CM3 or CM4 */
|
||||
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
|
||||
void scb_reset_core(void)
|
||||
{
|
||||
SCB_AIRCR = SCB_AIRCR_VECTKEY | SCB_AIRCR_VECTRESET;
|
||||
|
||||
while (1);
|
||||
}
|
||||
#endif
|
||||
|
||||
void scb_reset_system(void)
|
||||
{
|
||||
SCB_AIRCR = SCB_AIRCR_VECTKEY | SCB_AIRCR_SYSRESETREQ;
|
||||
|
||||
while (1);
|
||||
}
|
||||
|
||||
/* Those are defined only on CM3 or CM4 */
|
||||
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
|
||||
void scb_set_priority_grouping(uint32_t prigroup)
|
||||
{
|
||||
SCB_AIRCR = SCB_AIRCR_VECTKEY | prigroup;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**@}*/
|
||||
79
libopencm3/lib/cm3/sync.c
Normal file
79
libopencm3/lib/cm3/sync.c
Normal file
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2012 Fergus Noble <fergusnoble@gmail.com>
|
||||
*
|
||||
* 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/cm3/sync.h>
|
||||
|
||||
/* DMB is supported on CM0 */
|
||||
void __dmb()
|
||||
{
|
||||
__asm__ volatile ("dmb");
|
||||
}
|
||||
|
||||
/* Those are defined only on CM3 or CM4 */
|
||||
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
|
||||
|
||||
uint32_t __ldrex(volatile uint32_t *addr)
|
||||
{
|
||||
uint32_t res;
|
||||
__asm__ volatile ("ldrex %0, [%1]" : "=r" (res) : "r" (addr));
|
||||
return res;
|
||||
}
|
||||
|
||||
uint32_t __strex(uint32_t val, volatile uint32_t *addr)
|
||||
{
|
||||
uint32_t res;
|
||||
__asm__ volatile ("strex %0, %2, [%1]"
|
||||
: "=&r" (res) : "r" (addr), "r" (val));
|
||||
return res;
|
||||
}
|
||||
|
||||
void mutex_lock(mutex_t *m)
|
||||
{
|
||||
while (!mutex_trylock(m));
|
||||
}
|
||||
|
||||
/* returns 1 if the lock was acquired */
|
||||
uint32_t mutex_trylock(mutex_t *m)
|
||||
{
|
||||
uint32_t status = 1;
|
||||
|
||||
/* If the mutex is unlocked. */
|
||||
if (__ldrex(m) == MUTEX_UNLOCKED) {
|
||||
/* Try to lock it. */
|
||||
status = __strex(MUTEX_LOCKED, m);
|
||||
}
|
||||
|
||||
/* Execute the mysterious Data Memory Barrier instruction! */
|
||||
__dmb();
|
||||
|
||||
/* Did we get the lock? If not then try again
|
||||
* by calling this function once more. */
|
||||
return status == 0;
|
||||
}
|
||||
|
||||
void mutex_unlock(mutex_t *m)
|
||||
{
|
||||
/* Ensure accesses to protected resource are finished */
|
||||
__dmb();
|
||||
|
||||
/* Free the lock. */
|
||||
*m = MUTEX_UNLOCKED;
|
||||
}
|
||||
|
||||
#endif
|
||||
203
libopencm3/lib/cm3/systick.c
Normal file
203
libopencm3/lib/cm3/systick.c
Normal file
@@ -0,0 +1,203 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2010 Thomas Otto <tommi@viadmin.org>
|
||||
* Copyright (C) 2012 Benjamin Vernoux <titanmkd@gmail.com>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
/** @defgroup CM3_systick_file SysTick
|
||||
*
|
||||
* @ingroup CM3_files
|
||||
*
|
||||
* @brief <b>libopencm3 Cortex System Tick Timer</b>
|
||||
*
|
||||
* @version 1.0.0
|
||||
*
|
||||
* @author @htmlonly © @endhtmlonly 2010 Thomas Otto <tommi@viadmin.org>
|
||||
*
|
||||
* @date 19 August 2012
|
||||
*
|
||||
* This library supports the System Tick timer in ARM Cortex Microcontrollers.
|
||||
*
|
||||
* The System Tick timer is part of the ARM Cortex core. It is a 24 bit
|
||||
* down counter that can be configured with an automatical reload value.
|
||||
*
|
||||
* LGPL License Terms @ref lgpl_license
|
||||
*/
|
||||
|
||||
/**@{*/
|
||||
#include <libopencm3/cm3/systick.h>
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief SysTick Set the Automatic Reload Value.
|
||||
*
|
||||
* The counter is set to the reload value when the counter starts and after it
|
||||
* reaches zero.
|
||||
*
|
||||
* @note The systick counter value might be undefined upon startup. To get
|
||||
* predictable behavior, it is a good idea to set or clear the counter after
|
||||
* set reload. @sa systick_clear
|
||||
*
|
||||
* @param[in] value uint32_t. 24 bit reload value.
|
||||
*/
|
||||
|
||||
void systick_set_reload(uint32_t value)
|
||||
{
|
||||
STK_RVR = (value & STK_RVR_RELOAD);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief SysTick Read the Automatic Reload Value.
|
||||
*
|
||||
* @returns 24 bit reload value as uint32_t.
|
||||
*/
|
||||
|
||||
uint32_t systick_get_reload(void)
|
||||
{
|
||||
return STK_RVR & STK_RVR_RELOAD;
|
||||
}
|
||||
|
||||
/** @brief SysTick Set clock and frequency of overflow
|
||||
*
|
||||
* This function sets the systick to AHB clock source, and the prescaler to
|
||||
* generate interrupts with the desired frequency. The function fails, if
|
||||
* the frequency is too low.
|
||||
*
|
||||
* @param[in] freq uint32_t The desired frequency in Hz
|
||||
* @param[in] ahb uint32_t The current AHB frequency in Hz
|
||||
* @returns true, if success, false if the desired frequency cannot be set.
|
||||
*/
|
||||
bool systick_set_frequency(uint32_t freq, uint32_t ahb)
|
||||
{
|
||||
uint32_t ratio = ahb / freq;
|
||||
|
||||
#if defined(__ARM_ARCH_6M__)
|
||||
systick_set_clocksource(STK_CSR_CLKSOURCE_AHB);
|
||||
#else
|
||||
if (ratio >= (STK_RVR_RELOAD * 8)) {
|
||||
/* This frequency is too slow */
|
||||
return false;
|
||||
} else if (ratio >= STK_RVR_RELOAD) {
|
||||
ratio /= 8;
|
||||
systick_set_clocksource(STK_CSR_CLKSOURCE_AHB_DIV8);
|
||||
} else {
|
||||
systick_set_clocksource(STK_CSR_CLKSOURCE_AHB);
|
||||
}
|
||||
#endif
|
||||
systick_set_reload(ratio - 1);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Get the current SysTick counter value.
|
||||
*
|
||||
* @returns 24 bit current value as uint32_t.
|
||||
*/
|
||||
|
||||
uint32_t systick_get_value(void)
|
||||
{
|
||||
return STK_CVR & STK_CVR_CURRENT;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Set the SysTick Clock Source.
|
||||
*
|
||||
* The clock source can be either the AHB clock or the same clock divided by 8.
|
||||
*
|
||||
* @param[in] clocksource uint8_t. Clock source from @ref systick_clksource.
|
||||
*/
|
||||
|
||||
void systick_set_clocksource(uint8_t clocksource)
|
||||
{
|
||||
STK_CSR = (STK_CSR & ~STK_CSR_CLKSOURCE) |
|
||||
(clocksource & STK_CSR_CLKSOURCE);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Enable SysTick Interrupt.
|
||||
*
|
||||
*/
|
||||
|
||||
void systick_interrupt_enable(void)
|
||||
{
|
||||
STK_CSR |= STK_CSR_TICKINT;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Disable SysTick Interrupt.
|
||||
*
|
||||
*/
|
||||
|
||||
void systick_interrupt_disable(void)
|
||||
{
|
||||
STK_CSR &= ~STK_CSR_TICKINT;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Enable SysTick Counter.
|
||||
*
|
||||
*/
|
||||
|
||||
void systick_counter_enable(void)
|
||||
{
|
||||
STK_CSR |= STK_CSR_ENABLE;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Disable SysTick Counter.
|
||||
*
|
||||
*/
|
||||
|
||||
void systick_counter_disable(void)
|
||||
{
|
||||
STK_CSR &= ~STK_CSR_ENABLE;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief SysTick Read the Counter Flag.
|
||||
*
|
||||
* The count flag is set when the timer count becomes zero, and is cleared when
|
||||
* the flag is read.
|
||||
*
|
||||
* @returns Boolean if flag set.
|
||||
*/
|
||||
|
||||
uint8_t systick_get_countflag(void)
|
||||
{
|
||||
return (STK_CSR & STK_CSR_COUNTFLAG) ? 1 : 0;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief SysTick Clear counter Value.
|
||||
*
|
||||
* The counter value is cleared. Useful for well defined startup.
|
||||
*/
|
||||
|
||||
void systick_clear(void)
|
||||
{
|
||||
STK_CVR = 0;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief SysTick Get Calibration Value
|
||||
*
|
||||
* @returns Current calibration value
|
||||
*/
|
||||
uint32_t systick_get_calib(void)
|
||||
{
|
||||
return STK_CALIB & STK_CALIB_TENMS;
|
||||
}
|
||||
/**@}*/
|
||||
|
||||
125
libopencm3/lib/cm3/vector.c
Normal file
125
libopencm3/lib/cm3/vector.c
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2010 Piotr Esden-Tempski <piotr@esden.net>,
|
||||
* Copyright (C) 2012 chrysn <chrysn@fsfe.org>
|
||||
*
|
||||
* 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/cm3/scb.h>
|
||||
#include <libopencm3/cm3/vector.h>
|
||||
|
||||
/* load optional platform dependent initialization routines */
|
||||
#include "../dispatch/vector_chipset.c"
|
||||
/* load the weak symbols for IRQ_HANDLERS */
|
||||
#include "../dispatch/vector_nvic.c"
|
||||
|
||||
/* Less common symbols exported by the linker script(s): */
|
||||
typedef void (*funcp_t) (void);
|
||||
extern funcp_t __preinit_array_start, __preinit_array_end;
|
||||
extern funcp_t __init_array_start, __init_array_end;
|
||||
extern funcp_t __fini_array_start, __fini_array_end;
|
||||
|
||||
int main(void);
|
||||
void blocking_handler(void);
|
||||
void null_handler(void);
|
||||
|
||||
__attribute__ ((section(".vectors")))
|
||||
vector_table_t vector_table = {
|
||||
.initial_sp_value = &_stack,
|
||||
.reset = reset_handler,
|
||||
.nmi = nmi_handler,
|
||||
.hard_fault = hard_fault_handler,
|
||||
|
||||
/* Those are defined only on CM3 or CM4 */
|
||||
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
|
||||
.memory_manage_fault = mem_manage_handler,
|
||||
.bus_fault = bus_fault_handler,
|
||||
.usage_fault = usage_fault_handler,
|
||||
.debug_monitor = debug_monitor_handler,
|
||||
#endif
|
||||
|
||||
.sv_call = sv_call_handler,
|
||||
.pend_sv = pend_sv_handler,
|
||||
.systick = sys_tick_handler,
|
||||
.irq = {
|
||||
IRQ_HANDLERS
|
||||
}
|
||||
};
|
||||
|
||||
void __attribute__ ((weak)) reset_handler(void)
|
||||
{
|
||||
volatile unsigned *src, *dest;
|
||||
funcp_t *fp;
|
||||
|
||||
for (src = &_data_loadaddr, dest = &_data;
|
||||
dest < &_edata;
|
||||
src++, dest++) {
|
||||
*dest = *src;
|
||||
}
|
||||
|
||||
while (dest < &_ebss) {
|
||||
*dest++ = 0;
|
||||
}
|
||||
|
||||
/* Ensure 8-byte alignment of stack pointer on interrupts */
|
||||
/* Enabled by default on most Cortex-M parts, but not M3 r1 */
|
||||
SCB_CCR |= SCB_CCR_STKALIGN;
|
||||
|
||||
/* might be provided by platform specific vector.c */
|
||||
pre_main();
|
||||
|
||||
/* Constructors. */
|
||||
for (fp = &__preinit_array_start; fp < &__preinit_array_end; fp++) {
|
||||
(*fp)();
|
||||
}
|
||||
for (fp = &__init_array_start; fp < &__init_array_end; fp++) {
|
||||
(*fp)();
|
||||
}
|
||||
|
||||
/* Call the application's entry point. */
|
||||
(void)main();
|
||||
|
||||
/* Destructors. */
|
||||
for (fp = &__fini_array_start; fp < &__fini_array_end; fp++) {
|
||||
(*fp)();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void blocking_handler(void)
|
||||
{
|
||||
while (1);
|
||||
}
|
||||
|
||||
void null_handler(void)
|
||||
{
|
||||
/* Do nothing. */
|
||||
}
|
||||
|
||||
#pragma weak nmi_handler = null_handler
|
||||
#pragma weak hard_fault_handler = blocking_handler
|
||||
#pragma weak sv_call_handler = null_handler
|
||||
#pragma weak pend_sv_handler = null_handler
|
||||
#pragma weak sys_tick_handler = null_handler
|
||||
|
||||
/* Those are defined only on CM3 or CM4 */
|
||||
#if defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7EM__)
|
||||
#pragma weak mem_manage_handler = blocking_handler
|
||||
#pragma weak bus_fault_handler = blocking_handler
|
||||
#pragma weak usage_fault_handler = blocking_handler
|
||||
#pragma weak debug_monitor_handler = null_handler
|
||||
#endif
|
||||
|
||||
125
libopencm3/lib/cortex-m-generic.ld
Normal file
125
libopencm3/lib/cortex-m-generic.ld
Normal file
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is a generic linker script for Cortex-M targets using libopencm3.
|
||||
*
|
||||
* Memory regions MUST be defined in the ld script which includes this one!
|
||||
* Example:
|
||||
|
||||
MEMORY
|
||||
{
|
||||
rom (rx) : ORIGIN = 0x08000000, LENGTH = 256K
|
||||
ram (rwx) : ORIGIN = 0x20000000, LENGTH = 16K
|
||||
}
|
||||
|
||||
INCLUDE cortex-m-generic.ld
|
||||
|
||||
*/
|
||||
|
||||
/* 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 = .;
|
||||
|
||||
/* ram, but not cleared on reset, eg boot/app comms */
|
||||
.noinit (NOLOAD) : {
|
||||
*(.noinit*)
|
||||
} >ram
|
||||
. = ALIGN(4);
|
||||
|
||||
.data : {
|
||||
_data = .;
|
||||
*(.data*) /* Read-write initialized data */
|
||||
*(.ramtext*) /* "text" functions to run in ram */
|
||||
. = 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));
|
||||
|
||||
29
libopencm3/lib/dispatch/vector_chipset.c
Normal file
29
libopencm3/lib/dispatch/vector_chipset.c
Normal file
@@ -0,0 +1,29 @@
|
||||
#if defined(STM32F3)
|
||||
# include "../stm32/f3/vector_chipset.c"
|
||||
#elif defined(STM32F4)
|
||||
# include "../stm32/f4/vector_chipset.c"
|
||||
#elif defined(STM32F7)
|
||||
# include "../stm32/f7/vector_chipset.c"
|
||||
#elif defined(STM32G4)
|
||||
# include "../stm32/g4/vector_chipset.c"
|
||||
#elif defined(STM32H7)
|
||||
# include "../stm32/h7/vector_chipset.c"
|
||||
#elif defined(STM32L4)
|
||||
# include "../stm32/l4/vector_chipset.c"
|
||||
#elif defined(LM4F)
|
||||
# include "../lm4f/vector_chipset.c"
|
||||
#elif defined(LPC43XX_M4)
|
||||
# include "../lpc43xx/m4/vector_chipset.c"
|
||||
#elif defined(VF6XX)
|
||||
# include "../vf6xx/vector_chipset.c"
|
||||
#elif defined(EFM32WG)
|
||||
# include "../efm32/wg/vector_chipset.c"
|
||||
#elif defined(EZR32WG)
|
||||
# include "../efm32/ezr32wg/vector_chipset.c"
|
||||
#elif defined(PAC55XX)
|
||||
# include "../pac55xx/vector_chipset.c"
|
||||
#else
|
||||
|
||||
static void pre_main(void) {}
|
||||
|
||||
#endif
|
||||
96
libopencm3/lib/dispatch/vector_nvic.c
Normal file
96
libopencm3/lib/dispatch/vector_nvic.c
Normal file
@@ -0,0 +1,96 @@
|
||||
#if defined(STM32F0)
|
||||
# include "../stm32/f0/vector_nvic.c"
|
||||
#elif defined(STM32F1)
|
||||
# include "../stm32/f1/vector_nvic.c"
|
||||
#elif defined(STM32F2)
|
||||
# include "../stm32/f2/vector_nvic.c"
|
||||
#elif defined(STM32F3)
|
||||
# include "../stm32/f3/vector_nvic.c"
|
||||
#elif defined(STM32F4)
|
||||
# include "../stm32/f4/vector_nvic.c"
|
||||
#elif defined(STM32F7)
|
||||
# include "../stm32/f7/vector_nvic.c"
|
||||
#elif defined(STM32L0)
|
||||
# include "../stm32/l0/vector_nvic.c"
|
||||
#elif defined(STM32L1)
|
||||
# include "../stm32/l1/vector_nvic.c"
|
||||
#elif defined(STM32L4)
|
||||
# include "../stm32/l4/vector_nvic.c"
|
||||
#elif defined(STM32G0)
|
||||
# include "../stm32/g0/vector_nvic.c"
|
||||
#elif defined(STM32G4)
|
||||
# include "../stm32/g4/vector_nvic.c"
|
||||
#elif defined(STM32H7)
|
||||
# include "../stm32/h7/vector_nvic.c"
|
||||
|
||||
#elif defined(GD32F1X0)
|
||||
# include "../gd32/f1x0/vector_nvic.c"
|
||||
|
||||
#elif defined(EFM32TG)
|
||||
# include "../efm32/tg/vector_nvic.c"
|
||||
#elif defined(EFM32G)
|
||||
# include "../efm32/g/vector_nvic.c"
|
||||
#elif defined(EFM32LG)
|
||||
# include "../efm32/lg/vector_nvic.c"
|
||||
#elif defined(EFM32GG)
|
||||
# include "../efm32/gg/vector_nvic.c"
|
||||
#elif defined(EFM32HG)
|
||||
# include "../efm32/hg/vector_nvic.c"
|
||||
#elif defined(EFM32WG)
|
||||
# include "../efm32/wg/vector_nvic.c"
|
||||
#elif defined(EZR32WG)
|
||||
# include "../efm32/ezr32wg/vector_nvic.c"
|
||||
|
||||
#elif defined(LPC13XX)
|
||||
# include "../lpc13xx/vector_nvic.c"
|
||||
#elif defined(LPC17XX)
|
||||
# include "../lpc17xx/vector_nvic.c"
|
||||
#elif defined(LPC43XX_M4)
|
||||
# include "../lpc43xx/m4/vector_nvic.c"
|
||||
#elif defined(LPC43XX_M0)
|
||||
# include "../lpc43xx/m0/vector_nvic.c"
|
||||
|
||||
#elif defined(NRF51)
|
||||
# include "../nrf/51/vector_nvic.c"
|
||||
#elif defined(NRF52)
|
||||
# include "../nrf/52/vector_nvic.c"
|
||||
|
||||
#elif defined(SAM3A)
|
||||
# include "../sam/3a/vector_nvic.c"
|
||||
#elif defined(SAM3N)
|
||||
# include "../sam/3n/vector_nvic.c"
|
||||
#elif defined(SAM3S)
|
||||
# include "../sam/3s/vector_nvic.c"
|
||||
#elif defined(SAM3U)
|
||||
# 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"
|
||||
|
||||
#elif defined(VF6XX)
|
||||
# include "../vf6xx/vector_nvic.c"
|
||||
|
||||
#elif defined(PAC55XX)
|
||||
# include "../pac55xx/vector_nvic.c"
|
||||
|
||||
|
||||
#elif defined(LM3S) || defined(LM4F)
|
||||
/* Yes, we use the same interrupt table for both LM3S and LM4F */
|
||||
# include "../lm3s/vector_nvic.c"
|
||||
|
||||
#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"
|
||||
|
||||
#define IRQ_HANDLERS
|
||||
|
||||
#endif
|
||||
15
libopencm3/lib/efm32/common/acmp_common.c
Normal file
15
libopencm3/lib/efm32/common/acmp_common.c
Normal file
@@ -0,0 +1,15 @@
|
||||
/** @addtogroup acmp_file ACMP peripheral API
|
||||
* @ingroup peripheral_apis
|
||||
* @brief Analog Comparator helper functions.
|
||||
*
|
||||
* <b>NO</b> helper functions exist. Only header definitions are available.
|
||||
* Delete these lines if/when you add actual helper APIs.
|
||||
* @copyright See @ref lgpl_license
|
||||
*/
|
||||
|
||||
#include <libopencm3/efm32/acmp.h>
|
||||
|
||||
/**@{*/
|
||||
|
||||
/**@}*/
|
||||
|
||||
678
libopencm3/lib/efm32/common/adc_common.c
Normal file
678
libopencm3/lib/efm32/common/adc_common.c
Normal file
@@ -0,0 +1,678 @@
|
||||
/** @addtogroup adc_file ADC peripheral API
|
||||
* @ingroup peripheral_apis
|
||||
*/
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2015 Kuldeep Singh Dhaka <kuldeepdhaka9@gmail.com>
|
||||
*
|
||||
* 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/efm32/adc.h>
|
||||
|
||||
/**@{*/
|
||||
|
||||
/**
|
||||
* Set ADC over sampling
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
* @param[in] oversamp Oversampling (use ADC_CTRL_OVERSEL_Xx)
|
||||
*/
|
||||
void adc_set_oversampling(uint32_t adc, uint32_t oversamp)
|
||||
{
|
||||
ADC_CTRL(adc) = (ADC_CTRL(adc) & ~ADC_CTRL_OVERSEL_MASK) | oversamp;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set ADC warm up
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
* @param[in] clocks Clock cycles (1 - 128)
|
||||
* @note warm-up-time = (@a clocks / HFPERCLK)
|
||||
*/
|
||||
void adc_set_warm_up(uint32_t adc, uint8_t clocks)
|
||||
{
|
||||
uint32_t timebase = ADC_CTRL_TIMEBASE(clocks - 1);
|
||||
ADC_CTRL(adc) = (ADC_CTRL(adc) & ~ADC_CTRL_TIMEBASE_MASK) | timebase;
|
||||
}
|
||||
|
||||
/** Clock division factor
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
* @param[in] factor Factor (1 - 128)
|
||||
* @note output-clock = input-clock / @a factor
|
||||
*/
|
||||
void adc_set_clock_prescaler(uint32_t adc, uint8_t factor)
|
||||
{
|
||||
uint32_t presc = ADC_CTRL_PRESC(factor - 1);
|
||||
ADC_CTRL(adc) = (ADC_CTRL(adc) & ~ADC_CTRL_PRESC_MASK) | presc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set low pass filter mode
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
* @param[in] lpfmode Low pass filter mode (use ADC_CTRL_LPFMODE_*)
|
||||
*/
|
||||
void adc_set_lowpass_filter(uint32_t adc, uint32_t lpfmode)
|
||||
{
|
||||
ADC_CTRL(adc) = (ADC_CTRL(adc) & ~ADC_CTRL_LPFMODE_MASK) | lpfmode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable tail gating
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
*/
|
||||
void adc_enable_tailgating(uint32_t adc)
|
||||
{
|
||||
ADC_CTRL(adc) |= ADC_CTRL_TAILGATE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable tail gating
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
*/
|
||||
void adc_disable_tailgating(uint32_t adc)
|
||||
{
|
||||
ADC_CTRL(adc) &= ~ADC_CTRL_TAILGATE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set warm up mode
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
* @param[in] warmupmode Warm Up Mode (use ADC_CTRL_WARMUPMODE_*)
|
||||
*/
|
||||
void adc_set_warm_up_mode(uint32_t adc, uint32_t warmupmode)
|
||||
{
|
||||
ADC_CTRL(adc) = (ADC_CTRL(adc) & ~ADC_CTRL_WARMUPMODE_MASK)
|
||||
| warmupmode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start ADC in single acquisition
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
*/
|
||||
void adc_single_start(uint32_t adc)
|
||||
{
|
||||
ADC_CMD(adc) = ADC_CMD_SINGLESTART;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop ADC in single acquisition
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
*/
|
||||
void adc_single_stop(uint32_t adc)
|
||||
{
|
||||
ADC_CMD(adc) = ADC_CMD_SINGLESTOP;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start ADC in scan acquisition
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
*/
|
||||
void adc_scan_start(uint32_t adc)
|
||||
{
|
||||
ADC_CMD(adc) = ADC_CMD_SCANSTART;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop ADC in scan acquisition
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
*/
|
||||
void adc_scan_stop(uint32_t adc)
|
||||
{
|
||||
ADC_CMD(adc) = ADC_CMD_SCANSTOP;
|
||||
}
|
||||
|
||||
/* Single ----------------------------------------------------------- */
|
||||
/**
|
||||
* Set single PRS trigger
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
* @param[in] prssel PRS Selected (use PRS_CHx)
|
||||
*/
|
||||
void adc_set_single_prs_trigger(uint32_t adc, uint8_t prssel)
|
||||
{
|
||||
ADC_SINGLECTRL(adc) =
|
||||
(ADC_SINGLECTRL(adc) & ~ADC_SINGLECTRL_PRSSEL_MASK) |
|
||||
(ADC_SINGLECTRL_PRSSEL_PRSCHx(prssel));
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable single PRS Triggering
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
*/
|
||||
void adc_enable_single_prs_trigger(uint32_t adc)
|
||||
{
|
||||
ADC_SINGLECTRL(adc) |= ADC_SINGLECTRL_PRSEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable single PRS Triggering
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
*/
|
||||
void adc_disable_single_prs_trigger(uint32_t adc)
|
||||
{
|
||||
ADC_SINGLECTRL(adc) &= ~ADC_SINGLECTRL_PRSEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set single acquisition cycle
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
* @param[in] at Acquisition time (use ADC_SINGLECTRL_AT_x)
|
||||
*/
|
||||
void adc_set_single_acquisition_cycle(uint32_t adc, uint32_t at)
|
||||
{
|
||||
ADC_SINGLECTRL(adc) =
|
||||
(ADC_SINGLECTRL(adc) & ~ADC_SINGLECTRL_AT_MASK) | at;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set single reference for acquisition
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
* @param[in] ref Reference (use ADC_SINGLECTRL_REF_x)
|
||||
*/
|
||||
void adc_set_single_reference(uint32_t adc, uint32_t ref)
|
||||
{
|
||||
ADC_SINGLECTRL(adc) =
|
||||
(ADC_SINGLECTRL(adc) & ~ADC_SINGLECTRL_REF_MASK) | ref;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set single channel
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
* @param[in] ch Channel (use ADC_CHx and ADC_CH_*)
|
||||
*/
|
||||
void adc_set_single_channel(uint32_t adc, uint8_t ch)
|
||||
{
|
||||
ADC_SINGLECTRL(adc) =
|
||||
(ADC_SINGLECTRL(adc) & ~ADC_SINGLECTRL_INPUTSEL_MASK) |
|
||||
ADC_SINGLECTRL_INPUTSEL(ch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set single resolution of conversion
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
* @param[in] res Resolution (use ADC_SINGLECTRL_RES_*)
|
||||
*/
|
||||
void adc_set_single_resolution(uint32_t adc, uint32_t res)
|
||||
{
|
||||
ADC_SINGLECTRL(adc) =
|
||||
(ADC_SINGLECTRL(adc) & ~ADC_SINGLECTRL_RES_MASK) | res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set single left aligned output
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
*/
|
||||
void adc_set_single_left_aligned(uint32_t adc)
|
||||
{
|
||||
ADC_SINGLECTRL(adc) |= ADC_SINGLECTRL_ADJ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set single right aligned output
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
*/
|
||||
void adc_set_single_right_aligned(uint32_t adc)
|
||||
{
|
||||
ADC_SINGLECTRL(adc) &= ~ADC_SINGLECTRL_ADJ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set single single-ended conversion
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
*/
|
||||
void adc_set_single_single_ended(uint32_t adc)
|
||||
{
|
||||
ADC_SINGLECTRL(adc) &= ~ADC_SINGLECTRL_DIFF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set single differential conversion
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
*/
|
||||
void adc_set_single_differential(uint32_t adc)
|
||||
{
|
||||
ADC_SINGLECTRL(adc) |= ADC_SINGLECTRL_DIFF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable single channel repeated conversion
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
*/
|
||||
void adc_enable_single_repeat_conv(uint32_t adc)
|
||||
{
|
||||
ADC_SINGLECTRL(adc) |= ADC_SINGLECTRL_REP;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable single repeated conversion
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
*/
|
||||
void adc_disable_single_repeat_conv(uint32_t adc)
|
||||
{
|
||||
ADC_SINGLECTRL(adc) &= ~ADC_SINGLECTRL_REP;
|
||||
}
|
||||
|
||||
/* Scan ------------------------------------------------------------- */
|
||||
/**
|
||||
* Set scan PRS trigger
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
* @param[in] prssel PRS Selected (use PRS_CHx)
|
||||
*/
|
||||
void adc_set_scan_prs_trigger(uint32_t adc, uint8_t prssel)
|
||||
{
|
||||
ADC_SCANCTRL(adc) =
|
||||
(ADC_SCANCTRL(adc) & ~ADC_SCANCTRL_PRSSEL_MASK) |
|
||||
ADC_SCANCTRL_PRSSEL_PRSCHx(prssel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable scan PRS Triggering
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
*/
|
||||
void adc_enable_scan_prs_trigger(uint32_t adc)
|
||||
{
|
||||
ADC_SCANCTRL(adc) |= ADC_SCANCTRL_PRSEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable scan PRS Triggering
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
*/
|
||||
void adc_disable_scan_prs_trigger(uint32_t adc)
|
||||
{
|
||||
ADC_SCANCTRL(adc) &= ~ADC_SCANCTRL_PRSEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set scan acquisition cycle
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
* @param[in] at Acquisition time (use ADC_SCANCTRL_AT_x)
|
||||
*/
|
||||
void adc_set_scan_acquisition_cycle(uint32_t adc, uint32_t at)
|
||||
{
|
||||
ADC_SCANCTRL(adc) =
|
||||
(ADC_SCANCTRL(adc) & ~ADC_SCANCTRL_AT_MASK) | at;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set scan reference for acquisition
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
* @param[in] ref Reference (use ADC_SCANCTRL_REF_x)
|
||||
*/
|
||||
void adc_set_scan_reference(uint32_t adc, uint32_t ref)
|
||||
{
|
||||
ADC_SCANCTRL(adc) =
|
||||
(ADC_SCANCTRL(adc) & ~ADC_SCANCTRL_REF_MASK) | ref;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set scan channel list
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
* @param[in] length Length of @a channel
|
||||
* @param[in] channel channel list (use ADC_CHx)
|
||||
* @note channel[0] is used as single acuqisition
|
||||
*/
|
||||
void adc_set_scan_channel(uint32_t adc, uint8_t length, uint8_t channel[])
|
||||
{
|
||||
unsigned i;
|
||||
uint32_t val = 0;
|
||||
|
||||
for (i = 0; i < length; i++) {
|
||||
val |= 1 << (channel[i] + ADC_SCANCTRL_INPUTSEL_SHIFT);
|
||||
}
|
||||
|
||||
ADC_SCANCTRL(adc) =
|
||||
(ADC_SCANCTRL(adc) & ~ADC_SCANCTRL_INPUTSEL_MASK) |
|
||||
(val & ADC_SCANCTRL_INPUTSEL_MASK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set scan resolution of conversion
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
* @param[in] res Resolution (use ADC_SCANCTRL_RES_*)
|
||||
*/
|
||||
void adc_set_scan_resolution(uint32_t adc, uint32_t res)
|
||||
{
|
||||
ADC_SCANCTRL(adc) =
|
||||
(ADC_SCANCTRL(adc) & ~ADC_SCANCTRL_RES_MASK) | res;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set scan left aligned output
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
*/
|
||||
void adc_set_scan_left_aligned(uint32_t adc)
|
||||
{
|
||||
ADC_SCANCTRL(adc) |= ADC_SCANCTRL_ADJ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set scan right aligned output
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
*/
|
||||
void adc_set_scan_right_aligned(uint32_t adc)
|
||||
{
|
||||
ADC_SCANCTRL(adc) &= ~ADC_SCANCTRL_ADJ;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set scan single ended conversion
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
*/
|
||||
void adc_set_scan_single_ended(uint32_t adc)
|
||||
{
|
||||
ADC_SCANCTRL(adc) &= ~ADC_SCANCTRL_DIFF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set scan differential conversion
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
*/
|
||||
void adc_set_scan_differential(uint32_t adc)
|
||||
{
|
||||
ADC_SCANCTRL(adc) |= ADC_SCANCTRL_DIFF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable scan repeated conversion
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
* @note In SINGLE mode, channel is repeated
|
||||
* @note In SCAN mode, channel sequence is repeated
|
||||
*/
|
||||
void adc_enable_scan_repeat_conv(uint32_t adc)
|
||||
{
|
||||
ADC_SCANCTRL(adc) |= ADC_SCANCTRL_REP;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable scan repeated conversion
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
*/
|
||||
void adc_disable_scan_repeat_conv(uint32_t adc)
|
||||
{
|
||||
ADC_SCANCTRL(adc) &= ~ADC_SCANCTRL_REP;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable single result overflow interrupt
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
*/
|
||||
void adc_enable_single_result_overflow_interrupt(uint32_t adc)
|
||||
{
|
||||
ADC_IEN(adc) |= ADC_IEN_SINGLEOF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable single result overflow interrupt
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
*/
|
||||
void adc_disable_single_result_overflow_interrupt(uint32_t adc)
|
||||
{
|
||||
ADC_IEN(adc) &= ~ADC_IEN_SINGLEOF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable single conversion complete interrupt
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
*/
|
||||
void adc_enable_single_conversion_complete_interrupt(uint32_t adc)
|
||||
{
|
||||
ADC_IEN(adc) |= ADC_IEN_SINGLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable single conversion complete interrupt
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
*/
|
||||
void adc_disable_single_conversion_complete_interrupt(uint32_t adc)
|
||||
{
|
||||
ADC_IEN(adc) &= ~ADC_IEN_SINGLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable scan result overflow interrupt
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
*/
|
||||
void adc_enable_scan_result_overflow_interrupt(uint32_t adc)
|
||||
{
|
||||
ADC_IEN(adc) |= ADC_IEN_SCANOF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable scan result overflow interrupt
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
*/
|
||||
void adc_disable_scan_result_overflow_interrupt(uint32_t adc)
|
||||
{
|
||||
ADC_IEN(adc) &= ~ADC_IEN_SCANOF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable scan conversion complete interrupt
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
*/
|
||||
void adc_enable_scan_conversion_complete_interrupt(uint32_t adc)
|
||||
{
|
||||
ADC_IEN(adc) |= ADC_IEN_SCAN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable scan conversion complete interrupt
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
*/
|
||||
void adc_disable_scan_conversion_complete_interrupt(uint32_t adc)
|
||||
{
|
||||
ADC_IEN(adc) &= ~ADC_IEN_SCAN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get single result overflow flag
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
* @retval true if flag set
|
||||
* @retval false if flag is not set
|
||||
*/
|
||||
bool adc_get_single_result_overflow_flag(uint32_t adc)
|
||||
{
|
||||
return (ADC_IF(adc) & ADC_IF_SCANOF) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get single conversion complete flag
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
* @retval true if flag set
|
||||
* @retval false if flag is not set
|
||||
*/
|
||||
bool adc_get_single_conversion_complete_flag(uint32_t adc)
|
||||
{
|
||||
return (ADC_IF(adc) & ADC_IF_SINGLE) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get scan result overflow flag
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
* @retval true if flag set
|
||||
* @retval false if flag is not set
|
||||
*/
|
||||
bool adc_get_scan_result_overflow_flag(uint32_t adc)
|
||||
{
|
||||
return (ADC_IF(adc) & ADC_IF_SCANOF) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get scan conversion complete flag
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
* @retval true if flag is set
|
||||
* @retval false if flag is not set
|
||||
*/
|
||||
bool adc_get_scan_conversion_complete_flag(uint32_t adc)
|
||||
{
|
||||
return (ADC_IF(adc) & ADC_IF_SCAN) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set single result overflow flag
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
*/
|
||||
void adc_set_single_result_overflow_flag(uint32_t adc)
|
||||
{
|
||||
ADC_IFS(adc) = ADC_IFS_SINGLEOF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set single conversion complete flag
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
*/
|
||||
void adc_set_single_conversion_complete_flag(uint32_t adc)
|
||||
{
|
||||
ADC_IFS(adc) = ADC_IFS_SINGLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set scan result overflow flag
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
*/
|
||||
void adc_set_scan_result_overflow_flag(uint32_t adc)
|
||||
{
|
||||
ADC_IFS(adc) = ADC_IFS_SCANOF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set scan conversion complete flag
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
*/
|
||||
void adc_set_scan_conversion_complete_flag(uint32_t adc)
|
||||
{
|
||||
ADC_IFS(adc) = ADC_IFS_SCAN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear single result overflow flag
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
*/
|
||||
void adc_clear_single_result_overflow_flag(uint32_t adc)
|
||||
{
|
||||
ADC_IFC(adc) = ADC_IFC_SINGLEOF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear single conversion complete flag
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
*/
|
||||
void adc_clear_single_conversion_complete_flag(uint32_t adc)
|
||||
{
|
||||
ADC_IFC(adc) = ADC_IFC_SINGLE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear scan result overflow flag
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
*/
|
||||
void adc_clear_scan_result_overflow_flag(uint32_t adc)
|
||||
{
|
||||
ADC_IFC(adc) = ADC_IFC_SCANOF;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear scan conversion complete flag
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
*/
|
||||
void adc_clear_scan_conversion_complete_flag(uint32_t adc)
|
||||
{
|
||||
ADC_IFC(adc) = ADC_IFC_SCAN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get result from last scan conversion
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
* @return result
|
||||
*/
|
||||
uint32_t adc_single_data(uint32_t adc)
|
||||
{
|
||||
return ADC_SINGLEDATA(adc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get result from last scan conversion
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
* @return result
|
||||
*/
|
||||
uint32_t adc_scan_data(uint32_t adc)
|
||||
{
|
||||
return ADC_SCANDATA(adc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get result from last single conversion (peak)
|
||||
* Reading result using this function will not clear
|
||||
* SINGLEDV in ADC_STATUS or SINGLE DMA request.
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
* @return result
|
||||
*/
|
||||
uint32_t adc_single_data_peak(uint32_t adc)
|
||||
{
|
||||
return ADC_SINGLEDATAP(adc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get result from last scan conversion (peak)
|
||||
* Reading result using this function will not clear
|
||||
* SCANDV in ADC_STATUS or SCAN DMA request.
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
* @return result
|
||||
*/
|
||||
uint32_t adc_scan_data_peak(uint32_t adc)
|
||||
{
|
||||
return ADC_SCANDATAP(adc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set ADC scan gain calibration
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
* @param scan_gain calibration of gain for internal ref
|
||||
*/
|
||||
void adc_set_calibration_scan_gain(uint32_t adc, uint8_t scan_gain)
|
||||
{
|
||||
ADC_CAL(adc) = (ADC_CAL(adc) & ADC_CAL_SCANGAIN_MASK) | scan_gain;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set ADC scan offset calibration
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
* @param scan_offset calibration of offset for internal ref
|
||||
*/
|
||||
void adc_set_calibration_scan_offset(uint32_t adc, uint8_t scan_offset)
|
||||
{
|
||||
ADC_CAL(adc) = (ADC_CAL(adc) & ADC_CAL_SCANOFF_MASK) | scan_offset;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set ADC single gain calibration
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
* @param single_gain calibration of gain for internal ref
|
||||
*/
|
||||
void adc_set_calibration_single_gain(uint32_t adc, uint8_t single_gain)
|
||||
{
|
||||
ADC_CAL(adc) = (ADC_CAL(adc) & ADC_CAL_SINGLEGAIN_MASK) | single_gain;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set ADC single offset calibration
|
||||
* @param[in] adc ADC (use ADCx)
|
||||
* @param single_offset calibration of offset for internal ref
|
||||
*/
|
||||
void adc_set_calibration_single_offset(uint32_t adc, uint8_t single_offset)
|
||||
{
|
||||
ADC_CAL(adc) = (ADC_CAL(adc) & ADC_CAL_SINGLEOFF_MASK) | single_offset;
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
15
libopencm3/lib/efm32/common/burtc_common.c
Normal file
15
libopencm3/lib/efm32/common/burtc_common.c
Normal file
@@ -0,0 +1,15 @@
|
||||
/** @addtogroup burtc_file BURTC peripheral API
|
||||
* @ingroup peripheral_apis
|
||||
* @brief Backup RTC helper functions.
|
||||
*
|
||||
* <b>NO</b> helper functions exist. Only header definitions are available.
|
||||
* Delete these lines if/when you add actual helper APIs.
|
||||
* @copyright See @ref lgpl_license
|
||||
*/
|
||||
|
||||
#include <libopencm3/efm32/burtc.h>
|
||||
|
||||
/**@{*/
|
||||
|
||||
/**@}*/
|
||||
|
||||
279
libopencm3/lib/efm32/common/cmu_common.c
Normal file
279
libopencm3/lib/efm32/common/cmu_common.c
Normal file
@@ -0,0 +1,279 @@
|
||||
/** @addtogroup cmu_file CMU peripheral API
|
||||
* @ingroup peripheral_apis
|
||||
*/
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2015 Kuldeep Singh Dhaka <kuldeepdhaka9@gmail.com>
|
||||
*
|
||||
* 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/efm32/cmu.h>
|
||||
#include <libopencm3/efm32/msc.h>
|
||||
|
||||
/**@{*/
|
||||
|
||||
/**
|
||||
* Enable CMU registers lock.
|
||||
*/
|
||||
void cmu_enable_lock(void)
|
||||
{
|
||||
CMU_LOCK = CMU_LOCK_LOCKKEY_LOCK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable CMU registers lock
|
||||
*/
|
||||
void cmu_disable_lock(void)
|
||||
{
|
||||
CMU_LOCK = CMU_LOCK_LOCKKEY_UNLOCK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get CMU register lock flag
|
||||
* @retval true if flag is set
|
||||
* @retval false if flag is not set
|
||||
*/
|
||||
bool cmu_get_lock_flag(void)
|
||||
{
|
||||
return (CMU_LOCK & CMU_LOCK_LOCKKEY_MASK) == CMU_LOCK_LOCKKEY_LOCKED;
|
||||
}
|
||||
|
||||
#define _CMU_REG(i) MMIO32(CMU_BASE + ((i) >> 5))
|
||||
#define _CMU_BIT(i) (1 << ((i) & 0x1f))
|
||||
|
||||
/**
|
||||
* @brief Enable Peripheral Clock in running mode.
|
||||
*
|
||||
* Enable the clock on particular peripheral.
|
||||
*
|
||||
* @param[in] clken Peripheral Name
|
||||
*
|
||||
* For available constants, see @a enum::cmu_periph_clken (CMU_LEUART1 for
|
||||
* example)
|
||||
*/
|
||||
|
||||
void cmu_periph_clock_enable(enum cmu_periph_clken clken)
|
||||
{
|
||||
_CMU_REG(clken) |= _CMU_BIT(clken);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable Peripheral Clock in running mode.
|
||||
* Disable the clock on particular peripheral.
|
||||
*
|
||||
* @param[in] clken Peripheral Name
|
||||
*
|
||||
* For available constants, see @a enum::cmu_periph_clken (CMU_LEUART1 for
|
||||
* example)
|
||||
*/
|
||||
|
||||
void cmu_periph_clock_disable(enum cmu_periph_clken clken)
|
||||
{
|
||||
_CMU_REG(clken) &= ~_CMU_BIT(clken);
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn on Oscillator
|
||||
* @param[in] osc enum cmu_osc Oscillator name
|
||||
*/
|
||||
void cmu_osc_on(enum cmu_osc osc)
|
||||
{
|
||||
switch (osc) {
|
||||
case HFRCO:
|
||||
CMU_OSCENCMD = CMU_OSCENCMD_HFRCOEN;
|
||||
break;
|
||||
case LFRCO:
|
||||
CMU_OSCENCMD = CMU_OSCENCMD_LFRCOEN;
|
||||
break;
|
||||
case ULFRCO:
|
||||
/* TODO: but how? */
|
||||
break;
|
||||
case HFXO:
|
||||
CMU_OSCENCMD = CMU_OSCENCMD_HFXOEN;
|
||||
break;
|
||||
case LFXO:
|
||||
CMU_OSCENCMD = CMU_OSCENCMD_LFXOEN;
|
||||
break;
|
||||
case AUXHFRCO:
|
||||
CMU_OSCENCMD = CMU_OSCENCMD_AUXHFRCOEN;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn off Oscillator
|
||||
* @param[in] osc enum cmu_osc Oscillator name
|
||||
*/
|
||||
void cmu_osc_off(enum cmu_osc osc)
|
||||
{
|
||||
switch (osc) {
|
||||
case HFRCO:
|
||||
CMU_OSCENCMD = CMU_OSCENCMD_HFRCODIS;
|
||||
break;
|
||||
case LFRCO:
|
||||
CMU_OSCENCMD = CMU_OSCENCMD_LFRCODIS;
|
||||
break;
|
||||
case ULFRCO:
|
||||
/* TODO: but how? */
|
||||
break;
|
||||
case HFXO:
|
||||
CMU_OSCENCMD = CMU_OSCENCMD_HFXODIS;
|
||||
break;
|
||||
case LFXO:
|
||||
CMU_OSCENCMD = CMU_OSCENCMD_LFXODIS;
|
||||
break;
|
||||
case AUXHFRCO:
|
||||
CMU_OSCENCMD = CMU_OSCENCMD_AUXHFRCODIS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Oscillator read flag
|
||||
* @param[in] osc enum cmu_osc Oscillator name
|
||||
* @retval true if flag is set
|
||||
* @retval false if flag is not set
|
||||
*/
|
||||
bool cmu_osc_ready_flag(enum cmu_osc osc)
|
||||
{
|
||||
switch (osc) {
|
||||
case HFRCO:
|
||||
return (CMU_STATUS & CMU_STATUS_HFRCORDY) != 0;
|
||||
break;
|
||||
case LFRCO:
|
||||
return (CMU_STATUS & CMU_STATUS_LFRCORDY) != 0;
|
||||
break;
|
||||
case ULFRCO:
|
||||
/* TODO: but how? */
|
||||
break;
|
||||
case HFXO:
|
||||
return (CMU_STATUS & CMU_STATUS_HFXORDY) != 0;
|
||||
break;
|
||||
case LFXO:
|
||||
return (CMU_STATUS & CMU_STATUS_LFXORDY) != 0;
|
||||
break;
|
||||
case AUXHFRCO:
|
||||
return (CMU_STATUS & CMU_STATUS_AUXHFRCORDY) != 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait till oscillator is not ready
|
||||
* @param[in] osc enum cmu_osc Oscillator name
|
||||
*/
|
||||
void cmu_wait_for_osc_ready(enum cmu_osc osc)
|
||||
{
|
||||
switch (osc) {
|
||||
case HFRCO:
|
||||
while ((CMU_STATUS & CMU_STATUS_HFRCORDY) == 0);
|
||||
break;
|
||||
case LFRCO:
|
||||
while ((CMU_STATUS & CMU_STATUS_LFRCORDY) == 0);
|
||||
break;
|
||||
case ULFRCO:
|
||||
/* TODO: but how? */
|
||||
break;
|
||||
case HFXO:
|
||||
while ((CMU_STATUS & CMU_STATUS_HFXORDY) == 0);
|
||||
break;
|
||||
case LFXO:
|
||||
while ((CMU_STATUS & CMU_STATUS_LFXORDY) == 0);
|
||||
break;
|
||||
case AUXHFRCO:
|
||||
while ((CMU_STATUS & CMU_STATUS_AUXHFRCORDY) == 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set HFCLK clock source
|
||||
* @param[in] osc enum cmu_osc Oscillator name
|
||||
* @note calling cmu_set_hfclk_source() do not set source immediately, use
|
||||
* @a cmu_get_hfclk_source() to verify that the source has been set.
|
||||
* @see cmu_get_hfclk_source()
|
||||
*/
|
||||
void cmu_set_hfclk_source(enum cmu_osc osc)
|
||||
{
|
||||
switch (osc) {
|
||||
case HFXO:
|
||||
CMU_CMD = CMU_CMD_HFCLKSEL_HFXO;
|
||||
break;
|
||||
case HFRCO:
|
||||
CMU_CMD = CMU_CMD_HFCLKSEL_HFRCO;
|
||||
break;
|
||||
case LFXO:
|
||||
CMU_CMD = CMU_CMD_HFCLKSEL_LFXO;
|
||||
break;
|
||||
case LFRCO:
|
||||
CMU_CMD = CMU_CMD_HFCLKSEL_LFRCO;
|
||||
break;
|
||||
default:
|
||||
/* not applicable */
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
enum cmu_osc cmu_get_hfclk_source(void)
|
||||
{
|
||||
uint32_t status = CMU_STATUS;
|
||||
if (status & CMU_STATUS_LFXOSEL) {
|
||||
return LFXO;
|
||||
} else if (status & CMU_STATUS_LFRCOSEL) {
|
||||
return LFRCO;
|
||||
} else if (status & CMU_STATUS_HFXOSEL) {
|
||||
return HFXO;
|
||||
} else if (status & CMU_STATUS_HFRCOSEL) {
|
||||
return HFRCO;
|
||||
}
|
||||
|
||||
/* never reached */
|
||||
return (enum cmu_osc) -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* HFXO output 48Mhz and core running at 48Mhz
|
||||
*/
|
||||
void cmu_clock_setup_in_hfxo_out_48mhz(void)
|
||||
{
|
||||
/* configure HFXO and prescaler */
|
||||
CMU_HFCORECLKDIV = CMU_HFCORECLKDIV_HFCORECLKDIV_NODIV
|
||||
| CMU_HFCORECLKDIV_HFCORECLKLEDIV;
|
||||
CMU_CTRL = (CMU_CTRL
|
||||
& ~(CMU_CTRL_HFCLKDIV_MASK | CMU_CTRL_HFXOBUFCUR_MASK))
|
||||
| (CMU_CTRL_HFCLKDIV_NODIV
|
||||
| CMU_CTRL_HFXOBUFCUR_BOOSTABOVE32MHZ);
|
||||
|
||||
/* enable HFXO */
|
||||
cmu_osc_on(HFXO);
|
||||
|
||||
/* wait for HFXO */
|
||||
cmu_wait_for_osc_ready(HFXO);
|
||||
|
||||
/* set flash wait state */
|
||||
MSC_READCTRL = (MSC_READCTRL & ~MSC_READCTRL_MODE_MASK)
|
||||
| MSC_READCTRL_MODE_WS2;
|
||||
|
||||
/* switch to HFXO */
|
||||
cmu_set_hfclk_source(HFXO);
|
||||
|
||||
/* wait till HFXO not selected */
|
||||
while (cmu_get_hfclk_source() != HFXO);
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
175
libopencm3/lib/efm32/common/dac_common.c
Normal file
175
libopencm3/lib/efm32/common/dac_common.c
Normal file
@@ -0,0 +1,175 @@
|
||||
/** @addtogroup dac_file DAC peripheral API
|
||||
* @ingroup peripheral_apis
|
||||
*/
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2015 Kuldeep Singh Dhaka <kuldeepdhaka9@gmail.com>
|
||||
*
|
||||
* 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/efm32/dac.h>
|
||||
|
||||
/**@{*/
|
||||
|
||||
/**
|
||||
* Set DAC refresh cycle
|
||||
* @param[in] dac DAC (use DACx)
|
||||
* @param[in] refrsel (use DAC_CTRL_REFRSEL_*CYCLES)
|
||||
* @see dac_disable_auto_refresh()
|
||||
* @see dac_enable_auto_refresh()
|
||||
*/
|
||||
void dac_set_refresh_cycle(uint32_t dac, uint32_t refrsel)
|
||||
{
|
||||
DAC_CTRL(dac) = (DAC_CTRL(dac) & ~DAC_CTRL_REFRSEL_MASK) | refrsel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set DAC clock prescaler
|
||||
* @param[in] dac DAC (use DACx)
|
||||
* @param[in] presc Prescaler (use DAC_CTRL_PRESC_*)
|
||||
*/
|
||||
void dac_set_clock_prescaler(uint32_t dac, uint32_t presc)
|
||||
{
|
||||
DAC_CTRL(dac) = (DAC_CTRL(dac) & ~DAC_CTRL_PRESC_MASK) | presc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set DAC reference
|
||||
* @param[in] dac DAC (use DACx)
|
||||
* @param[in] refsel Reference (DAC_CTRL_REFSEL_*)
|
||||
*/
|
||||
void dac_set_reference(uint32_t dac, uint32_t refsel)
|
||||
{
|
||||
DAC_CTRL(dac) = (DAC_CTRL(dac) & ~DAC_CTRL_REFSEL_MASK) | refsel;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set DAC output mode
|
||||
* @param[in] dac DAC (use DACx)
|
||||
* @param[in] outmode Output mode (DAC_CTRL_OUTMODE_*)
|
||||
*/
|
||||
void dac_set_out_mode(uint32_t dac, uint32_t outmode)
|
||||
{
|
||||
DAC_CTRL(dac) = (DAC_CTRL(dac) & ~DAC_CTRL_OUTMODE_MASK) | outmode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set conversion mode
|
||||
* @param[in] dac DAC (use DACx)
|
||||
* @param[in] convmode Conversion mode (use DAC_CTRL_CONVMODE_*)
|
||||
*/
|
||||
void dac_set_conversion_mode(uint32_t dac, uint32_t convmode)
|
||||
{
|
||||
DAC_CTRL(dac) = (DAC_CTRL(dac) & ~DAC_CTRL_CONVMODE_MASK) | convmode;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable Sine wave on output
|
||||
* @param[in] dac DAC (use DACx)
|
||||
*/
|
||||
void dac_enable_sine(uint32_t dac)
|
||||
{
|
||||
DAC_CTRL(dac) |= DAC_CTRL_SINMODE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable Sine wave on output
|
||||
* @param[in] dac DAC (use DACx)
|
||||
*/
|
||||
void dac_disable_sine(uint32_t dac)
|
||||
{
|
||||
DAC_CTRL(dac) &= ~DAC_CTRL_SINMODE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set PRS trigger source on DAC channel
|
||||
* @param[in] dac DAC (use DACx)
|
||||
* @param[in] dac_chan DAC Channel (use DAC_CHx)
|
||||
* @param[in] prs_chan PRS Channel (use PRS_CHx)
|
||||
*/
|
||||
void dac_set_prs_trigger(uint32_t dac, enum dac_ch dac_chan,
|
||||
enum prs_ch prs_chan)
|
||||
{
|
||||
uint32_t ch_ctrl = DAC_CHx_CTRL(dac, dac_chan);
|
||||
ch_ctrl &= DAC_CH_CTRL_PRSSEL_MASK;
|
||||
ch_ctrl |= DAC_CH_CTRL_PRSSEL(prs_chan);
|
||||
DAC_CHx_CTRL(dac, dac_chan) = ch_ctrl;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable PRS triggerring
|
||||
* @param[in] dac DAC (use DACx)
|
||||
* @param[in] ch DAC Channel (use DAC_CHx)
|
||||
*/
|
||||
void dac_enable_prs_trigger(uint32_t dac, enum dac_ch ch)
|
||||
{
|
||||
DAC_CHx_CTRL(dac, ch) |= DAC_CH_CTRL_PRSEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable PRS triggerring
|
||||
* @param[in] dac DAC (use DACx)
|
||||
* @param[in] ch DAC Channel (use DAC_CHx)
|
||||
*/
|
||||
void dac_disable_prs_trigger(uint32_t dac, enum dac_ch ch)
|
||||
{
|
||||
DAC_CHx_CTRL(dac, ch) &= ~DAC_CH_CTRL_PRSEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable auto refresh
|
||||
* @param[in] dac DAC (use DACx)
|
||||
* @param[in] ch DAC Channel (use DAC_CHx)
|
||||
*/
|
||||
void dac_enable_auto_refresh(uint32_t dac, enum dac_ch ch)
|
||||
{
|
||||
DAC_CHx_CTRL(dac, ch) |= DAC_CH_CTRL_REFREN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable auto refresh
|
||||
* @param[in] dac DAC (use DACx)
|
||||
* @param[in] ch DAC Channel (use DAC_CHx)
|
||||
*/
|
||||
void dac_disable_auto_refresh(uint32_t dac, enum dac_ch ch)
|
||||
{
|
||||
DAC_CHx_CTRL(dac, ch) &= ~DAC_CH_CTRL_REFREN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable channel
|
||||
* @param[in] dac DAC (use DACx)
|
||||
* @param[in] ch DAC Channel (use DAC_CHx)
|
||||
*/
|
||||
void dac_enable_channel(uint32_t dac, enum dac_ch ch)
|
||||
{
|
||||
DAC_CHx_CTRL(dac, ch) |= DAC_CH_CTRL_EN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable channel
|
||||
* @param[in] dac DAC (use DACx)
|
||||
* @param[in] ch DAC Channel (use DAC_CHx)
|
||||
*/
|
||||
void dac_disable_channel(uint32_t dac, enum dac_ch ch)
|
||||
{
|
||||
DAC_CHx_CTRL(dac, ch) &= ~DAC_CH_CTRL_REFREN;
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
627
libopencm3/lib/efm32/common/dma_common.c
Normal file
627
libopencm3/lib/efm32/common/dma_common.c
Normal file
@@ -0,0 +1,627 @@
|
||||
/** @addtogroup dma_file DMA peripheral API
|
||||
* @ingroup peripheral_apis
|
||||
*/
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2015 Kuldeep Singh Dhaka <kuldeepdhaka9@gmail.com>
|
||||
*
|
||||
* 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/efm32/dma.h>
|
||||
|
||||
/**@{*/
|
||||
|
||||
#define CHANNEL_SUPPORT_LOOP(ch) (((ch) == DMA_CH0) || ((ch) == DMA_CH1))
|
||||
|
||||
/**
|
||||
* Enable DMA with privileged access
|
||||
* @see dma_enable_with_unprivileged_access()
|
||||
*/
|
||||
void dma_enable_with_privileged_access(void)
|
||||
{
|
||||
DMA_CONFIG = DMA_CONFIG_EN | DMA_CONFIG_CHPROT;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable DMA with un-privileged access
|
||||
* @see dma_enable_with_privileged_access()
|
||||
*/
|
||||
void dma_enable_with_unprivileged_access(void)
|
||||
{
|
||||
DMA_CONFIG = DMA_CONFIG_EN;
|
||||
}
|
||||
|
||||
/**
|
||||
* same as @a dma_enable_with_unprivileged_access()
|
||||
* @see dma_enable_with_unprivileged_access()
|
||||
*/
|
||||
void dma_enable(void)
|
||||
{
|
||||
dma_enable_with_unprivileged_access();
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable DMA
|
||||
*/
|
||||
void dma_disable(void)
|
||||
{
|
||||
DMA_CONFIG = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set channel's descriptor address
|
||||
* @param[in] desc_base Address of channel's descriptor address
|
||||
* @note @a desc_base 8LSB's should be 0x00
|
||||
*/
|
||||
void dma_set_desc_address(uint32_t desc_base)
|
||||
{
|
||||
if (desc_base & 0xFF) {
|
||||
return;
|
||||
}
|
||||
|
||||
DMA_CTRLBASE = desc_base;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get channel wait on request status flag
|
||||
* @retval true if flag is set
|
||||
* @retval false if flag is not set
|
||||
*/
|
||||
bool dma_get_wait_on_request_flag(enum dma_ch ch)
|
||||
{
|
||||
uint32_t mask = DMA_CHWAITSTATUS_CHxWAITSTATUS(ch);
|
||||
return (DMA_CHWAITSTATUS & mask) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a software request on channel
|
||||
* @param[in] ch Channel (use DMA_CHx)
|
||||
*/
|
||||
void dma_generate_software_request(enum dma_ch ch)
|
||||
{
|
||||
DMA_CHSWREQ = DMA_CHSWREQ_CHxSWREQ(ch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable channel burst only
|
||||
* @param[in] ch Channel (use DMA_CHx)
|
||||
*/
|
||||
void dma_enable_burst_only(enum dma_ch ch)
|
||||
{
|
||||
DMA_CHUSEBURSTS = DMA_CHUSEBURSTS_CHxSUSEBURSTS(ch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable channel single and burst
|
||||
* @param[in] ch Channel (use DMA_CHx)
|
||||
*/
|
||||
void dma_enable_single_and_burst(enum dma_ch ch)
|
||||
{
|
||||
DMA_CHUSEBURSTC = DMA_CHUSEBURSTC_CHxSUSEBURSTC(ch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable channel peripherial request
|
||||
* @param[in] ch Channel (use DMA_CHx)
|
||||
*/
|
||||
void dma_enable_periph_request(enum dma_ch ch)
|
||||
{
|
||||
DMA_CHREQMASKC = DMA_CHREQMASKC_CHxSREQMASKC(ch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable channel peripherial request
|
||||
* @param[in] ch Channel (use DMA_CHx)
|
||||
*/
|
||||
void dma_disable_periph_request(enum dma_ch ch)
|
||||
{
|
||||
DMA_CHREQMASKS = DMA_CHREQMASKS_CHxSREQMASKS(ch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable channel
|
||||
* @param[in] ch Channel (use DMA_CHx)
|
||||
*/
|
||||
void dma_enable_channel(enum dma_ch ch)
|
||||
{
|
||||
DMA_CHENS = DMA_CHENS_CHxSENS(ch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable channel
|
||||
* @param[in] ch Channel (use DMA_CHx)
|
||||
*/
|
||||
void dma_disable_channel(enum dma_ch ch)
|
||||
{
|
||||
DMA_CHENC = DMA_CHENC_CHxSENC(ch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable channel alternate structure
|
||||
* @param[in] ch Channel (use DMA_CHx)
|
||||
*/
|
||||
void dma_disable_alternate_structure(enum dma_ch ch)
|
||||
{
|
||||
DMA_CHALTC = DMA_CHALTC_CHxSALTC(ch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable channel alternate structure
|
||||
* @param[in] ch Channel (use DMA_CHx)
|
||||
*/
|
||||
void dma_enable_alternate_structure(enum dma_ch ch)
|
||||
{
|
||||
DMA_CHALTS = DMA_CHALTS_CHxSALTS(ch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable channel high priority
|
||||
* @param[in] ch Channel (use DMA_CHx)
|
||||
*/
|
||||
void dma_enable_priority(enum dma_ch ch)
|
||||
{
|
||||
DMA_CHPRIS = DMA_CHPRIS_CHxSPRIC(ch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable channel high priority
|
||||
* @param[in] ch Channel (use DMA_CHx)
|
||||
*/
|
||||
void dma_disable_priority(enum dma_ch ch)
|
||||
{
|
||||
DMA_CHPRIC = DMA_CHPRIC_CHxSPRIC(ch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get bus error flag
|
||||
* @retval true if flag is set
|
||||
* @retval false if flag is not set
|
||||
*/
|
||||
bool dma_get_bus_error_flag(void)
|
||||
{
|
||||
return (DMA_ERRORC & DMA_ERRORC_ERRORC) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear bus error flag
|
||||
*/
|
||||
void dma_clear_bus_error_flag(void)
|
||||
{
|
||||
DMA_ERRORC = DMA_ERRORC_ERRORC;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get channel request flag
|
||||
* @param[in] ch Channel (use DMA_CHx)
|
||||
* @retval true if flag is set
|
||||
* @retval false if flag is not set
|
||||
*/
|
||||
bool dma_get_request_flag(enum dma_ch ch)
|
||||
{
|
||||
uint32_t mask = DMA_CHREQSTATUS_CHxSREQSTATUS(ch);
|
||||
return (DMA_CHREQSTATUS & mask) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get bus error interrupt flag
|
||||
* @retval true if flag is set
|
||||
* @retval false if flag is not set
|
||||
*/
|
||||
bool dma_get_bus_error_interrupt_flag(void)
|
||||
{
|
||||
return (DMA_IF & DMA_IF_ERR) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get channel done interrupt flag
|
||||
* @param[in] ch Channel (use DMA_CHx)
|
||||
* @retval true if flag is set
|
||||
* @retval false if flag is not set
|
||||
*
|
||||
*/
|
||||
bool dma_get_done_interrupt_flag(enum dma_ch ch)
|
||||
{
|
||||
return (DMA_IF & DMA_IF_CHxDONE(ch)) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set bus error interrupt flag
|
||||
*/
|
||||
void dma_set_bus_error_interrupt_flag(void)
|
||||
{
|
||||
DMA_IFS = DMA_IFS_ERR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set channel done interrupt flag
|
||||
* @param[in] ch Channel (use DMA_CHx)
|
||||
*/
|
||||
void dma_set_done_interrupt_flag(enum dma_ch ch)
|
||||
{
|
||||
DMA_IFS = DMA_IFS_CHxDONE(ch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear bus error interrupt flag
|
||||
*/
|
||||
void dma_clear_bus_error_interrupt_flag(void)
|
||||
{
|
||||
DMA_IFC = DMA_IFC_ERR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear channel done interrupt flag
|
||||
* @param[in] ch Channel (use DMA_CHx)
|
||||
*/
|
||||
void dma_clear_done_interrupt_flag(enum dma_ch ch)
|
||||
{
|
||||
DMA_IFC = DMA_IFC_CHxDONE(ch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable bus error interrupt
|
||||
*/
|
||||
void dma_enable_bus_error_interrupt(void)
|
||||
{
|
||||
DMA_IEN |= DMA_IEN_ERR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable bus error interrupt
|
||||
*/
|
||||
void dma_disable_bus_error_interrupt(void)
|
||||
{
|
||||
DMA_IEN &= ~DMA_IEN_ERR;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable channel done interrupt
|
||||
* @param[in] ch Channel (use DMA_CHx)
|
||||
*/
|
||||
void dma_enable_done_interrupt(enum dma_ch ch)
|
||||
{
|
||||
DMA_IEN |= DMA_IEN_CHxDONE(ch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable channel done interrupt
|
||||
* @param[in] ch Channel (use DMA_CHx)
|
||||
*/
|
||||
void dma_disable_done_interrupt(enum dma_ch ch)
|
||||
{
|
||||
DMA_IEN &= ~DMA_IEN_CHxDONE(ch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set channel source
|
||||
* @param[in] ch Channel (use DMA_CHx)
|
||||
* @param[in] source Source (use DMA_CH_CTRL_SOURCESEL_*)
|
||||
*/
|
||||
void dma_set_source(enum dma_ch ch, uint32_t source)
|
||||
{
|
||||
DMA_CHx_CTRL(ch) = (DMA_CHx_CTRL(ch) & ~DMA_CH_CTRL_SOURCESEL_MASK)
|
||||
| source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set channel source signal
|
||||
* @param[in] ch Channel (use DMA_CHx)
|
||||
* @param[in] signal Signal (use DMA_CH_CTRL_SIGSEL_*)
|
||||
*/
|
||||
void dma_set_signal(enum dma_ch ch, uint32_t signal)
|
||||
{
|
||||
DMA_CHx_CTRL(ch) = (DMA_CHx_CTRL(ch) & ~DMA_CH_CTRL_SIGSEL_MASK)
|
||||
| signal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset channel
|
||||
* @param[in] ch Channel (use DMA_CHx)
|
||||
*/
|
||||
void dma_channel_reset(enum dma_ch ch)
|
||||
{
|
||||
/* Disable channel */
|
||||
DMA_CHENC = DMA_CHENC_CHxSENC(ch);
|
||||
/* reset channel alternate desc */
|
||||
DMA_CHALTC = DMA_CHALTC_CHxSALTC(ch);
|
||||
/* reset channel priority */
|
||||
DMA_CHPRIC = DMA_CHPRIC_CHxSPRIC(ch);
|
||||
/* clear channel interrupt */
|
||||
DMA_IFC = DMA_IFC_CHxDONE(ch);
|
||||
/* disable loop */
|
||||
if (CHANNEL_SUPPORT_LOOP(ch)) {
|
||||
DMA_LOOPx(ch) = 0;
|
||||
}
|
||||
/* reset signal {source, select} */
|
||||
DMA_CHx_CTRL(ch) = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set channel loop width to ( @a count + 1)
|
||||
* @param[in] ch Channel (use DMA_CHx)
|
||||
* @param[in] count Count
|
||||
* @note @a count is expected to be equal to (n_minus_1 + 1)
|
||||
*/
|
||||
void dma_set_loop_count(enum dma_ch ch, uint16_t count)
|
||||
{
|
||||
if (!CHANNEL_SUPPORT_LOOP(ch)) {
|
||||
return;
|
||||
}
|
||||
|
||||
DMA_LOOPx(ch) = (DMA_LOOPx(ch) & ~DMA_LOOP_WIDTH_MASK)
|
||||
| DMA_LOOP_WIDTH(count - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable channel loop
|
||||
* @param[in] ch Channel (use DMA_CHx)
|
||||
*/
|
||||
void dma_enable_loop(enum dma_ch ch)
|
||||
{
|
||||
if (!CHANNEL_SUPPORT_LOOP(ch)) {
|
||||
return;
|
||||
}
|
||||
|
||||
DMA_LOOPx(ch) |= DMA_LOOP_EN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable channel loop
|
||||
* @param[in] ch Channel (use DMA_CHx)
|
||||
*/
|
||||
void dma_disable_loop(enum dma_ch ch)
|
||||
{
|
||||
if (!CHANNEL_SUPPORT_LOOP(ch)) {
|
||||
return;
|
||||
}
|
||||
|
||||
DMA_LOOPx(ch) &= ~DMA_LOOP_EN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set desination size
|
||||
* @param[in] desc_base start of memory location that contain channel
|
||||
* descriptor
|
||||
* @param[in] ch Channel (use DMA_CHx)
|
||||
* @param[in] size Size (use DMA_MEM_*)
|
||||
*/
|
||||
void dma_desc_set_dest_size(uint32_t desc_base, enum dma_ch ch,
|
||||
enum dma_mem size)
|
||||
{
|
||||
uint32_t cfg = DMA_DESC_CHx_CFG(desc_base, ch);
|
||||
cfg &= ~DMA_DESC_CH_CFG_DEST_SIZE_MASK;
|
||||
cfg |= DMA_DESC_CH_CFG_DEST_SIZE(size);
|
||||
DMA_DESC_CHx_CFG(desc_base, ch) = cfg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set destination increment
|
||||
* @param[in] desc_base start of memory location that contain channel
|
||||
* descriptor
|
||||
* @param[in] ch Channel (use DMA_CHx)
|
||||
* @param[in] inc Increment (use DMA_MEM_*)
|
||||
*/
|
||||
void dma_desc_set_dest_inc(uint32_t desc_base, enum dma_ch ch,
|
||||
enum dma_mem inc)
|
||||
{
|
||||
uint32_t cfg = DMA_DESC_CHx_CFG(desc_base, ch);
|
||||
cfg &= ~DMA_DESC_CH_CFG_DEST_INC_MASK;
|
||||
cfg |= DMA_DESC_CH_CFG_DEST_INC(inc);
|
||||
DMA_DESC_CHx_CFG(desc_base, ch) = cfg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set source size
|
||||
* @param[in] desc_base start of memory location that contain channel
|
||||
* descriptor
|
||||
* @param[in] ch Channel (use DMA_CHx)
|
||||
* @param[in] size Size (use DMA_MEM_*)
|
||||
*/
|
||||
void dma_desc_set_src_size(uint32_t desc_base, enum dma_ch ch,
|
||||
enum dma_mem size)
|
||||
{
|
||||
uint32_t cfg = DMA_DESC_CHx_CFG(desc_base, ch);
|
||||
cfg &= ~DMA_DESC_CH_CFG_SRC_SIZE_MASK;
|
||||
cfg |= DMA_DESC_CH_CFG_SRC_SIZE(size);
|
||||
DMA_DESC_CHx_CFG(desc_base, ch) = cfg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set source increment
|
||||
* @param[in] desc_base start of memory location that contain channel
|
||||
* descriptor
|
||||
* @param[in] ch Channel (use DMA_CHx)
|
||||
* @param[in] inc Increment (use DMA_MEM_*)
|
||||
*/
|
||||
void dma_desc_set_src_inc(uint32_t desc_base, enum dma_ch ch, enum dma_mem inc)
|
||||
{
|
||||
|
||||
uint32_t cfg = DMA_DESC_CHx_CFG(desc_base, ch);
|
||||
cfg &= ~DMA_DESC_CH_CFG_SRC_INC_MASK;
|
||||
cfg |= DMA_DESC_CH_CFG_SRC_INC(inc);
|
||||
DMA_DESC_CHx_CFG(desc_base, ch) = cfg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set R Power
|
||||
* @param[in] desc_base start of memory location that contain channel
|
||||
* descriptor
|
||||
* @param[in] ch Channel (use DMA_CHx)
|
||||
* @param[in] r_power R Power (Use DMA_R_POWER_*)
|
||||
*/
|
||||
void dma_desc_set_r_power(uint32_t desc_base, enum dma_ch ch,
|
||||
enum dma_r_power r_power)
|
||||
{
|
||||
uint32_t cfg = DMA_DESC_CHx_CFG(desc_base, ch);
|
||||
cfg &= ~DMA_DESC_CH_CFG_R_POWER_MASK;
|
||||
cfg |= DMA_DESC_CH_CFG_R_POWER(r_power);
|
||||
DMA_DESC_CHx_CFG(desc_base, ch) = cfg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable next useburst
|
||||
* @param[in] desc_base start of memory location that contain channel
|
||||
* descriptor
|
||||
* @param[in] ch Channel (use DMA_CHx)
|
||||
*/
|
||||
void dma_desc_enable_next_useburst(uint32_t desc_base, enum dma_ch ch)
|
||||
{
|
||||
DMA_DESC_CHx_CFG(desc_base, ch) &= ~DMA_DESC_CH_CFG_NEXT_USEBURST;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable next useburst
|
||||
* @param[in] desc_base start of memory location that contain channel
|
||||
* descriptor
|
||||
* @param[in] ch Channel (use DMA_CHx)
|
||||
*/
|
||||
void dma_desc_disable_next_useburst(uint32_t desc_base, enum dma_ch ch)
|
||||
{
|
||||
DMA_DESC_CHx_CFG(desc_base, ch) |= DMA_DESC_CH_CFG_NEXT_USEBURST;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set number (count) of transfer to be performed
|
||||
* @param[in] desc_base start of memory location that contain channel
|
||||
* descriptor
|
||||
* @param[in] ch Channel (use DMA_CHx)
|
||||
* @param[in] count Count
|
||||
*/
|
||||
void dma_desc_set_count(uint32_t desc_base, enum dma_ch ch, uint16_t count)
|
||||
{
|
||||
uint32_t cfg = DMA_DESC_CHx_CFG(desc_base, ch);
|
||||
cfg &= ~DMA_DESC_CH_CFG_N_MINUS_1_MASK;
|
||||
cfg |= DMA_DESC_CH_CFG_N_MINUS_1(count - 1);
|
||||
DMA_DESC_CHx_CFG(desc_base, ch) = cfg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Store user data field in channel descriptor
|
||||
* @param[in] desc_base start of memory location that contain channel
|
||||
* descriptor
|
||||
* @param[in] ch Channel (use DMA_CHx)
|
||||
* @param[in] user_data User data
|
||||
*/
|
||||
void dma_desc_set_user_data(uint32_t desc_base, enum dma_ch ch,
|
||||
uint32_t user_data)
|
||||
{
|
||||
DMA_DESC_CHx_USER_DATA(desc_base, ch) = user_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Extract user data field from channel descriptor
|
||||
* @param[in] desc_base start of memory location that contain channel
|
||||
* descriptor
|
||||
* @param[in] ch Channel (use DMA_CHx)
|
||||
* @return user data
|
||||
*/
|
||||
uint32_t dma_desc_get_user_data(uint32_t desc_base, enum dma_ch ch)
|
||||
{
|
||||
return DMA_DESC_CHx_USER_DATA(desc_base, ch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate end from start address.
|
||||
*
|
||||
* @details
|
||||
* See "8.4.3.4 Address calculation" p68, EFM32LG-RM "d0183_Rev1.10"
|
||||
*
|
||||
* @param[in] start address to start of memory
|
||||
* @param[in] inc Increment (use DMA_MEM_*)
|
||||
* @param[in] n_minus_1 the number of transfers minus 1 (ie count - 1)
|
||||
* @return the calculate end address
|
||||
* @note can be used to calculate {source, destination} end address
|
||||
*/
|
||||
static inline uint32_t dma_calc_end_from_start(uint32_t start, uint8_t inc,
|
||||
uint16_t n_minus_1)
|
||||
{
|
||||
switch (inc) {
|
||||
case DMA_MEM_BYTE:
|
||||
return start + n_minus_1;
|
||||
case DMA_MEM_HALF_WORD:
|
||||
return start + (n_minus_1 << 1);
|
||||
case DMA_MEM_WORD:
|
||||
return start + (n_minus_1 << 2);
|
||||
case DMA_MEM_NONE:
|
||||
return start;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign Source address to DMA Channel
|
||||
* @param[in] desc_base start of memory location that contain channel
|
||||
* descriptor
|
||||
* @param[in] ch Channel (use DMA_CHx)
|
||||
* @param[in] src_start Source data start address
|
||||
* this function uses @ref dma_calc_end_from_start to calculate the
|
||||
* src data end address from @a src_start
|
||||
* @note dma_desc_set_count() should be called first.
|
||||
* @note dma_desc_set_src_inc() should be called first.
|
||||
*/
|
||||
void dma_desc_set_src_address(uint32_t desc_base, enum dma_ch ch,
|
||||
uint32_t src_start)
|
||||
{
|
||||
uint32_t cfg = DMA_DESC_CHx_CFG(desc_base, ch);
|
||||
uint8_t inc = (cfg & DMA_DESC_CH_CFG_SRC_INC_MASK)
|
||||
>> DMA_DESC_CH_CFG_SRC_INC_SHIFT;
|
||||
uint16_t n_minus_1 = (cfg & DMA_DESC_CH_CFG_N_MINUS_1_MASK)
|
||||
>> DMA_DESC_CH_CFG_N_MINUS_1_SHIFT;
|
||||
uint32_t src_end = dma_calc_end_from_start(src_start, inc, n_minus_1);
|
||||
DMA_DESC_CHx_SRC_DATA_END_PTR(desc_base, ch) = src_end;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assign Destination address to DMA Channel
|
||||
* @param[in] desc_base start of memory location that contain channel
|
||||
* descriptor
|
||||
* @param[in] ch Channel (use DMA_CHx)
|
||||
* @param[in] dest_start Destination data start address
|
||||
* this function uses @ref dma_calc_end_from_start to calculate the
|
||||
* dest data end address from @a dest_start
|
||||
* @note dma_desc_set_count() should be called first.
|
||||
* @note dma_desc_set_dest_inc() should be called first.
|
||||
*/
|
||||
void dma_desc_set_dest_address(uint32_t desc_base, enum dma_ch ch,
|
||||
uint32_t dest_start)
|
||||
{
|
||||
uint32_t cfg = DMA_DESC_CHx_CFG(desc_base, ch);
|
||||
uint8_t inc = (cfg & DMA_DESC_CH_CFG_DEST_INC_MASK)
|
||||
>> DMA_DESC_CH_CFG_DEST_INC_SHIFT;
|
||||
uint16_t n_minus_1 = (cfg & DMA_DESC_CH_CFG_N_MINUS_1_MASK)
|
||||
>> DMA_DESC_CH_CFG_N_MINUS_1_SHIFT;
|
||||
uint32_t dest_end = dma_calc_end_from_start(dest_start, inc,
|
||||
n_minus_1);
|
||||
DMA_DESC_CHx_DEST_DATA_END_PTR(desc_base, ch) = dest_end;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the channel mode ("Cycle control")
|
||||
* @param[in] desc_base start of memory location that contain channel
|
||||
* descriptor
|
||||
* @param[in] ch Channel (use DMA_CHx)
|
||||
* @param[in] mode Mode (use DMA_MODE_*)
|
||||
*/
|
||||
void dma_desc_set_mode(uint32_t desc_base, enum dma_ch ch, enum dma_mode mode)
|
||||
{
|
||||
uint32_t cfg = DMA_DESC_CHx_CFG(desc_base, ch);
|
||||
cfg &= ~DMA_DESC_CH_CFG_CYCLE_CTRL_MASK;
|
||||
cfg |= DMA_DESC_CH_CFG_CYCLE_CTRL(mode);
|
||||
DMA_DESC_CHx_CFG(desc_base, ch) = cfg;
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
15
libopencm3/lib/efm32/common/emu_common.c
Normal file
15
libopencm3/lib/efm32/common/emu_common.c
Normal file
@@ -0,0 +1,15 @@
|
||||
/** @addtogroup emu_file EMU peripheral API
|
||||
* @ingroup peripheral_apis
|
||||
* @brief Energy Management Unit helper functions.
|
||||
*
|
||||
* <b>NO</b> helper functions exist. Only header definitions are available.
|
||||
* Delete these lines if/when you add actual helper APIs.
|
||||
* @copyright See @ref lgpl_license
|
||||
*/
|
||||
|
||||
#include <libopencm3/efm32/emu.h>
|
||||
|
||||
/**@{*/
|
||||
|
||||
/**@}*/
|
||||
|
||||
182
libopencm3/lib/efm32/common/gpio_common.c
Normal file
182
libopencm3/lib/efm32/common/gpio_common.c
Normal file
@@ -0,0 +1,182 @@
|
||||
/** @addtogroup gpio_file GPIO peripheral API
|
||||
* @ingroup peripheral_apis
|
||||
*/
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2015 Kuldeep Singh Dhaka <kuldeepdhaka9@gmail.com>
|
||||
*
|
||||
* 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/efm32/gpio.h>
|
||||
|
||||
/**@{*/
|
||||
|
||||
/**
|
||||
* Enable GPIO registers lock.
|
||||
* @see gpio_disable_lock()
|
||||
* @see gpio_get_lock_flag()
|
||||
*/
|
||||
void gpio_enable_lock(void)
|
||||
{
|
||||
GPIO_LOCK = GPIO_LOCK_LOCKKEY_LOCK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable GPIO registers lock.
|
||||
* @see gpio_enable_lock()
|
||||
* @see gpio_get_lock_flag()
|
||||
*/
|
||||
void gpio_disable_lock(void)
|
||||
{
|
||||
GPIO_LOCK = GPIO_LOCK_LOCKKEY_UNLOCK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get GPIO register lock flag
|
||||
* @retval true if flag is set
|
||||
* @retval false if flag is not set
|
||||
* @see gpio_enable_lock()
|
||||
* @see gpio_disable_lock()
|
||||
*/
|
||||
bool gpio_get_lock_flag(void)
|
||||
{
|
||||
return (GPIO_LOCK & GPIO_LOCK_LOCKKEY_MASK)
|
||||
== GPIO_LOCK_LOCKKEY_LOCKED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set port pins drive strength
|
||||
* @param[in] gpio_port GPIO Port (use GPIO* ex. GPIOA, GPIOB, ....)
|
||||
* @param[in] drive_stength Driver Stength (use GPIO_STENGTH_*)
|
||||
*/
|
||||
void gpio_set_drive_strength(uint32_t gpio_port,
|
||||
enum gpio_drive_strength drive_stength)
|
||||
{
|
||||
GPIO_P_CTRL(gpio_port) = GPIO_P_CTRL_DRIVEMODE(drive_stength);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set port pins mode
|
||||
* @param[in] gpio_port GPIO Port (use GPIO* ex. GPIOA, GPIOB, ....)
|
||||
* @param[in] mode Mode (use GPIO_MODE_*)
|
||||
* @param[in] gpios (pins mask (use GPIO* ex . GPIO0, GPIO1 .... GPIO_ALL,
|
||||
* use bitwise OR '|' to separate)
|
||||
*/
|
||||
void gpio_mode_setup(uint32_t gpio_port, enum gpio_mode mode, uint16_t gpios)
|
||||
{
|
||||
unsigned i;
|
||||
|
||||
uint32_t high = GPIO_P_MODEH(gpio_port);
|
||||
uint32_t low = GPIO_P_MODEL(gpio_port);
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
if (gpios & (1 << i)) {
|
||||
low &= ~GPIO_P_MODE_MODEx_MASK(i);
|
||||
low |= GPIO_P_MODE_MODEx(i, mode);
|
||||
}
|
||||
|
||||
if (gpios & (1 << (i + 8))) {
|
||||
high &= ~GPIO_P_MODE_MODEx_MASK(i);
|
||||
high |= GPIO_P_MODE_MODEx(i, mode);
|
||||
}
|
||||
}
|
||||
|
||||
GPIO_P_MODEL(gpio_port) = low;
|
||||
GPIO_P_MODEH(gpio_port) = high;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set port pins output value (Atomic)
|
||||
* @param[in] gpio_port GPIO Port (use GPIO* ex. GPIOA, GPIOB, ....)
|
||||
* @param[in] gpios (pins mask (use GPIO* ex . GPIO0, GPIO1 .... GPIO_ALL,
|
||||
* use bitwise OR '|' to separate)
|
||||
*/
|
||||
void gpio_set(uint32_t gpio_port, uint16_t gpios)
|
||||
{
|
||||
GPIO_P_DOUTSET(gpio_port) = gpios;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set port pins output value (Atomic)
|
||||
* @param[in] gpio_port GPIO Port (use GPIO* ex. GPIOA, GPIOB, ....)
|
||||
* @param[in] gpios (pins mask (use GPIO* ex . GPIO0, GPIO1 .... GPIO_ALL,
|
||||
* use bitwise OR '|' to separate)
|
||||
*/
|
||||
void gpio_clear(uint32_t gpio_port, uint16_t gpios)
|
||||
{
|
||||
GPIO_P_DOUTCLR(gpio_port) = gpios;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get port pins input value
|
||||
* @param[in] gpio_port GPIO Port (use GPIO* ex. GPIOA, GPIOB, ....)
|
||||
* @param[in] gpios (pins mask (use GPIO* ex . GPIO0, GPIO1 .... GPIO_ALL,
|
||||
* use bitwise OR '|' to separate)
|
||||
* @return masked pins value (separated by bitwise OR '|')
|
||||
*/
|
||||
uint16_t gpio_get(uint32_t gpio_port, uint16_t gpios)
|
||||
{
|
||||
return GPIO_P_DIN(gpio_port) & gpios;
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggle port pins output value (Atomic)
|
||||
* @param[in] gpio_port GPIO Port (use GPIO* ex. GPIOA, GPIOB, ....)
|
||||
* @param[in] gpios (pins mask (use GPIO* ex . GPIO0, GPIO1 .... GPIO_ALL,
|
||||
* use bitwise OR '|' to separate)
|
||||
*/
|
||||
void gpio_toggle(uint32_t gpio_port, uint16_t gpios)
|
||||
{
|
||||
GPIO_P_DOUTTGL(gpio_port) = gpios;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get port (all) input value's
|
||||
* @param[in] gpio_port GPIO Port (use GPIO* ex. GPIOA, GPIOB, ....)
|
||||
* @return all pins input value
|
||||
*/
|
||||
uint16_t gpio_port_read(uint32_t gpio_port)
|
||||
{
|
||||
return GPIO_P_DIN(gpio_port);
|
||||
}
|
||||
|
||||
/**
|
||||
* Set port (all) output value's
|
||||
* @param[in] gpio_port GPIO Port (use GPIO* ex. GPIOA, GPIOB, ....)
|
||||
* @param[in] data Data (all pins output value)
|
||||
*/
|
||||
void gpio_port_write(uint32_t gpio_port, uint16_t data)
|
||||
{
|
||||
GPIO_P_DOUT(gpio_port) = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Lock the Configuration of a Group of Pins
|
||||
*
|
||||
* The configuration of one or more pins of the given GPIO port is locked.
|
||||
* There is no mechanism to unlock these via software. Unlocking occurs at the
|
||||
* next reset.
|
||||
*
|
||||
* @param[in] gpio_port GPIO Port (use GPIO* ex. GPIOA, GPIOB, ....)
|
||||
* @param[in] gpios (pins mask (use GPIO* ex . GPIO0, GPIO1 .... GPIO_ALL,
|
||||
* use bitwise OR '|' to separate)
|
||||
*/
|
||||
void gpio_port_config_lock(uint32_t gpio_port, uint16_t gpios)
|
||||
{
|
||||
GPIO_P_PINLOCKN(gpio_port) = ~gpios;
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
15
libopencm3/lib/efm32/common/i2c_common.c
Normal file
15
libopencm3/lib/efm32/common/i2c_common.c
Normal file
@@ -0,0 +1,15 @@
|
||||
/** @addtogroup i2c_file I2C peripheral API
|
||||
* @ingroup peripheral_apis
|
||||
* @brief I²C helper functions.
|
||||
*
|
||||
* <b>NO</b> helper functions exist. Only header definitions are available.
|
||||
* Delete these lines if/when you add actual helper APIs.
|
||||
* @copyright See @ref lgpl_license
|
||||
*/
|
||||
|
||||
#include <libopencm3/efm32/i2c.h>
|
||||
|
||||
/**@{*/
|
||||
|
||||
/**@}*/
|
||||
|
||||
15
libopencm3/lib/efm32/common/letimer_common.c
Normal file
15
libopencm3/lib/efm32/common/letimer_common.c
Normal file
@@ -0,0 +1,15 @@
|
||||
/** @addtogroup letimer_file LETIMER peripheral API
|
||||
* @ingroup peripheral_apis
|
||||
* @brief Low Energy Timer helper functions.
|
||||
*
|
||||
* <b>NO</b> helper functions exist. Only header definitions are available.
|
||||
* Delete these lines if/when you add actual helper APIs.
|
||||
* @copyright See @ref lgpl_license
|
||||
*/
|
||||
|
||||
#include <libopencm3/efm32/letimer.h>
|
||||
|
||||
/**@{*/
|
||||
|
||||
/**@}*/
|
||||
|
||||
15
libopencm3/lib/efm32/common/msc_common.c
Normal file
15
libopencm3/lib/efm32/common/msc_common.c
Normal file
@@ -0,0 +1,15 @@
|
||||
/** @addtogroup msc_file MSC peripheral API
|
||||
* @ingroup peripheral_apis
|
||||
* @brief Memory Systems Controller helper functions.
|
||||
*
|
||||
* <b>NO</b> helper functions exist. Only header definitions are available.
|
||||
* Delete these lines if/when you add actual helper APIs.
|
||||
* @copyright See @ref lgpl_license
|
||||
*/
|
||||
|
||||
#include <libopencm3/efm32/msc.h>
|
||||
|
||||
/**@{*/
|
||||
|
||||
/**@}*/
|
||||
|
||||
151
libopencm3/lib/efm32/common/prs_common.c
Normal file
151
libopencm3/lib/efm32/common/prs_common.c
Normal file
@@ -0,0 +1,151 @@
|
||||
/** @addtogroup prs_file PRS peripheral API
|
||||
* @ingroup peripheral_apis
|
||||
* @brief EFM32 Peripheral Reflex System (PRS).
|
||||
* The Peripheral Reflex System (PRS) system is a network which allows the
|
||||
* different peripheral modules to communicate directly with each other
|
||||
* without involving the CPU.
|
||||
*/
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2015 Kuldeep Singh Dhaka <kuldeepdhaka9@gmail.com>
|
||||
*
|
||||
* 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/efm32/prs.h>
|
||||
|
||||
/**@{*/
|
||||
|
||||
/**
|
||||
* Enable PRS output to GPIO.
|
||||
* @param[in] ch Channel (use PRS_CHx)
|
||||
* @see prs_set_output_loc()
|
||||
*/
|
||||
void prs_enable_gpio_output(enum prs_ch ch)
|
||||
{
|
||||
PRS_ROUTE |= PRS_ROUTE_CHxPEN(ch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable PRS output to GPIO.
|
||||
* @param[in] ch Channel (use PRS_CHx)
|
||||
* @see prs_set_output_loc()
|
||||
*/
|
||||
void prs_disable_gpio_output(enum prs_ch ch)
|
||||
{
|
||||
PRS_ROUTE &= ~PRS_ROUTE_CHxPEN(ch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Location of the PRS to be output on GPIO.
|
||||
* @param[in] loc location (use PRS_ROUTE_LOCATION_LOCx)
|
||||
* @see prs_set_output_loc()
|
||||
*/
|
||||
void prs_set_output_loc(uint32_t loc)
|
||||
{
|
||||
PRS_ROUTE = (PRS_ROUTE & ~PRS_ROUTE_LOCATION_MASK) | loc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate software pulse.
|
||||
* @param[in] ch Channel (use PRS_CHx)
|
||||
* @note the final output is dependent on "software level" value of the channel
|
||||
* @see prs_software_level_high()
|
||||
* @see prs_software_level_low()
|
||||
*/
|
||||
void prs_software_pulse(enum prs_ch ch)
|
||||
{
|
||||
PRS_SWPULSE = PRS_SWPULSE_CHxPULSE(ch);
|
||||
}
|
||||
|
||||
/**
|
||||
* HIGH is XOR'ed with the corresponding bit in the software-pulse and
|
||||
* the PRS input signal to generate.
|
||||
* @param[in] ch Channel (use PRS_CHx)
|
||||
* @see prs_software_level_low()
|
||||
* @see prs_software_pulse()
|
||||
*/
|
||||
void prs_software_level_high(enum prs_ch ch)
|
||||
{
|
||||
PRS_SWLEVEL |= PRS_SWLEVEL_CHxLEVEL(ch);
|
||||
}
|
||||
|
||||
/**
|
||||
* LOW is XOR'ed with the corresponding bit in the software-pulse and
|
||||
* the PRS input signal to generate.
|
||||
* @param[in] ch Channel (use PRS_CHx)
|
||||
* @see prs_software_level_high()
|
||||
* @see prs_software_pulse()
|
||||
*/
|
||||
void prs_software_level_low(enum prs_ch ch)
|
||||
{
|
||||
PRS_SWLEVEL &= ~PRS_SWLEVEL_CHxLEVEL(ch);
|
||||
}
|
||||
|
||||
/**
|
||||
* disable synchronization of this channel reflex signal
|
||||
* @param[in] ch Channel (use PRS_CHx)
|
||||
* @see prs_disable_async()
|
||||
*/
|
||||
void prs_enable_async(enum prs_ch ch)
|
||||
{
|
||||
PRS_CHx_CTRL(ch) |= PRS_CH_CTRL_ASYNC;
|
||||
}
|
||||
|
||||
/**
|
||||
* enable synchronization of this channel reflex signal
|
||||
* @param[in] ch Channel (use PRS_CHx)
|
||||
* @see prs_disable_async()
|
||||
*/
|
||||
void prs_disable_async(enum prs_ch ch)
|
||||
{
|
||||
PRS_CHx_CTRL(ch) &= ~PRS_CH_CTRL_ASYNC;
|
||||
}
|
||||
|
||||
/**
|
||||
* Edge detection for the channel
|
||||
* @param[in] ch Channel (use PRS_CHx)
|
||||
* @param[in] edge Edge (use PRS_CH_CTRL_EDSEL_*)
|
||||
*/
|
||||
void prs_set_edge(enum prs_ch ch, uint32_t edge)
|
||||
{
|
||||
PRS_CHx_CTRL(ch) = (PRS_CHx_CTRL(ch) & ~PRS_CH_CTRL_EDSEL_MASK) | edge;
|
||||
}
|
||||
|
||||
/**
|
||||
* Source for the channel
|
||||
* @param[in] ch Channel (use PRS_CHx)
|
||||
* @param[in] source Source (use PRS_CH_CTRL_SOURCESEL_*)
|
||||
* @see prs_set_signal()
|
||||
*/
|
||||
void prs_set_source(enum prs_ch ch, uint32_t source)
|
||||
{
|
||||
PRS_CHx_CTRL(ch) = (PRS_CHx_CTRL(ch) & ~PRS_CH_CTRL_SOURCESEL_MASK)
|
||||
| source;
|
||||
}
|
||||
|
||||
/**
|
||||
* Source for the channel
|
||||
* @param[in] ch Channel (use PRS_CHx)
|
||||
* @param[in] signal Signal (use PRS_CH_CTRL_SIGSEL_*)
|
||||
* @see prs_set_source()
|
||||
*/
|
||||
void prs_set_signal(enum prs_ch ch, uint32_t signal)
|
||||
{
|
||||
PRS_CHx_CTRL(ch) = (PRS_CHx_CTRL(ch) & ~PRS_CH_CTRL_SIGSEL_MASK)
|
||||
| signal;
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
15
libopencm3/lib/efm32/common/rmu_common.c
Normal file
15
libopencm3/lib/efm32/common/rmu_common.c
Normal file
@@ -0,0 +1,15 @@
|
||||
/** @addtogroup rmu_file RMU peripheral API
|
||||
* @ingroup peripheral_apis
|
||||
* @brief Reset Management Unit helper functions.
|
||||
*
|
||||
* <b>NO</b> helper functions exist. Only header definitions are available.
|
||||
* Delete these lines if/when you add actual helper APIs.
|
||||
* @copyright See @ref lgpl_license
|
||||
*/
|
||||
|
||||
#include <libopencm3/efm32/rmu.h>
|
||||
|
||||
/**@{*/
|
||||
|
||||
/**@}*/
|
||||
|
||||
16
libopencm3/lib/efm32/common/rtc_common.c
Normal file
16
libopencm3/lib/efm32/common/rtc_common.c
Normal file
@@ -0,0 +1,16 @@
|
||||
/** @addtogroup rtc_file RTC peripheral API
|
||||
* @ingroup peripheral_apis
|
||||
* @brief Real Time Clock helper functions.
|
||||
*
|
||||
* <b>NO</b> helper functions exist. Only header definitions are available.
|
||||
* Delete these lines if/when you add actual helper APIs.
|
||||
* @sa rtc_defines
|
||||
* @copyright See @ref lgpl_license
|
||||
*/
|
||||
|
||||
#include <libopencm3/efm32/rtc.h>
|
||||
|
||||
/**@{*/
|
||||
|
||||
/**@}*/
|
||||
|
||||
69
libopencm3/lib/efm32/common/timer_common.c
Normal file
69
libopencm3/lib/efm32/common/timer_common.c
Normal file
@@ -0,0 +1,69 @@
|
||||
/** @addtogroup timer_file TIMER peripheral API
|
||||
* @ingroup peripheral_apis
|
||||
*/
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2015 Kuldeep Singh Dhaka <kuldeepdhaka9@gmail.com>
|
||||
*
|
||||
* 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/efm32/timer.h>
|
||||
|
||||
/**@{*/
|
||||
|
||||
#define HAS_DEAD_TIME_INSERTION(timer) (timer == TIMER0)
|
||||
|
||||
/**
|
||||
* Start timer
|
||||
* @param[in] timer Timer (use TIMERx)
|
||||
*/
|
||||
void timer_start(uint32_t timer)
|
||||
{
|
||||
TIMER_CMD(timer) = TIMER_CMD_START;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop timer
|
||||
* @param[in] timer Timer (use TIMERx)
|
||||
*/
|
||||
void timer_stop(uint32_t timer)
|
||||
{
|
||||
TIMER_CMD(timer) = TIMER_CMD_STOP;
|
||||
}
|
||||
|
||||
/** Clock division factor
|
||||
* @param[in] timer Timer (use TIMERx)
|
||||
* @param[in] presc Factor (use TIMER_CTRL_PRESC_DIV*)
|
||||
* @note output-clock = input-clock / @a presc
|
||||
*/
|
||||
void timer_set_clock_prescaler(uint32_t timer, uint32_t presc)
|
||||
{
|
||||
TIMER_CTRL(timer) = (TIMER_CTRL(timer) & ~TIMER_CTRL_PRESC_MASK)
|
||||
| TIMER_CTRL_PRESC(presc);
|
||||
}
|
||||
|
||||
/**
|
||||
* Start timer top value
|
||||
* the timer reload after it reaches top value
|
||||
* @param[in] timer Timer (use TIMERx)
|
||||
* @param[in] top Top value
|
||||
*/
|
||||
void timer_set_top(uint32_t timer, uint32_t top)
|
||||
{
|
||||
TIMER_TOP(timer) = top;
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
18
libopencm3/lib/efm32/common/usart_common.c
Normal file
18
libopencm3/lib/efm32/common/usart_common.c
Normal file
@@ -0,0 +1,18 @@
|
||||
/** @addtogroup usart_file UART/USART peripheral API
|
||||
* @ingroup peripheral_apis
|
||||
* @brief UART/USART helper functions.
|
||||
*
|
||||
* <b>NO</b> helper functions exist. Only header definitions are available.
|
||||
* Delete these lines if/when you add actual helper APIs.
|
||||
* @sa usart_defines
|
||||
* @sa uart_defines
|
||||
* @copyright See @ref lgpl_license
|
||||
*/
|
||||
|
||||
#include <libopencm3/efm32/uart.h>
|
||||
#include <libopencm3/efm32/usart.h>
|
||||
|
||||
/**@{*/
|
||||
|
||||
/**@}*/
|
||||
|
||||
15
libopencm3/lib/efm32/common/wdog_common.c
Normal file
15
libopencm3/lib/efm32/common/wdog_common.c
Normal file
@@ -0,0 +1,15 @@
|
||||
/** @addtogroup wdog_file WDOG peripheral API
|
||||
* @ingroup peripheral_apis
|
||||
* @brief Watchdog Module helper functions.
|
||||
*
|
||||
* <b>NO</b> helper functions exist. Only header definitions are available.
|
||||
* Delete these lines if/when you add actual helper APIs.
|
||||
* @copyright See @ref lgpl_license
|
||||
*/
|
||||
|
||||
#include <libopencm3/efm32/wdog.h>
|
||||
|
||||
/**@{*/
|
||||
|
||||
/**@}*/
|
||||
|
||||
65
libopencm3/lib/efm32/ezr32wg/Makefile
Normal file
65
libopencm3/lib/efm32/ezr32wg/Makefile
Normal file
@@ -0,0 +1,65 @@
|
||||
##
|
||||
## This file is part of the libopencm3 project.
|
||||
##
|
||||
## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
## Copyright (C) 2012 chrysn <chrysn@fsfe.org>
|
||||
## Copyright (C) 2015 Kuldeep Singh Dhaka <kuldeepdhaka9@gmail.com>
|
||||
##
|
||||
## 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/>.
|
||||
##
|
||||
|
||||
LIBNAME = libopencm3_ezr32wg
|
||||
SRCLIBDIR ?= ../..
|
||||
FAMILY = EZR32WG
|
||||
|
||||
FP_FLAGS ?= -mfloat-abi=hard -mfpu=fpv4-sp-d16
|
||||
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-m4 $(FP_FLAGS) -mthumb -Wstrict-prototypes \
|
||||
-ffunction-sections -fdata-sections -MD -D$(FAMILY)
|
||||
TGT_CFLAGS += $(DEBUG_FLAGS)
|
||||
# ARFLAGS = rcsv
|
||||
ARFLAGS = rcs
|
||||
|
||||
OBJS += acmp_common.o
|
||||
OBJS += adc_common.o
|
||||
OBJS += burtc_common.o
|
||||
OBJS += cmu_common.o
|
||||
OBJS += dac_common.o
|
||||
OBJS += dma_common.o
|
||||
OBJS += emu_common.o
|
||||
OBJS += gpio_common.o
|
||||
OBJS += i2c_common.o
|
||||
OBJS += letimer_common.o
|
||||
OBJS += msc_common.o
|
||||
OBJS += prs_common.o
|
||||
OBJS += rmu_common.o
|
||||
OBJS += rtc_common.o
|
||||
OBJS += timer_common.o
|
||||
OBJS += usart_common.o
|
||||
OBJS += wdog_common.o
|
||||
|
||||
OBJS += usb.o usb_control.o usb_standard.o usb_msc.o
|
||||
OBJS += usb_hid.o
|
||||
OBJS += usb_audio.o usb_cdc.o usb_midi.o
|
||||
OBJS += usb_efm32.o
|
||||
|
||||
VPATH += ../../usb:../:../../cm3:../common
|
||||
|
||||
include ../../Makefile.include
|
||||
27
libopencm3/lib/efm32/ezr32wg/vector_chipset.c
Normal file
27
libopencm3/lib/efm32/ezr32wg/vector_chipset.c
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2010 Piotr Esden-Tempski <piotr@esden.net>
|
||||
* Copyright (C) 2011 Fergus Noble <fergusnoble@gmail.com>
|
||||
*
|
||||
* 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/cm3/scb.h>
|
||||
|
||||
static void pre_main(void)
|
||||
{
|
||||
/* Enable access to Floating-Point coprocessor. */
|
||||
SCB_CPACR |= SCB_CPACR_FULL * (SCB_CPACR_CP10 | SCB_CPACR_CP11);
|
||||
}
|
||||
43
libopencm3/lib/efm32/g/Makefile
Normal file
43
libopencm3/lib/efm32/g/Makefile
Normal file
@@ -0,0 +1,43 @@
|
||||
##
|
||||
## This file is part of the libopencm3 project.
|
||||
##
|
||||
## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
## Copyright (C) 2012 chrysn <chrysn@fsfe.org>
|
||||
##
|
||||
## 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/>.
|
||||
##
|
||||
|
||||
LIBNAME = libopencm3_efm32g
|
||||
SRCLIBDIR ?= ../..
|
||||
FAMILY = EFM32G
|
||||
|
||||
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-m3 $(FP_FLAGS) -mthumb -Wstrict-prototypes \
|
||||
-ffunction-sections -fdata-sections -MD -D$(FAMILY)
|
||||
TGT_CFLAGS += $(DEBUG_FLAGS)
|
||||
TGT_CFLAGS += $(STANDARD_FLAGS)
|
||||
# ARFLAGS = rcsv
|
||||
ARFLAGS = rcs
|
||||
OBJS =
|
||||
|
||||
VPATH += ../:../../cm3
|
||||
|
||||
include ../../Makefile.include
|
||||
|
||||
43
libopencm3/lib/efm32/gg/Makefile
Normal file
43
libopencm3/lib/efm32/gg/Makefile
Normal file
@@ -0,0 +1,43 @@
|
||||
##
|
||||
## This file is part of the libopencm3 project.
|
||||
##
|
||||
## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
## Copyright (C) 2012 chrysn <chrysn@fsfe.org>
|
||||
##
|
||||
## 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/>.
|
||||
##
|
||||
|
||||
LIBNAME = libopencm3_efm32gg
|
||||
SRCLIBDIR ?= ../..
|
||||
FAMILY = EFM32GG
|
||||
|
||||
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-m3 $(FP_FLAGS) -mthumb -Wstrict-prototypes \
|
||||
-ffunction-sections -fdata-sections -MD -D$(FAMILY)
|
||||
TGT_CFLAGS += $(DEBUG_FLAGS)
|
||||
TGT_CFLAGS += $(STANDARD_FLAGS)
|
||||
# ARFLAGS = rcsv
|
||||
ARFLAGS = rcs
|
||||
OBJS =
|
||||
|
||||
VPATH += ../:../../cm3
|
||||
|
||||
include ../../Makefile.include
|
||||
|
||||
52
libopencm3/lib/efm32/hg/Makefile
Normal file
52
libopencm3/lib/efm32/hg/Makefile
Normal file
@@ -0,0 +1,52 @@
|
||||
##
|
||||
## This file is part of the libopencm3 project.
|
||||
##
|
||||
## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
## Copyright (C) 2012 chrysn <chrysn@fsfe.org>
|
||||
## Copyright (C) 2015 Kuldeep Singh Dhaka <kuldeepdhaka9@gmail.com>
|
||||
## Copyright (C) 2018 Seb Holzapfel <schnommus@gmail.com>
|
||||
##
|
||||
## 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/>.
|
||||
##
|
||||
|
||||
LIBNAME = libopencm3_efm32hg
|
||||
SRCLIBDIR ?= ../..
|
||||
FAMILY = EFM32HG
|
||||
|
||||
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-m0plus $(FP_FLAGS) -mthumb -Wstrict-prototypes \
|
||||
-ffunction-sections -fdata-sections -MD -D$(FAMILY)
|
||||
TGT_CFLAGS += $(DEBUG_FLAGS)
|
||||
TGT_CFLAGS += $(STANDARD_FLAGS)
|
||||
|
||||
ARFLAGS = rcs
|
||||
|
||||
OBJS += cmu.o
|
||||
OBJS += gpio_common.o
|
||||
OBJS += timer_common.o
|
||||
|
||||
OBJS += usb.o usb_control.o usb_standard.o usb_msc.o
|
||||
OBJS += usb_hid.o
|
||||
OBJS += usb_audio.o usb_cdc.o usb_midi.o
|
||||
OBJS += usb_dwc_common.o usb_efm32hg.o
|
||||
|
||||
VPATH += ../../usb:../:../../cm3:../common
|
||||
|
||||
include ../../Makefile.include
|
||||
314
libopencm3/lib/efm32/hg/cmu.c
Normal file
314
libopencm3/lib/efm32/hg/cmu.c
Normal file
@@ -0,0 +1,314 @@
|
||||
/** @addtogroup cmu_file CMU peripheral API
|
||||
* @ingroup peripheral_apis
|
||||
*/
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2015 Kuldeep Singh Dhaka <kuldeepdhaka9@gmail.com>
|
||||
* Copyright (C) 2018 Seb Holzapfel <schnommus@gmail.com>
|
||||
*
|
||||
* 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/efm32/cmu.h>
|
||||
|
||||
/**@{*/
|
||||
|
||||
/**
|
||||
* Enable CMU registers lock.
|
||||
*/
|
||||
void cmu_enable_lock(void)
|
||||
{
|
||||
CMU_LOCK = CMU_LOCK_LOCKKEY_LOCK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable CMU registers lock
|
||||
*/
|
||||
void cmu_disable_lock(void)
|
||||
{
|
||||
CMU_LOCK = CMU_LOCK_LOCKKEY_UNLOCK;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get CMU register lock flag
|
||||
* @retval true if flag is set
|
||||
* @retval false if flag is not set
|
||||
*/
|
||||
bool cmu_get_lock_flag(void)
|
||||
{
|
||||
return (CMU_LOCK & CMU_LOCK_LOCKKEY_MASK) == CMU_LOCK_LOCKKEY_LOCKED;
|
||||
}
|
||||
|
||||
#define _CMU_REG(i) MMIO32(CMU_BASE + ((i) >> 5))
|
||||
#define _CMU_BIT(i) (1 << ((i) & 0x1f))
|
||||
|
||||
/**
|
||||
* @brief Enable Peripheral Clock in running mode.
|
||||
*
|
||||
* Enable the clock on particular peripheral.
|
||||
*
|
||||
* @param[in] clken Peripheral Name
|
||||
*
|
||||
* For available constants, see @a enum::cmu_periph_clken (CMU_LEUART1 for
|
||||
* example)
|
||||
*/
|
||||
|
||||
void cmu_periph_clock_enable(enum cmu_periph_clken clken)
|
||||
{
|
||||
_CMU_REG(clken) |= _CMU_BIT(clken);
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Disable Peripheral Clock in running mode.
|
||||
* Disable the clock on particular peripheral.
|
||||
*
|
||||
* @param[in] clken Peripheral Name
|
||||
*
|
||||
* For available constants, see @a enum::cmu_periph_clken (CMU_LEUART1 for
|
||||
* example)
|
||||
*/
|
||||
|
||||
void cmu_periph_clock_disable(enum cmu_periph_clken clken)
|
||||
{
|
||||
_CMU_REG(clken) &= ~_CMU_BIT(clken);
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn on Oscillator
|
||||
* @param[in] osc enum cmu_osc Oscillator name
|
||||
*/
|
||||
void cmu_osc_on(enum cmu_osc osc)
|
||||
{
|
||||
switch (osc) {
|
||||
case HFRCO:
|
||||
CMU_OSCENCMD = CMU_OSCENCMD_HFRCOEN;
|
||||
break;
|
||||
case LFRCO:
|
||||
CMU_OSCENCMD = CMU_OSCENCMD_LFRCOEN;
|
||||
break;
|
||||
case USHFRCO:
|
||||
CMU_OSCENCMD = CMU_OSCENCMD_USHFRCOEN;
|
||||
break;
|
||||
case HFXO:
|
||||
CMU_OSCENCMD = CMU_OSCENCMD_HFXOEN;
|
||||
break;
|
||||
case LFXO:
|
||||
CMU_OSCENCMD = CMU_OSCENCMD_LFXOEN;
|
||||
break;
|
||||
case AUXHFRCO:
|
||||
CMU_OSCENCMD = CMU_OSCENCMD_AUXHFRCOEN;
|
||||
break;
|
||||
default:
|
||||
/* not applicable */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Turn off Oscillator
|
||||
* @param[in] osc enum cmu_osc Oscillator name
|
||||
*/
|
||||
void cmu_osc_off(enum cmu_osc osc)
|
||||
{
|
||||
switch (osc) {
|
||||
case HFRCO:
|
||||
CMU_OSCENCMD = CMU_OSCENCMD_HFRCODIS;
|
||||
break;
|
||||
case LFRCO:
|
||||
CMU_OSCENCMD = CMU_OSCENCMD_LFRCODIS;
|
||||
break;
|
||||
case USHFRCO:
|
||||
CMU_OSCENCMD = CMU_OSCENCMD_USHFRCODIS;
|
||||
break;
|
||||
case HFXO:
|
||||
CMU_OSCENCMD = CMU_OSCENCMD_HFXODIS;
|
||||
break;
|
||||
case LFXO:
|
||||
CMU_OSCENCMD = CMU_OSCENCMD_LFXODIS;
|
||||
break;
|
||||
case AUXHFRCO:
|
||||
CMU_OSCENCMD = CMU_OSCENCMD_AUXHFRCODIS;
|
||||
break;
|
||||
default:
|
||||
/* not applicable */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Oscillator read flag
|
||||
* @param[in] osc enum cmu_osc Oscillator name
|
||||
* @retval true if flag is set
|
||||
* @retval false if flag is not set
|
||||
*/
|
||||
bool cmu_osc_ready_flag(enum cmu_osc osc)
|
||||
{
|
||||
switch (osc) {
|
||||
case HFRCO:
|
||||
return (CMU_STATUS & CMU_STATUS_HFRCORDY) != 0;
|
||||
break;
|
||||
case LFRCO:
|
||||
return (CMU_STATUS & CMU_STATUS_LFRCORDY) != 0;
|
||||
break;
|
||||
case USHFRCO:
|
||||
return (CMU_STATUS & CMU_STATUS_USHFRCORDY) != 0;
|
||||
break;
|
||||
case HFXO:
|
||||
return (CMU_STATUS & CMU_STATUS_HFXORDY) != 0;
|
||||
break;
|
||||
case LFXO:
|
||||
return (CMU_STATUS & CMU_STATUS_LFXORDY) != 0;
|
||||
break;
|
||||
case AUXHFRCO:
|
||||
return (CMU_STATUS & CMU_STATUS_AUXHFRCORDY) != 0;
|
||||
break;
|
||||
default:
|
||||
/* not applicable */
|
||||
break;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait while oscillator is not ready
|
||||
* @param[in] osc enum cmu_osc Oscillator name
|
||||
*/
|
||||
void cmu_wait_for_osc_ready(enum cmu_osc osc)
|
||||
{
|
||||
switch (osc) {
|
||||
case HFRCO:
|
||||
while ((CMU_STATUS & CMU_STATUS_HFRCORDY) == 0);
|
||||
break;
|
||||
case LFRCO:
|
||||
while ((CMU_STATUS & CMU_STATUS_LFRCORDY) == 0);
|
||||
break;
|
||||
case USHFRCO:
|
||||
while ((CMU_STATUS & CMU_STATUS_USHFRCORDY) == 0);
|
||||
break;
|
||||
case HFXO:
|
||||
while ((CMU_STATUS & CMU_STATUS_HFXORDY) == 0);
|
||||
break;
|
||||
case LFXO:
|
||||
while ((CMU_STATUS & CMU_STATUS_LFXORDY) == 0);
|
||||
break;
|
||||
case AUXHFRCO:
|
||||
while ((CMU_STATUS & CMU_STATUS_AUXHFRCORDY) == 0);
|
||||
break;
|
||||
default:
|
||||
/* not applicable */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set HFCLK clock source
|
||||
* @param[in] osc enum cmu_osc Oscillator name
|
||||
* @note calling cmu_set_hfclk_source() do not set source immediately, use
|
||||
* @a cmu_get_hfclk_source() to verify that the source has been set.
|
||||
* @see cmu_get_hfclk_source()
|
||||
*/
|
||||
void cmu_set_hfclk_source(enum cmu_osc osc)
|
||||
{
|
||||
switch (osc) {
|
||||
case HFXO:
|
||||
CMU_CMD = CMU_CMD_HFCLKSEL_HFXO;
|
||||
break;
|
||||
case HFRCO:
|
||||
CMU_CMD = CMU_CMD_HFCLKSEL_HFRCO;
|
||||
break;
|
||||
case LFXO:
|
||||
CMU_CMD = CMU_CMD_HFCLKSEL_LFXO;
|
||||
break;
|
||||
case LFRCO:
|
||||
CMU_CMD = CMU_CMD_HFCLKSEL_LFRCO;
|
||||
break;
|
||||
case USHFRCODIV2:
|
||||
CMU_CMD = CMU_CMD_HFCLKSEL_USHFRCODIV2;
|
||||
break;
|
||||
default:
|
||||
/* not applicable */
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get HFCLK clock source
|
||||
* @retval enum cmu_osc Oscillator name
|
||||
*/
|
||||
enum cmu_osc cmu_get_hfclk_source(void)
|
||||
{
|
||||
uint32_t status = CMU_STATUS;
|
||||
if (status & CMU_STATUS_LFXOSEL) {
|
||||
return LFXO;
|
||||
} else if (status & CMU_STATUS_LFRCOSEL) {
|
||||
return LFRCO;
|
||||
} else if (status & CMU_STATUS_HFXOSEL) {
|
||||
return HFXO;
|
||||
} else if (status & CMU_STATUS_HFRCOSEL) {
|
||||
return HFRCO;
|
||||
} else if (status & CMU_STATUS_USHFRCODIV2SEL) {
|
||||
return USHFRCODIV2;
|
||||
}
|
||||
|
||||
/* never reached */
|
||||
return (enum cmu_osc) -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set USBCLK clock source
|
||||
* @param osc Oscillator name
|
||||
*/
|
||||
void cmu_set_usbclk_source(enum cmu_osc osc)
|
||||
{
|
||||
switch (osc) {
|
||||
case LFXO:
|
||||
CMU_CMD = CMU_CMD_USBCCLKSEL_LFXO;
|
||||
break;
|
||||
case LFRCO:
|
||||
CMU_CMD = CMU_CMD_USBCCLKSEL_LFRCO;
|
||||
break;
|
||||
case USHFRCO:
|
||||
CMU_CMD = CMU_CMD_USBCCLKSEL_USHFRCO;
|
||||
break;
|
||||
default:
|
||||
/* not applicable */
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait while USBCLK is not selected
|
||||
* @param[in] osc enum cmu_osc Oscillator name
|
||||
*/
|
||||
void cmu_wait_for_usbclk_selected(enum cmu_osc osc)
|
||||
{
|
||||
switch (osc) {
|
||||
case LFXO:
|
||||
while ((CMU_STATUS & CMU_STATUS_USBCLFXOSEL) == 0);
|
||||
break;
|
||||
case LFRCO:
|
||||
while ((CMU_STATUS & CMU_STATUS_USBCLFRCOSEL) == 0);
|
||||
break;
|
||||
case USHFRCO:
|
||||
while ((CMU_STATUS & CMU_STATUS_USBCUSHFRCOSEL) == 0);
|
||||
break;
|
||||
default:
|
||||
/* not applicable */
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
66
libopencm3/lib/efm32/lg/Makefile
Normal file
66
libopencm3/lib/efm32/lg/Makefile
Normal file
@@ -0,0 +1,66 @@
|
||||
##
|
||||
## This file is part of the libopencm3 project.
|
||||
##
|
||||
## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
## Copyright (C) 2012 chrysn <chrysn@fsfe.org>
|
||||
## Copyright (C) 2015 Kuldeep Singh Dhaka <kuldeepdhaka9@gmail.com>
|
||||
##
|
||||
## 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/>.
|
||||
##
|
||||
|
||||
LIBNAME = libopencm3_efm32lg
|
||||
SRCLIBDIR ?= ../..
|
||||
FAMILY = EFM32LG
|
||||
|
||||
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-m3 $(FP_FLAGS) -mthumb -Wstrict-prototypes \
|
||||
-ffunction-sections -fdata-sections -MD -D$(FAMILY)
|
||||
TGT_CFLAGS += $(DEBUG_FLAGS)
|
||||
TGT_CFLAGS += $(STANDARD_FLAGS)
|
||||
# ARFLAGS = rcsv
|
||||
ARFLAGS = rcs
|
||||
|
||||
OBJS += acmp_common.o
|
||||
OBJS += adc_common.o
|
||||
OBJS += burtc_common.o
|
||||
OBJS += cmu_common.o
|
||||
OBJS += dac_common.o
|
||||
OBJS += dma_common.o
|
||||
OBJS += emu_common.o
|
||||
OBJS += gpio_common.o
|
||||
OBJS += i2c_common.o
|
||||
OBJS += letimer_common.o
|
||||
OBJS += msc_common.o
|
||||
OBJS += prs_common.o
|
||||
OBJS += rmu_common.o
|
||||
OBJS += rtc_common.o
|
||||
OBJS += timer_common.o
|
||||
OBJS += usart_common.o
|
||||
OBJS += wdog_common.o
|
||||
|
||||
OBJS += usb.o usb_control.o usb_standard.o usb_msc.o
|
||||
OBJS += usb_hid.o
|
||||
OBJS += usb_audio.o usb_cdc.o usb_midi.o
|
||||
OBJS += usb_efm32.o
|
||||
|
||||
VPATH += ../../usb:../:../../cm3:../common
|
||||
|
||||
include ../../Makefile.include
|
||||
|
||||
43
libopencm3/lib/efm32/tg/Makefile
Normal file
43
libopencm3/lib/efm32/tg/Makefile
Normal file
@@ -0,0 +1,43 @@
|
||||
##
|
||||
## This file is part of the libopencm3 project.
|
||||
##
|
||||
## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
## Copyright (C) 2012 chrysn <chrysn@fsfe.org>
|
||||
##
|
||||
## 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/>.
|
||||
##
|
||||
|
||||
LIBNAME = libopencm3_efm32tg
|
||||
SRCLIBDIR ?= ../..
|
||||
FAMILY = EFM32TG
|
||||
|
||||
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-m3 $(FP_FLAGS) -mthumb -Wstrict-prototypes \
|
||||
-ffunction-sections -fdata-sections -MD -D$(FAMILY)
|
||||
TGT_CFLAGS += $(DEBUG_FLAGS)
|
||||
TGT_CFLAGS += $(STANDARD_FLAGS)
|
||||
# ARFLAGS = rcsv
|
||||
ARFLAGS = rcs
|
||||
OBJS =
|
||||
|
||||
VPATH += ../:../../cm3
|
||||
|
||||
include ../../Makefile.include
|
||||
|
||||
65
libopencm3/lib/efm32/wg/Makefile
Normal file
65
libopencm3/lib/efm32/wg/Makefile
Normal file
@@ -0,0 +1,65 @@
|
||||
##
|
||||
## This file is part of the libopencm3 project.
|
||||
##
|
||||
## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
## Copyright (C) 2012 chrysn <chrysn@fsfe.org>
|
||||
## Copyright (C) 2015 Kuldeep Singh Dhaka <kuldeepdhaka9@gmail.com>
|
||||
##
|
||||
## 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/>.
|
||||
##
|
||||
|
||||
LIBNAME = libopencm3_efm32wg
|
||||
SRCLIBDIR ?= ../..
|
||||
FAMILY = EFM32WG
|
||||
|
||||
FP_FLAGS ?= -mfloat-abi=hard -mfpu=fpv4-sp-d16
|
||||
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-m4 $(FP_FLAGS) -mthumb -Wstrict-prototypes \
|
||||
-ffunction-sections -fdata-sections -MD -D$(FAMILY)
|
||||
TGT_CFLAGS += $(DEBUG_FLAGS)
|
||||
# ARFLAGS = rcsv
|
||||
ARFLAGS = rcs
|
||||
|
||||
OBJS += acmp_common.o
|
||||
OBJS += adc_common.o
|
||||
OBJS += burtc_common.o
|
||||
OBJS += cmu_common.o
|
||||
OBJS += dac_common.o
|
||||
OBJS += dma_common.o
|
||||
OBJS += emu_common.o
|
||||
OBJS += gpio_common.o
|
||||
OBJS += i2c_common.o
|
||||
OBJS += letimer_common.o
|
||||
OBJS += msc_common.o
|
||||
OBJS += prs_common.o
|
||||
OBJS += rmu_common.o
|
||||
OBJS += rtc_common.o
|
||||
OBJS += timer_common.o
|
||||
OBJS += usart_common.o
|
||||
OBJS += wdog_common.o
|
||||
|
||||
OBJS += usb.o usb_control.o usb_standard.o usb_msc.o
|
||||
OBJS += usb_hid.o
|
||||
OBJS += usb_audio.o usb_cdc.o usb_midi.o
|
||||
OBJS += usb_efm32.o
|
||||
|
||||
VPATH += ../../usb:../:../../cm3:../common
|
||||
|
||||
include ../../Makefile.include
|
||||
27
libopencm3/lib/efm32/wg/vector_chipset.c
Normal file
27
libopencm3/lib/efm32/wg/vector_chipset.c
Normal file
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2010 Piotr Esden-Tempski <piotr@esden.net>
|
||||
* Copyright (C) 2011 Fergus Noble <fergusnoble@gmail.com>
|
||||
*
|
||||
* 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/cm3/scb.h>
|
||||
|
||||
static void pre_main(void)
|
||||
{
|
||||
/* Enable access to Floating-Point coprocessor. */
|
||||
SCB_CPACR |= SCB_CPACR_FULL * (SCB_CPACR_CP10 | SCB_CPACR_CP11);
|
||||
}
|
||||
43
libopencm3/lib/ethernet/mac.c
Normal file
43
libopencm3/lib/ethernet/mac.c
Normal file
@@ -0,0 +1,43 @@
|
||||
/** @defgroup ethernet_mac_file MAC Generic Drivers
|
||||
*
|
||||
* @ingroup ETH
|
||||
*
|
||||
* @brief <b>Ethernet MAC Generic Drivers</b>
|
||||
*
|
||||
* @version 1.0.0
|
||||
* @author @htmlonly © @endhtmlonly 2013 Frantisek Burian <BuFran@seznam.cz>
|
||||
*
|
||||
* @date 1 September 2013
|
||||
*
|
||||
*
|
||||
* LGPL License Terms @ref lgpl_license
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2013 Frantisek Burian <BuFran@seznam.cz>
|
||||
*
|
||||
* 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/ethernet/mac.h>
|
||||
#include <libopencm3/ethernet/phy.h>
|
||||
|
||||
/**@{*/
|
||||
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/**@}*/
|
||||
384
libopencm3/lib/ethernet/mac_stm32fxx7.c
Normal file
384
libopencm3/lib/ethernet/mac_stm32fxx7.c
Normal file
@@ -0,0 +1,384 @@
|
||||
/** @defgroup ethernet_mac_stm32fxx7_file MAC STM32Fxx7
|
||||
*
|
||||
* @ingroup ETH
|
||||
*
|
||||
* @brief <b>Ethernet MAC STM32Fxx7 Drivers</b>
|
||||
*
|
||||
* @version 1.0.0
|
||||
* @author @htmlonly © @endhtmlonly 2013 Frantisek Burian <BuFran@seznam.cz>
|
||||
*
|
||||
* @date 1 September 2013
|
||||
*
|
||||
*
|
||||
* LGPL License Terms @ref lgpl_license
|
||||
*/
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2013 Frantisek Burian <BuFran@seznam.cz>
|
||||
*
|
||||
* 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 <string.h>
|
||||
#include <libopencm3/ethernet/mac.h>
|
||||
#include <libopencm3/ethernet/phy.h>
|
||||
#include <libopencm3/stm32/gpio.h>
|
||||
#include <libopencm3/cm3/nvic.h>
|
||||
|
||||
/**@{*/
|
||||
|
||||
uint32_t TxBD;
|
||||
uint32_t RxBD;
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Set MAC to the PHY
|
||||
*
|
||||
* @param[in] mac uint8_t* Desired MAC
|
||||
*/
|
||||
void eth_set_mac(const uint8_t *mac)
|
||||
{
|
||||
ETH_MACAHR(0) = ((uint32_t)mac[5] << 8) | (uint32_t)mac[4] |
|
||||
ETH_MACA0HR_MACA0H;
|
||||
ETH_MACALR(0) = ((uint32_t)mac[3] << 24) | ((uint32_t)mac[2] << 16) |
|
||||
((uint32_t)mac[1] << 8) | mac[0];
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Initialize buffers and descriptors.
|
||||
*
|
||||
* @param[in] buf uint8_t* Memory area for the descriptors and data buffers
|
||||
* @param[in] nTx uint32_t Count of transmit descriptors (equal to count of buffers)
|
||||
* @param[in] nRx uint32_t Count of receive descriptors (equal to count of buffers)
|
||||
* @param[in] cTx uint32_t Bytes in each transmit buffer, must be a
|
||||
* multiple of 4
|
||||
* @param[in] cRx uint32_t Bytes in each receive buffer, must be a
|
||||
* multiple of 4
|
||||
* @param[in] isext bool true if extended descriptors should be used
|
||||
*
|
||||
* Note, the space passed via buf pointer must be large enough to
|
||||
* hold all the buffers and one descriptor per buffer.
|
||||
*/
|
||||
void eth_desc_init(uint8_t *buf, uint32_t nTx, uint32_t nRx, uint32_t cTx,
|
||||
uint32_t cRx, bool isext)
|
||||
{
|
||||
uint32_t bd = (uint32_t)buf;
|
||||
uint32_t sz = isext ? ETH_DES_EXT_SIZE : ETH_DES_STD_SIZE;
|
||||
|
||||
memset(buf, 0, nTx * (cTx + sz) + nRx * (cRx + sz));
|
||||
|
||||
/* enable / disable extended frames */
|
||||
if (isext) {
|
||||
ETH_DMABMR |= ETH_DMABMR_EDFE;
|
||||
} else {
|
||||
ETH_DMABMR &= ~ETH_DMABMR_EDFE;
|
||||
}
|
||||
|
||||
TxBD = bd;
|
||||
while (--nTx > 0) {
|
||||
ETH_DES0(bd) = ETH_TDES0_TCH;
|
||||
ETH_DES2(bd) = bd + sz;
|
||||
ETH_DES3(bd) = bd + sz + cTx;
|
||||
bd = ETH_DES3(bd);
|
||||
}
|
||||
|
||||
ETH_DES0(bd) = ETH_TDES0_TCH;
|
||||
ETH_DES2(bd) = bd + sz;
|
||||
ETH_DES3(bd) = TxBD;
|
||||
bd += sz + cTx;
|
||||
|
||||
RxBD = bd;
|
||||
while (--nRx > 0) {
|
||||
ETH_DES0(bd) = ETH_RDES0_OWN;
|
||||
ETH_DES1(bd) = ETH_RDES1_RCH | cRx;
|
||||
ETH_DES2(bd) = bd + sz;
|
||||
ETH_DES3(bd) = bd + sz + cRx;
|
||||
bd = ETH_DES3(bd);
|
||||
}
|
||||
|
||||
ETH_DES0(bd) = ETH_RDES0_OWN;
|
||||
ETH_DES1(bd) = ETH_RDES1_RCH | cRx;
|
||||
ETH_DES2(bd) = bd + sz;
|
||||
ETH_DES3(bd) = RxBD;
|
||||
|
||||
ETH_DMARDLAR = (uint32_t) RxBD;
|
||||
ETH_DMATDLAR = (uint32_t) TxBD;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Transmit packet
|
||||
*
|
||||
* @param[in] ppkt uint8_t* Pointer to the beginning of the packet
|
||||
* @param[in] n uint32_t Size of the packet
|
||||
* @returns bool true, if success
|
||||
*/
|
||||
bool eth_tx(uint8_t *ppkt, uint32_t n)
|
||||
{
|
||||
if (ETH_DES0(TxBD) & ETH_TDES0_OWN) {
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy((void *)ETH_DES2(TxBD), ppkt, n);
|
||||
|
||||
ETH_DES1(TxBD) = n & ETH_TDES1_TBS1;
|
||||
ETH_DES0(TxBD) |= ETH_TDES0_LS | ETH_TDES0_FS | ETH_TDES0_OWN;
|
||||
TxBD = ETH_DES3(TxBD);
|
||||
|
||||
if (ETH_DMASR & ETH_DMASR_TBUS) {
|
||||
ETH_DMASR = ETH_DMASR_TBUS;
|
||||
ETH_DMATPDR = 0;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Receive packet
|
||||
*
|
||||
* @param[inout] ppkt uint8_t* Pointer to the data buffer where to store data
|
||||
* @param[inout] len uint32_t* Pointer to the variable with the packet length
|
||||
* @param[in] maxlen uint32_t Maximum length of the packet
|
||||
* @returns bool true, if the buffer contains readed packet data
|
||||
*/
|
||||
bool eth_rx(uint8_t *ppkt, uint32_t *len, uint32_t maxlen)
|
||||
{
|
||||
bool fs = false;
|
||||
bool ls = false;
|
||||
bool overrun = false;
|
||||
uint32_t l = 0;
|
||||
|
||||
while (!(ETH_DES0(RxBD) & ETH_RDES0_OWN) && !ls) {
|
||||
l = (ETH_DES0(RxBD) & ETH_RDES0_FL) >> ETH_RDES0_FL_SHIFT;
|
||||
|
||||
fs |= ETH_DES0(RxBD) & ETH_RDES0_FS;
|
||||
ls |= ETH_DES0(RxBD) & ETH_RDES0_LS;
|
||||
/* frame buffer overrun ?*/
|
||||
overrun |= fs && (maxlen < l);
|
||||
|
||||
if (fs && !overrun) {
|
||||
memcpy(ppkt, (void *)ETH_DES2(RxBD), l);
|
||||
ppkt += l;
|
||||
*len += l;
|
||||
maxlen -= l;
|
||||
}
|
||||
|
||||
ETH_DES0(RxBD) = ETH_RDES0_OWN;
|
||||
RxBD = ETH_DES3(RxBD);
|
||||
}
|
||||
|
||||
if (ETH_DMASR & ETH_DMASR_RBUS) {
|
||||
ETH_DMASR = ETH_DMASR_RBUS;
|
||||
ETH_DMARPDR = 0;
|
||||
}
|
||||
|
||||
return fs && ls && !overrun;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Start the Ethernet DMA processing
|
||||
*/
|
||||
void eth_start(void)
|
||||
{
|
||||
ETH_MACCR |= ETH_MACCR_TE;
|
||||
ETH_DMAOMR |= ETH_DMAOMR_FTF;
|
||||
ETH_MACCR |= ETH_MACCR_RE;
|
||||
|
||||
ETH_DMAOMR |= ETH_DMAOMR_ST;
|
||||
ETH_DMAOMR |= ETH_DMAOMR_SR;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Initialize ethernet
|
||||
*
|
||||
* This function will initialize ethernet, set up clocks, and initialize DMA.
|
||||
*
|
||||
* @param[in] phy phy id
|
||||
* @param[in] clock enum eth_clk Core clock speed
|
||||
*/
|
||||
void eth_init(uint8_t phy, enum eth_clk clock)
|
||||
{
|
||||
ETH_MACMIIAR = clock;
|
||||
phy_reset(phy);
|
||||
|
||||
ETH_MACCR = ETH_MACCR_CSTF | ETH_MACCR_FES | ETH_MACCR_DM |
|
||||
ETH_MACCR_APCS | ETH_MACCR_RD;
|
||||
ETH_MACFFR = ETH_MACFFR_RA | ETH_MACFFR_PM;
|
||||
ETH_MACHTHR = 0; /* pass all frames */
|
||||
ETH_MACHTLR = 0;
|
||||
ETH_MACFCR = (0x100 << ETH_MACFCR_PT_SHIFT);
|
||||
ETH_MACVLANTR = 0;
|
||||
ETH_DMAOMR = ETH_DMAOMR_DTCEFD | ETH_DMAOMR_RSF | ETH_DMAOMR_DFRF |
|
||||
ETH_DMAOMR_TSF | ETH_DMAOMR_FEF | ETH_DMAOMR_OSF;
|
||||
ETH_DMABMR = ETH_DMABMR_AAB | ETH_DMABMR_FB |
|
||||
(32 << ETH_DMABMR_RDP_SHIFT) | (32 << ETH_DMABMR_PBL_SHIFT) |
|
||||
ETH_DMABMR_PM_2_1 | ETH_DMABMR_USP;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Enable the Ethernet IRQ
|
||||
*
|
||||
* @param[in] reason uint32_t Which irq will be enabled
|
||||
*/
|
||||
void eth_irq_enable(uint32_t reason)
|
||||
{
|
||||
ETH_DMAIER |= reason;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Disable the Ethernet IRQ
|
||||
*
|
||||
* @param[in] reason uint32_t Which irq will be disabled
|
||||
*/
|
||||
void eth_irq_disable(uint32_t reason)
|
||||
{
|
||||
ETH_DMAIER &= ~reason;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Check if IRQ is pending
|
||||
*
|
||||
* @param[in] reason uint32_t Which irq type has to be tested
|
||||
* @returns bool true, if IRQ is pending
|
||||
*/
|
||||
bool eth_irq_is_pending(uint32_t reason)
|
||||
{
|
||||
return (ETH_DMASR & reason) != 0;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Check if IRQ is pending, and acknowledge it
|
||||
*
|
||||
* @param[in] reason uint32_t Which irq type has to be tested
|
||||
* @returns bool true, if IRQ is pending
|
||||
*/
|
||||
bool eth_irq_ack_pending(uint32_t reason)
|
||||
{
|
||||
reason &= ETH_DMASR;
|
||||
ETH_DMASR = reason;
|
||||
return reason != 0;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Enable checksum offload feature
|
||||
*
|
||||
* This function will enable the Checksum offload feature for all of the
|
||||
* transmit descriptors. Note to use this feature, descriptors must be in
|
||||
* extended format.
|
||||
*/
|
||||
void eth_enable_checksum_offload(void)
|
||||
{
|
||||
uint32_t tab = TxBD;
|
||||
do {
|
||||
ETH_DES0(tab) |= ETH_TDES0_CIC_IPPLPH;
|
||||
tab = ETH_DES3(tab);
|
||||
}
|
||||
while (tab != TxBD);
|
||||
|
||||
ETH_MACCR |= ETH_MACCR_IPCO;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Process pending SMI transaction and wait to be done.
|
||||
*/
|
||||
static void eth_smi_transact(void)
|
||||
{
|
||||
/* Begin transaction. */
|
||||
ETH_MACMIIAR |= ETH_MACMIIAR_MB;
|
||||
|
||||
/* Wait for not busy. */
|
||||
while (ETH_MACMIIAR & ETH_MACMIIAR_MB);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Write 16-bit register to the PHY
|
||||
*
|
||||
* @param[in] phy uint8_t ID of the PHY (defaults to 1)
|
||||
* @param[in] reg uint8_t Register address
|
||||
* @param[in] data uint16_t Data to write
|
||||
*/
|
||||
void eth_smi_write(uint8_t phy, uint8_t reg, uint16_t data)
|
||||
{
|
||||
/* Write operation MW=1*/
|
||||
ETH_MACMIIAR = (ETH_MACMIIAR & ETH_MACMIIAR_CR) | /* save clocks */
|
||||
(phy << ETH_MACMIIAR_PA_SHIFT) |
|
||||
(reg << ETH_MACMIIAR_MR_SHIFT) |
|
||||
ETH_MACMIIAR_MW;
|
||||
|
||||
ETH_MACMIIDR = data & ETH_MACMIIDR_MD;
|
||||
|
||||
eth_smi_transact();
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Read the 16-bit register from the PHY
|
||||
*
|
||||
* @param[in] phy uint8_t ID of the PHY (defaults to 1)
|
||||
* @param[in] reg uint8_t Register address
|
||||
* @returns uint16_t Readed data
|
||||
*/
|
||||
uint16_t eth_smi_read(uint8_t phy, uint8_t reg)
|
||||
{
|
||||
/* Read operation MW=0*/
|
||||
ETH_MACMIIAR = (ETH_MACMIIAR & ETH_MACMIIAR_CR) | /* save clocks */
|
||||
(phy << ETH_MACMIIAR_PA_SHIFT) |
|
||||
(reg << ETH_MACMIIAR_MR_SHIFT);
|
||||
|
||||
eth_smi_transact();
|
||||
|
||||
return (uint16_t)(ETH_MACMIIDR & ETH_MACMIIDR_MD);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Process the bit-operation on PHY register
|
||||
*
|
||||
* @param[in] phy uint8_t ID of the PHY (defaults to 1)
|
||||
* @param[in] reg uint8_t Register address
|
||||
* @param[in] bits uint16_t Bits that have to be set (or'ed)
|
||||
* @param[in] mask uint16_t Bits that have to be clear (and'ed)
|
||||
*/
|
||||
void eth_smi_bit_op(uint8_t phy, uint8_t reg, uint16_t bits, uint16_t mask)
|
||||
{
|
||||
uint16_t val = eth_smi_read(phy, reg);
|
||||
eth_smi_write(phy, reg, (val & mask) | bits);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Clear bits in the register
|
||||
*
|
||||
* @param[in] phy uint8_t ID of the PHY (defaults to 1)
|
||||
* @param[in] reg uint8_t Register address
|
||||
* @param[in] clearbits uint16_t Bits that have to be cleared
|
||||
*/
|
||||
void eth_smi_bit_clear(uint8_t phy, uint8_t reg, uint16_t clearbits)
|
||||
{
|
||||
uint16_t val = eth_smi_read(phy, reg);
|
||||
eth_smi_write(phy, reg, val & (uint16_t)~(clearbits));
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Set bits in the register
|
||||
*
|
||||
* @param[in] phy uint8_t ID of the PHY (defaults to 1)
|
||||
* @param[in] reg uint8_t Register address
|
||||
* @param[in] setbits uint16_t Bits that have to be set (or'ed)
|
||||
*/
|
||||
void eth_smi_bit_set(uint8_t phy, uint8_t reg, uint16_t setbits)
|
||||
{
|
||||
uint16_t val = eth_smi_read(phy, reg);
|
||||
eth_smi_write(phy, reg, val | setbits);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/**@}*/
|
||||
65
libopencm3/lib/ethernet/phy.c
Executable file
65
libopencm3/lib/ethernet/phy.c
Executable file
@@ -0,0 +1,65 @@
|
||||
/** @defgroup ethernet_phy_file PHY Generic Drivers
|
||||
*
|
||||
* @ingroup ETH
|
||||
*
|
||||
* @brief <b>Ethernet PHY Generic Drivers</b>
|
||||
*
|
||||
* @version 1.0.0
|
||||
* @author @htmlonly © @endhtmlonly 2013 Frantisek Burian <BuFran@seznam.cz>
|
||||
*
|
||||
* @date 1 September 2013
|
||||
*
|
||||
*
|
||||
* LGPL License Terms @ref lgpl_license
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2013 Frantisek Burian <BuFran@seznam.cz>
|
||||
*
|
||||
* 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/ethernet/mac.h>
|
||||
#include <libopencm3/ethernet/phy.h>
|
||||
|
||||
/**@{*/
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Is the link up ?
|
||||
*
|
||||
* @param[in] phy uint8_t phy ID of the PHY
|
||||
* @returns bool true, if link is up
|
||||
*/
|
||||
bool phy_link_isup(uint8_t phy)
|
||||
{
|
||||
return eth_smi_read(phy, PHY_REG_BSR) & PHY_REG_BSR_UP;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Reset the PHY
|
||||
*
|
||||
* Reset the PHY chip and wait for done
|
||||
* @param[in] phy uint8_t phy ID of the PHY
|
||||
*/
|
||||
void phy_reset(uint8_t phy)
|
||||
{
|
||||
eth_smi_write(phy, PHY_REG_BCR, PHY_REG_BCR_RESET);
|
||||
while (eth_smi_read(phy, PHY_REG_BCR) & PHY_REG_BCR_RESET);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/**@}*/
|
||||
93
libopencm3/lib/ethernet/phy_ksz80x1.c
Normal file
93
libopencm3/lib/ethernet/phy_ksz80x1.c
Normal file
@@ -0,0 +1,93 @@
|
||||
/** @defgroup ethernet_phy_ksz8051mll_file PHY KSZ8051MLL
|
||||
*
|
||||
* @ingroup ETH
|
||||
*
|
||||
* @brief <b>Ethernet PHY STM32Fxx7 Drivers</b>
|
||||
*
|
||||
* @version 1.0.0
|
||||
* @author @htmlonly © @endhtmlonly 2013 Frantisek Burian <BuFran@seznam.cz>
|
||||
*
|
||||
* @date 1 September 2013
|
||||
*
|
||||
* LGPL License Terms @ref lgpl_license
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2013 Frantisek Burian <BuFran@seznam.cz>
|
||||
*
|
||||
* 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/ethernet/mac.h>
|
||||
#include <libopencm3/ethernet/phy.h>
|
||||
#include <libopencm3/ethernet/phy_ksz80x1.h>
|
||||
|
||||
|
||||
/**@{*/
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Get the current link status
|
||||
*
|
||||
* Retrieve the link speed and duplex status of the link.
|
||||
*
|
||||
* @param[in] phy uint8_t phy ID of the PHY
|
||||
* @returns ::phy_status Link status
|
||||
*/
|
||||
enum phy_status phy_link_status(uint8_t phy)
|
||||
{
|
||||
return eth_smi_read(phy, KSZ80X1_CR1) & 0x07;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Force autonegotiation
|
||||
*
|
||||
* Force the autonegotiation and set link speed and duplex mode of the link
|
||||
*
|
||||
* @param[in] phy uint8_t phy ID of the PHY
|
||||
* @param[in] mode enum phy_status Desired link status
|
||||
*/
|
||||
void phy_autoneg_force(uint8_t phy, enum phy_status mode)
|
||||
{
|
||||
uint16_t bst = 0;
|
||||
|
||||
if ((mode == LINK_FD_10M) || (mode == LINK_FD_100M) ||
|
||||
(mode == LINK_FD_1000M) || (mode == LINK_FD_10000M)) {
|
||||
bst |= PHY_REG_BCR_FD;
|
||||
}
|
||||
|
||||
if ((mode == LINK_FD_100M) || (mode == LINK_HD_100M)) {
|
||||
bst |= PHY_REG_BCR_100M;
|
||||
}
|
||||
|
||||
eth_smi_bit_op(phy, PHY_REG_BCR, bst,
|
||||
~(PHY_REG_BCR_AN | PHY_REG_BCR_100M | PHY_REG_BCR_FD));
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Enable the autonegotiation
|
||||
*
|
||||
* Enable the autonegotiation of the link speed and duplex mode
|
||||
*
|
||||
* @param[in] phy uint8_t phy ID of the PHY
|
||||
*/
|
||||
void phy_autoneg_enable(uint8_t phy)
|
||||
{
|
||||
eth_smi_bit_set(phy, PHY_REG_BCR, PHY_REG_BCR_AN | PHY_REG_BCR_ANRST);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
|
||||
/**@}*/
|
||||
42
libopencm3/lib/gd32/f1x0/Makefile
Executable file
42
libopencm3/lib/gd32/f1x0/Makefile
Executable file
@@ -0,0 +1,42 @@
|
||||
##
|
||||
## This file is part of the libopencm3 project.
|
||||
##
|
||||
## Copyright (C) 2019 Icenowy Zheng <icenowy@aosc.io>
|
||||
##
|
||||
## 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/>.
|
||||
##
|
||||
|
||||
LIBNAME = libopencm3_gd32f1x0
|
||||
SRCLIBDIR ?= ../..
|
||||
|
||||
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-m3 $(FP_FLAGS) -mthumb -Wstrict-prototypes \
|
||||
-ffunction-sections -fdata-sections -MD -DGD32F1X0
|
||||
TGT_CFLAGS += $(DEBUG_FLAGS)
|
||||
# ARFLAGS = rcsv
|
||||
ARFLAGS = rcs
|
||||
|
||||
OBJS += flash.o flash_common_all.o flash_common_f.o flash_common_f01.o
|
||||
OBJS += gpio_common_all.o gpio_common_f0234.o
|
||||
OBJS += rcc.o rcc_common_all.o
|
||||
|
||||
VPATH += ../:../../cm3:../common:../../stm32/common
|
||||
|
||||
include ../../Makefile.include
|
||||
153
libopencm3/lib/gd32/f1x0/flash.c
Normal file
153
libopencm3/lib/gd32/f1x0/flash.c
Normal file
@@ -0,0 +1,153 @@
|
||||
/** @defgroup flash_file FLASH peripheral API
|
||||
*
|
||||
* @ingroup peripheral_apis
|
||||
*
|
||||
* @brief <b>libopencm3 GD32F1x0 FLASH</b>
|
||||
*
|
||||
* @version 1.0.0
|
||||
*
|
||||
* @author @htmlonly © @endhtmlonly 2013
|
||||
* Frantisek Burian <BuFran@seznam.cz>
|
||||
*
|
||||
* @date 14 January 2014
|
||||
*
|
||||
* FLASH memory may be used for data storage as well as code, and may be
|
||||
* programmatically modified. Note that for firmware upload the GD32F1x0
|
||||
* provides a built-in bootloader in system memory that can be entered from a
|
||||
* running program.
|
||||
*
|
||||
* FLASH must first be unlocked before programming. In this module a write to
|
||||
* FLASH is a blocking operation until the end-of-operation flag is asserted.
|
||||
*
|
||||
* @note: don't forget to lock it again when all operations are complete.
|
||||
*
|
||||
* LGPL License Terms @ref lgpl_license
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2013 Frantisek Burian <BuFran@seznam.cz>
|
||||
*
|
||||
* 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/gd32/flash.h>
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Clear All Status Flags
|
||||
|
||||
Program error, end of operation, write protect error, busy.
|
||||
*/
|
||||
|
||||
void flash_clear_status_flags(void)
|
||||
{
|
||||
flash_clear_pgerr_flag();
|
||||
flash_clear_eop_flag();
|
||||
flash_clear_wrprterr_flag();
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Read All Status Flags
|
||||
|
||||
The programming error, end of operation, write protect error and busy flags
|
||||
are returned in the order of appearance in the status register.
|
||||
|
||||
@returns uint32_t. bit 0: busy, bit 2: programming error, bit 4: write protect
|
||||
error, bit 5: end of operation.
|
||||
*/
|
||||
|
||||
uint32_t flash_get_status_flags(void)
|
||||
{
|
||||
return FLASH_SR & (FLASH_SR_PGERR |
|
||||
FLASH_SR_EOP |
|
||||
FLASH_SR_WRPRTERR |
|
||||
FLASH_SR_BSY);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Program a Half Word to FLASH
|
||||
|
||||
This performs all operations necessary to program a 16 bit word to FLASH memory.
|
||||
The program error flag should be checked separately for the event that memory
|
||||
was not properly erased.
|
||||
|
||||
Status bit polling is used to detect end of operation.
|
||||
|
||||
@param[in] address Full address of flash half word to be programmed.
|
||||
@param[in] data half word to write
|
||||
*/
|
||||
|
||||
void flash_program_half_word(uint32_t address, uint16_t data)
|
||||
{
|
||||
flash_wait_for_last_operation();
|
||||
|
||||
FLASH_CR |= FLASH_CR_PG;
|
||||
|
||||
MMIO16(address) = data;
|
||||
|
||||
flash_wait_for_last_operation();
|
||||
|
||||
FLASH_CR &= ~FLASH_CR_PG;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Erase a Page of FLASH
|
||||
|
||||
This performs all operations necessary to erase a page in FLASH memory.
|
||||
The page should be checked to ensure that it was properly erased. A page must
|
||||
first be fully erased before attempting to program it.
|
||||
|
||||
Note that the page sizes differ between devices. See the reference manual or
|
||||
the FLASH programming manual for details.
|
||||
|
||||
@param[in] page_address Full address of flash page to be erased.
|
||||
*/
|
||||
|
||||
void flash_erase_page(uint32_t page_address)
|
||||
{
|
||||
flash_wait_for_last_operation();
|
||||
|
||||
FLASH_CR |= FLASH_CR_PER;
|
||||
FLASH_AR = page_address;
|
||||
FLASH_CR |= FLASH_CR_STRT;
|
||||
|
||||
flash_wait_for_last_operation();
|
||||
|
||||
FLASH_CR &= ~FLASH_CR_PER;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief Erase All FLASH
|
||||
|
||||
This performs all operations necessary to erase all user pages in the FLASH
|
||||
memory. The information block is unaffected.
|
||||
*/
|
||||
|
||||
void flash_erase_all_pages(void)
|
||||
{
|
||||
flash_wait_for_last_operation();
|
||||
|
||||
FLASH_CR |= FLASH_CR_MER; /* Enable mass erase. */
|
||||
FLASH_CR |= FLASH_CR_STRT; /* Trigger the erase. */
|
||||
|
||||
flash_wait_for_last_operation();
|
||||
FLASH_CR &= ~FLASH_CR_MER; /* Disable mass erase. */
|
||||
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
|
||||
654
libopencm3/lib/gd32/f1x0/rcc.c
Normal file
654
libopencm3/lib/gd32/f1x0/rcc.c
Normal file
@@ -0,0 +1,654 @@
|
||||
/** @defgroup rcc_file RCC peripheral API
|
||||
|
||||
@ingroup peripheral_apis
|
||||
|
||||
@brief <b>libopencm3 GD32F1x0 Reset and Clock Control</b>
|
||||
|
||||
@version 1.0.0
|
||||
|
||||
@author @htmlonly © @endhtmlonly 2009
|
||||
Federico Ruiz-Ugalde \<memeruiz at gmail dot com\>
|
||||
@author @htmlonly © @endhtmlonly 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
@author @htmlonly © @endhtmlonly 2010 Thomas Otto <tommi@viadmin.org>
|
||||
|
||||
@date 18 August 2012
|
||||
|
||||
This library supports the Reset and Clock Control System in the GD32F1x0
|
||||
series of ARM Cortex Microcontrollers by GigaDevice.
|
||||
|
||||
@note Full support for F170 and F190 devices is not yet provided.
|
||||
|
||||
Clock settings and resets for many peripherals are given here rather than in
|
||||
the corresponding peripheral library.
|
||||
|
||||
The library also provides a number of common configurations for the processor
|
||||
system clock. Not all possible configurations are included.
|
||||
|
||||
LGPL License Terms @ref lgpl_license
|
||||
*/
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2019 Icenowy Zheng <icenowy@aosc.io>
|
||||
* Copyright (C) 2009 Federico Ruiz-Ugalde <memeruiz at gmail dot com>
|
||||
* Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
* Copyright (C) 2010 Thomas Otto <tommi@viadmin.org>
|
||||
*
|
||||
* 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/cm3/assert.h>
|
||||
#include <libopencm3/gd32/rcc.h>
|
||||
#include <libopencm3/gd32/flash.h>
|
||||
|
||||
/** Set the default clock frequencies */
|
||||
uint32_t rcc_apb1_frequency = 8000000;
|
||||
uint32_t rcc_apb2_frequency = 8000000;
|
||||
uint32_t rcc_ahb_frequency = 8000000;
|
||||
|
||||
const struct rcc_clock_scale rcc_hsi_configs[] = {
|
||||
{ /* 48MHz */
|
||||
.pllmul = RCC_CFGR_PLLMUL_PLL_CLK_MUL12,
|
||||
.hpre = RCC_CFGR_HPRE_NODIV,
|
||||
.ppre1 = RCC_CFGR_PPRE_DIV2,
|
||||
.ppre2 = RCC_CFGR_PPRE_NODIV,
|
||||
.adcpre = RCC_CFGR_ADCPRE_DIV8,
|
||||
.use_hse = false,
|
||||
.ahb_frequency = 48000000,
|
||||
.apb1_frequency = 24000000,
|
||||
.apb2_frequency = 48000000,
|
||||
},
|
||||
{ /* 64MHz */
|
||||
.pllmul = RCC_CFGR_PLLMUL_PLL_CLK_MUL16,
|
||||
.hpre = RCC_CFGR_HPRE_NODIV,
|
||||
.ppre1 = RCC_CFGR_PPRE_DIV2,
|
||||
.ppre2 = RCC_CFGR_PPRE_NODIV,
|
||||
.adcpre = RCC_CFGR_ADCPRE_DIV8,
|
||||
.use_hse = false,
|
||||
.ahb_frequency = 64000000,
|
||||
.apb1_frequency = 32000000,
|
||||
.apb2_frequency = 64000000,
|
||||
}
|
||||
};
|
||||
|
||||
const struct rcc_clock_scale rcc_hse8_configs[] = {
|
||||
{ /* 72MHz */
|
||||
.pllmul = RCC_CFGR_PLLMUL_PLL_CLK_MUL9,
|
||||
.hpre = RCC_CFGR_HPRE_NODIV,
|
||||
.ppre1 = RCC_CFGR_PPRE_DIV2,
|
||||
.ppre2 = RCC_CFGR_PPRE_NODIV,
|
||||
.adcpre = RCC_CFGR_ADCPRE_DIV8,
|
||||
.usbpre = RCC_CFGR_USBPRE_PLL_CLK_DIV1_5,
|
||||
.use_hse = true,
|
||||
.pll_hse_prediv = RCC_CFGR2_PREDIV_NODIV,
|
||||
.ahb_frequency = 72000000,
|
||||
.apb1_frequency = 36000000,
|
||||
.apb2_frequency = 72000000,
|
||||
},
|
||||
};
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief RCC Clear the Oscillator Ready Interrupt Flag
|
||||
|
||||
Clear the interrupt flag that was set when a clock oscillator became ready to
|
||||
use.
|
||||
|
||||
@param[in] osc Oscillator ID
|
||||
*/
|
||||
|
||||
void rcc_osc_ready_int_clear(enum rcc_osc osc)
|
||||
{
|
||||
switch (osc) {
|
||||
case RCC_PLL:
|
||||
RCC_CIR |= RCC_CIR_PLLRDYC;
|
||||
break;
|
||||
case RCC_HSE:
|
||||
RCC_CIR |= RCC_CIR_HSERDYC;
|
||||
break;
|
||||
case RCC_HSI:
|
||||
RCC_CIR |= RCC_CIR_HSIRDYC;
|
||||
break;
|
||||
case RCC_LSE:
|
||||
RCC_CIR |= RCC_CIR_LSERDYC;
|
||||
break;
|
||||
case RCC_LSI:
|
||||
RCC_CIR |= RCC_CIR_LSIRDYC;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief RCC Enable the Oscillator Ready Interrupt
|
||||
|
||||
@param[in] osc Oscillator ID
|
||||
*/
|
||||
|
||||
void rcc_osc_ready_int_enable(enum rcc_osc osc)
|
||||
{
|
||||
switch (osc) {
|
||||
case RCC_PLL:
|
||||
RCC_CIR |= RCC_CIR_PLLRDYIE;
|
||||
break;
|
||||
case RCC_HSE:
|
||||
RCC_CIR |= RCC_CIR_HSERDYIE;
|
||||
break;
|
||||
case RCC_HSI:
|
||||
RCC_CIR |= RCC_CIR_HSIRDYIE;
|
||||
break;
|
||||
case RCC_LSE:
|
||||
RCC_CIR |= RCC_CIR_LSERDYIE;
|
||||
break;
|
||||
case RCC_LSI:
|
||||
RCC_CIR |= RCC_CIR_LSIRDYIE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief RCC Disable the Oscillator Ready Interrupt
|
||||
|
||||
@param[in] osc Oscillator ID
|
||||
*/
|
||||
|
||||
void rcc_osc_ready_int_disable(enum rcc_osc osc)
|
||||
{
|
||||
switch (osc) {
|
||||
case RCC_PLL:
|
||||
RCC_CIR &= ~RCC_CIR_PLLRDYIE;
|
||||
break;
|
||||
case RCC_HSE:
|
||||
RCC_CIR &= ~RCC_CIR_HSERDYIE;
|
||||
break;
|
||||
case RCC_HSI:
|
||||
RCC_CIR &= ~RCC_CIR_HSIRDYIE;
|
||||
break;
|
||||
case RCC_LSE:
|
||||
RCC_CIR &= ~RCC_CIR_LSERDYIE;
|
||||
break;
|
||||
case RCC_LSI:
|
||||
RCC_CIR &= ~RCC_CIR_LSIRDYIE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief RCC Read the Oscillator Ready Interrupt Flag
|
||||
|
||||
@param[in] osc Oscillator ID
|
||||
@returns int. Boolean value for flag set.
|
||||
*/
|
||||
|
||||
int rcc_osc_ready_int_flag(enum rcc_osc osc)
|
||||
{
|
||||
switch (osc) {
|
||||
case RCC_PLL:
|
||||
return ((RCC_CIR & RCC_CIR_PLLRDYF) != 0);
|
||||
break;
|
||||
case RCC_HSE:
|
||||
return ((RCC_CIR & RCC_CIR_HSERDYF) != 0);
|
||||
break;
|
||||
case RCC_HSI:
|
||||
return ((RCC_CIR & RCC_CIR_HSIRDYF) != 0);
|
||||
break;
|
||||
case RCC_LSE:
|
||||
return ((RCC_CIR & RCC_CIR_LSERDYF) != 0);
|
||||
break;
|
||||
case RCC_LSI:
|
||||
return ((RCC_CIR & RCC_CIR_LSIRDYF) != 0);
|
||||
break;
|
||||
}
|
||||
|
||||
cm3_assert_not_reached();
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief RCC Clear the Clock Security System Interrupt Flag
|
||||
|
||||
*/
|
||||
|
||||
void rcc_css_int_clear(void)
|
||||
{
|
||||
RCC_CIR |= RCC_CIR_CSSC;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief RCC Read the Clock Security System Interrupt Flag
|
||||
|
||||
@returns int. Boolean value for flag set.
|
||||
*/
|
||||
|
||||
int rcc_css_int_flag(void)
|
||||
{
|
||||
return ((RCC_CIR & RCC_CIR_CSSF) != 0);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief RCC Wait for Oscillator Ready.
|
||||
|
||||
@param[in] osc Oscillator ID
|
||||
*/
|
||||
|
||||
void rcc_wait_for_osc_ready(enum rcc_osc osc)
|
||||
{
|
||||
switch (osc) {
|
||||
case RCC_PLL:
|
||||
while ((RCC_CR & RCC_CR_PLLRDY) == 0);
|
||||
break;
|
||||
case RCC_HSE:
|
||||
while ((RCC_CR & RCC_CR_HSERDY) == 0);
|
||||
break;
|
||||
case RCC_HSI:
|
||||
while ((RCC_CR & RCC_CR_HSIRDY) == 0);
|
||||
break;
|
||||
case RCC_LSE:
|
||||
while ((RCC_BDCR & RCC_BDCR_LSERDY) == 0);
|
||||
break;
|
||||
case RCC_LSI:
|
||||
while ((RCC_CSR & RCC_CSR_LSIRDY) == 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief RCC Turn on an Oscillator.
|
||||
|
||||
Enable an oscillator and power on. Each oscillator requires an amount of time
|
||||
to settle to a usable state. Refer to datasheets for time delay information. A
|
||||
status flag is available to indicate when the oscillator becomes ready (see
|
||||
@ref rcc_osc_ready_int_flag and @ref rcc_wait_for_osc_ready).
|
||||
|
||||
@note The LSE clock is in the backup domain and cannot be enabled until the
|
||||
backup domain write protection has been removed (see @ref
|
||||
pwr_disable_backup_domain_write_protect).
|
||||
|
||||
@param[in] osc Oscillator ID
|
||||
*/
|
||||
|
||||
void rcc_osc_on(enum rcc_osc osc)
|
||||
{
|
||||
switch (osc) {
|
||||
case RCC_PLL:
|
||||
RCC_CR |= RCC_CR_PLLON;
|
||||
break;
|
||||
case RCC_HSE:
|
||||
RCC_CR |= RCC_CR_HSEON;
|
||||
break;
|
||||
case RCC_HSI:
|
||||
RCC_CR |= RCC_CR_HSION;
|
||||
break;
|
||||
case RCC_LSE:
|
||||
RCC_BDCR |= RCC_BDCR_LSEON;
|
||||
break;
|
||||
case RCC_LSI:
|
||||
RCC_CSR |= RCC_CSR_LSION;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief RCC Turn off an Oscillator.
|
||||
|
||||
Disable an oscillator and power off.
|
||||
|
||||
@note An oscillator cannot be turned off if it is selected as the system clock.
|
||||
@note The LSE clock is in the backup domain and cannot be disabled until the
|
||||
backup domain write protection has been removed (see
|
||||
@ref pwr_disable_backup_domain_write_protect) or the backup domain has been
|
||||
(see reset @ref rcc_backupdomain_reset).
|
||||
|
||||
@param[in] osc Oscillator ID
|
||||
*/
|
||||
|
||||
void rcc_osc_off(enum rcc_osc osc)
|
||||
{
|
||||
switch (osc) {
|
||||
case RCC_PLL:
|
||||
RCC_CR &= ~RCC_CR_PLLON;
|
||||
break;
|
||||
case RCC_HSE:
|
||||
RCC_CR &= ~RCC_CR_HSEON;
|
||||
break;
|
||||
case RCC_HSI:
|
||||
RCC_CR &= ~RCC_CR_HSION;
|
||||
break;
|
||||
case RCC_LSE:
|
||||
RCC_BDCR &= ~RCC_BDCR_LSEON;
|
||||
break;
|
||||
case RCC_LSI:
|
||||
RCC_CSR &= ~RCC_CSR_LSION;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief RCC Enable the Clock Security System.
|
||||
|
||||
*/
|
||||
|
||||
void rcc_css_enable(void)
|
||||
{
|
||||
RCC_CR |= RCC_CR_CSSON;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief RCC Disable the Clock Security System.
|
||||
|
||||
*/
|
||||
|
||||
void rcc_css_disable(void)
|
||||
{
|
||||
RCC_CR &= ~RCC_CR_CSSON;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief RCC Set the Source for the System Clock.
|
||||
|
||||
@param[in] clk System Clock Selection @ref rcc_cfgr_scs
|
||||
*/
|
||||
|
||||
void rcc_set_sysclk_source(uint32_t clk)
|
||||
{
|
||||
RCC_CFGR = (RCC_CFGR & ~RCC_CFGR_SW) |
|
||||
(clk << RCC_CFGR_SW_SHIFT);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief RCC Set the PLL Multiplication Factor.
|
||||
|
||||
@note This only has effect when the PLL is disabled.
|
||||
|
||||
@param[in] mul PLL multiplication factor @ref rcc_cfgr_pmf
|
||||
*/
|
||||
|
||||
void rcc_set_pll_multiplication_factor(uint32_t mul)
|
||||
{
|
||||
RCC_CFGR = (RCC_CFGR & ~RCC_CFGR_PLLMUL_0_3 & ~RCC_CFGR_PLLMUL_4) |
|
||||
((mul & 0xf) << RCC_CFGR_PLLMUL_0_3_SHIFT) |
|
||||
((!!(mul & 0x10)) << RCC_CFGR_PLLMUL_4_SHIFT);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief RCC Set the PLL Clock Source.
|
||||
|
||||
@note This only has effect when the PLL is disabled.
|
||||
|
||||
@param[in] pllsrc PLL clock source @ref rcc_cfgr_pcs
|
||||
*/
|
||||
|
||||
void rcc_set_pll_source(uint32_t pllsrc)
|
||||
{
|
||||
RCC_CFGR = (RCC_CFGR & ~RCC_CFGR_PLLSRC) |
|
||||
(pllsrc << 16);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief RCC Set the HSE Frequency Divider used as PLL Clock Source.
|
||||
|
||||
@note This only has effect when the PLL is disabled.
|
||||
|
||||
@param[in] pllxtpre HSE division factor @ref rcc_cfgr_hsepre
|
||||
*/
|
||||
|
||||
void rcc_set_pllxtpre(uint32_t pllxtpre)
|
||||
{
|
||||
RCC_CFGR = (RCC_CFGR & ~RCC_CFGR_PLLXTPRE) |
|
||||
(pllxtpre << 17);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief RCC RTC Clock Enabled Flag
|
||||
|
||||
@returns uint32_t. Nonzero if the RTC Clock is enabled.
|
||||
*/
|
||||
|
||||
uint32_t rcc_rtc_clock_enabled_flag(void)
|
||||
{
|
||||
return RCC_BDCR & RCC_BDCR_RTCEN;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief RCC Enable the RTC clock
|
||||
|
||||
*/
|
||||
|
||||
void rcc_enable_rtc_clock(void)
|
||||
{
|
||||
RCC_BDCR |= RCC_BDCR_RTCEN;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief RCC Set the Source for the RTC clock
|
||||
|
||||
@param[in] clock_source RTC clock source. Only HSE/128, LSE and LSI.
|
||||
*/
|
||||
|
||||
void rcc_set_rtc_clock_source(enum rcc_osc clock_source)
|
||||
{
|
||||
uint32_t reg32;
|
||||
|
||||
switch (clock_source) {
|
||||
case RCC_LSE:
|
||||
/* Turn the LSE on and wait while it stabilises. */
|
||||
RCC_BDCR |= RCC_BDCR_LSEON;
|
||||
while ((reg32 = (RCC_BDCR & RCC_BDCR_LSERDY)) == 0);
|
||||
|
||||
/* Choose LSE as the RTC clock source. */
|
||||
RCC_BDCR &= ~((1 << 8) | (1 << 9));
|
||||
RCC_BDCR |= (1 << 8);
|
||||
break;
|
||||
case RCC_LSI:
|
||||
/* Turn the LSI on and wait while it stabilises. */
|
||||
RCC_CSR |= RCC_CSR_LSION;
|
||||
while ((reg32 = (RCC_CSR & RCC_CSR_LSIRDY)) == 0);
|
||||
|
||||
/* Choose LSI as the RTC clock source. */
|
||||
RCC_BDCR &= ~((1 << 8) | (1 << 9));
|
||||
RCC_BDCR |= (1 << 9);
|
||||
break;
|
||||
case RCC_HSE:
|
||||
/* Turn the HSE on and wait while it stabilises. */
|
||||
RCC_CR |= RCC_CR_HSEON;
|
||||
while ((reg32 = (RCC_CR & RCC_CR_HSERDY)) == 0);
|
||||
|
||||
/* Choose HSE as the RTC clock source. */
|
||||
RCC_BDCR &= ~((1 << 8) | (1 << 9));
|
||||
RCC_BDCR |= (1 << 9) | (1 << 8);
|
||||
break;
|
||||
case RCC_PLL:
|
||||
case RCC_HSI:
|
||||
/* Unusable clock source, here to prevent warnings. */
|
||||
/* Turn off clock sources to RTC. */
|
||||
RCC_BDCR &= ~((1 << 8) | (1 << 9));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief ADC Setup the A/D Clock
|
||||
|
||||
The ADC's have a common clock prescale setting.
|
||||
|
||||
@param[in] adcpre Prescale divider taken from @ref rcc_cfgr_adcpre
|
||||
*/
|
||||
|
||||
void rcc_set_adcpre(uint32_t adcpre)
|
||||
{
|
||||
RCC_CFGR = (RCC_CFGR & ~RCC_CFGR_ADCPRE) |
|
||||
(adcpre << RCC_CFGR_ADCPRE_SHIFT);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief RCC Set the APB2 Prescale Factor.
|
||||
|
||||
@param[in] ppre2 APB2 prescale factor @ref rcc_cfgr_apb2pre
|
||||
*/
|
||||
|
||||
void rcc_set_ppre2(uint32_t ppre2)
|
||||
{
|
||||
RCC_CFGR = (RCC_CFGR & ~RCC_CFGR_PPRE2) |
|
||||
(ppre2 << RCC_CFGR_PPRE2_SHIFT);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief RCC Set the APB1 Prescale Factor.
|
||||
|
||||
@note The APB1 clock frequency must not exceed 36MHz.
|
||||
|
||||
@param[in] ppre1 APB1 prescale factor @ref rcc_cfgr_apb1pre
|
||||
*/
|
||||
|
||||
void rcc_set_ppre1(uint32_t ppre1)
|
||||
{
|
||||
RCC_CFGR = (RCC_CFGR & ~RCC_CFGR_PPRE1) |
|
||||
(ppre1 << RCC_CFGR_PPRE1_SHIFT);
|
||||
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief RCC Set the AHB Prescale Factor.
|
||||
|
||||
@param[in] hpre AHB prescale factor @ref rcc_cfgr_ahbpre
|
||||
*/
|
||||
|
||||
void rcc_set_hpre(uint32_t hpre)
|
||||
{
|
||||
RCC_CFGR = (RCC_CFGR & ~RCC_CFGR_HPRE) |
|
||||
(hpre << RCC_CFGR_HPRE_SHIFT);
|
||||
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief RCC Set the USB Prescale Factor.
|
||||
|
||||
The prescale factor can be set to 1 (no prescale) for use when the PLL clock is
|
||||
48MHz, or 1.5 to generate the 48MHz USB clock from a 64MHz PLL clock.
|
||||
|
||||
@note This bit cannot be reset while the USB clock is enabled.
|
||||
|
||||
@param[in] usbpre USB prescale factor @ref rcc_cfgr_usbpre
|
||||
*/
|
||||
|
||||
void rcc_set_usbpre(uint32_t usbpre)
|
||||
{
|
||||
RCC_CFGR = (RCC_CFGR & ~RCC_CFGR_USBPRE) | usbpre;
|
||||
}
|
||||
|
||||
void rcc_set_prediv(uint32_t prediv)
|
||||
{
|
||||
RCC_CFGR2 = (RCC_CFGR2 & ~RCC_CFGR2_PREDIV) | prediv;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief RCC Get the System Clock Source.
|
||||
|
||||
@returns Unsigned int32. System clock source:
|
||||
@li 00 indicates HSE
|
||||
@li 01 indicates LSE
|
||||
@li 02 indicates PLL
|
||||
*/
|
||||
|
||||
uint32_t rcc_system_clock_source(void)
|
||||
{
|
||||
/* Return the clock source which is used as system clock. */
|
||||
return (RCC_CFGR & RCC_CFGR_SWS) >> RCC_CFGR_SWS_SHIFT;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/*
|
||||
* These functions are setting up the whole clock system for the most common
|
||||
* input clock and output clock configurations.
|
||||
*/
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/**
|
||||
* Setup clocks to run from PLL.
|
||||
* The arguments provide the pll source, multipliers, dividers, all that's
|
||||
* needed to establish a system clock.
|
||||
* @param clock clock information structure
|
||||
*/
|
||||
void rcc_clock_setup_pll(const struct rcc_clock_scale *clock)
|
||||
{
|
||||
if (clock->use_hse) {
|
||||
/* Enable external high-speed oscillator. */
|
||||
rcc_osc_on(RCC_HSE);
|
||||
rcc_wait_for_osc_ready(RCC_HSE);
|
||||
rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_HSECLK);
|
||||
} else {
|
||||
/* Enable internal high-speed oscillator. */
|
||||
rcc_osc_on(RCC_HSI);
|
||||
rcc_wait_for_osc_ready(RCC_HSI);
|
||||
rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_HSICLK);
|
||||
}
|
||||
|
||||
/*
|
||||
* Set prescalers for AHB, ADC, APB1, APB2 and USB.
|
||||
* Do this before touching the PLL (TODO: why?).
|
||||
*/
|
||||
rcc_set_hpre(clock->hpre);
|
||||
rcc_set_ppre1(clock->ppre1);
|
||||
rcc_set_ppre2(clock->ppre2);
|
||||
|
||||
rcc_set_adcpre(clock->adcpre);
|
||||
if (clock->use_hse)
|
||||
rcc_set_usbpre(clock->usbpre);
|
||||
|
||||
/* Set the PLL multiplication factor. */
|
||||
rcc_set_pll_multiplication_factor(clock->pllmul);
|
||||
|
||||
if (clock->use_hse) {
|
||||
/* Select HSE as PLL source. */
|
||||
rcc_set_pll_source(RCC_CFGR_PLLSRC_HSE_CLK);
|
||||
|
||||
/*
|
||||
* External frequency undivided before entering PLL
|
||||
* (only valid/needed for HSE).
|
||||
*/
|
||||
rcc_set_prediv(clock->pll_hse_prediv);
|
||||
} else {
|
||||
/* Select HSI/2 as PLL source. */
|
||||
rcc_set_pll_source(RCC_CFGR_PLLSRC_HSI_CLK_DIV2);
|
||||
}
|
||||
|
||||
/* Enable PLL oscillator and wait for it to stabilize. */
|
||||
rcc_osc_on(RCC_PLL);
|
||||
rcc_wait_for_osc_ready(RCC_PLL);
|
||||
|
||||
/* Select PLL as SYSCLK source. */
|
||||
rcc_set_sysclk_source(RCC_CFGR_SW_SYSCLKSEL_PLLCLK);
|
||||
|
||||
/* Set the peripheral clock frequencies used */
|
||||
rcc_ahb_frequency = clock->ahb_frequency;
|
||||
rcc_apb1_frequency = clock->apb1_frequency;
|
||||
rcc_apb2_frequency = clock->apb2_frequency;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief RCC Reset the Backup Domain
|
||||
|
||||
The backup domain registers are reset to disable RTC controls and clear user
|
||||
data.
|
||||
*/
|
||||
|
||||
void rcc_backupdomain_reset(void)
|
||||
{
|
||||
/* Set the backup domain software reset. */
|
||||
RCC_BDCR |= RCC_BDCR_BDRST;
|
||||
|
||||
/* Clear the backup domain software reset. */
|
||||
RCC_BDCR &= ~RCC_BDCR_BDRST;
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
|
||||
45
libopencm3/lib/lm3s/Makefile
Normal file
45
libopencm3/lib/lm3s/Makefile
Normal file
@@ -0,0 +1,45 @@
|
||||
##
|
||||
## This file is part of the libopencm3 project.
|
||||
##
|
||||
## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
##
|
||||
## 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/>.
|
||||
##
|
||||
|
||||
LIBNAME = libopencm3_lm3s
|
||||
SRCLIBDIR ?= ..
|
||||
|
||||
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-m3 -mthumb $(FP_FLAGS) -Wstrict-prototypes \
|
||||
-ffunction-sections -fdata-sections -MD -DLM3S
|
||||
TGT_CFLAGS += $(DEBUG_FLAGS)
|
||||
TGT_CFLAGS += $(STANDARD_FLAGS)
|
||||
# ARFLAGS = rcsv
|
||||
ARFLAGS = rcs
|
||||
|
||||
OBJS += assert.o
|
||||
OBJS += gpio.o
|
||||
OBJS += rcc.o
|
||||
OBJS += usart.o
|
||||
OBJS += vector.o
|
||||
|
||||
VPATH += ../cm3
|
||||
|
||||
include ../Makefile.include
|
||||
52
libopencm3/lib/lm3s/gpio.c
Normal file
52
libopencm3/lib/lm3s/gpio.c
Normal file
@@ -0,0 +1,52 @@
|
||||
/** @defgroup gpio_file General Purpose I/O
|
||||
|
||||
@brief <b>LM3S General Purpose I/O</b>
|
||||
|
||||
@ingroup LM3Sxx
|
||||
|
||||
@version 1.0.0
|
||||
|
||||
@author @htmlonly © @endhtmlonly 2011
|
||||
Gareth McMullin <gareth@blacksphere.co.nz>
|
||||
|
||||
@date 10 March 2013
|
||||
|
||||
LGPL License Terms @ref lgpl_license
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2011 Gareth McMullin <gareth@blacksphere.co.nz>
|
||||
*
|
||||
* 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/lm3s/gpio.h>
|
||||
|
||||
void gpio_set(uint32_t gpioport, uint8_t gpios)
|
||||
{
|
||||
/* ipaddr[9:2] mask the bits to be set, hence the array index */
|
||||
GPIO_DATA(gpioport)[gpios] = 0xff;
|
||||
}
|
||||
|
||||
void gpio_clear(uint32_t gpioport, uint8_t gpios)
|
||||
{
|
||||
GPIO_DATA(gpioport)[gpios] = 0;
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
|
||||
77
libopencm3/lib/lm3s/rcc.c
Normal file
77
libopencm3/lib/lm3s/rcc.c
Normal file
@@ -0,0 +1,77 @@
|
||||
/** @defgroup rcc_file RCC Controller
|
||||
|
||||
@brief <b>LM3S RCC Controller</b>
|
||||
|
||||
@ingroup LM3Sxx
|
||||
|
||||
@version 1.0.0
|
||||
|
||||
@author @htmlonly © @endhtmlonly 2015
|
||||
Daniele Lacamera \<root at danielinux dot net\>
|
||||
|
||||
@date 21 November 2015
|
||||
|
||||
LGPL License Terms @ref lgpl_license
|
||||
*/
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2015 Daniele Lacamera <root@danielinux.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 <stdint.h>
|
||||
#include <libopencm3/lm3s/rcc.h>
|
||||
#include <libopencm3/cm3/sync.h>
|
||||
|
||||
int rcc_clock_setup_in_xtal_8mhz_out_50mhz(void)
|
||||
{
|
||||
uint32_t rcc = RCC_RESET_VALUE;
|
||||
uint32_t rcc2 = RCC2_RESET_VALUE;
|
||||
|
||||
/* Stage 0: Reset values applied */
|
||||
RCC_CR = rcc;
|
||||
RCC2_CR = rcc2;
|
||||
__dmb();
|
||||
|
||||
/* Stage 1: Reset Oscillators and select configured values */
|
||||
RCC_CR = RCC_SYSDIV_50MHZ | RCC_PWMDIV_64 | RCC_XTAL_8MHZ_400MHZ | RCC_USEPWMDIV;
|
||||
RCC2_CR = (4 - 1) << RCC2_SYSDIV2_SHIFT;
|
||||
__dmb();
|
||||
|
||||
/* Stage 2: Power on oscillators */
|
||||
rcc &= ~RCC_OFF;
|
||||
rcc2 &= ~RCC2_OFF;
|
||||
RCC_CR = rcc;
|
||||
RCC2_CR = rcc2;
|
||||
__dmb();
|
||||
|
||||
/* Stage 3: Set USESYSDIV */
|
||||
rcc |= RCC_BYPASS | RCC_USESYSDIV;
|
||||
RCC_CR = rcc;
|
||||
__dmb();
|
||||
|
||||
/* Stage 4: Wait for PLL raw interrupt */
|
||||
while ((RCC_RIS & RIS_PLLLRIS) == 0)
|
||||
;
|
||||
|
||||
/* Stage 5: Disable bypass */
|
||||
rcc &= ~RCC_BYPASS;
|
||||
rcc2 &= ~RCC2_BYPASS;
|
||||
RCC_CR = rcc;
|
||||
RCC2_CR = rcc2;
|
||||
__dmb();
|
||||
return 0;
|
||||
}
|
||||
88
libopencm3/lib/lm3s/usart.c
Normal file
88
libopencm3/lib/lm3s/usart.c
Normal file
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2013 Gareth McMullin <gareth@blacksphere.co.nz>
|
||||
* Copyright (C) 2015 Daniele Lacamera <root at danielinux.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/lm3s/usart.h>
|
||||
|
||||
void usart_send(uint32_t usart, uint16_t data)
|
||||
{
|
||||
USART_DR(usart) = data;
|
||||
}
|
||||
|
||||
uint16_t usart_recv(uint32_t usart)
|
||||
{
|
||||
return USART_DR(usart) & 0xff;
|
||||
}
|
||||
|
||||
void usart_send_blocking(uint32_t usart, uint16_t data)
|
||||
{
|
||||
while (!usart_is_send_ready(usart));
|
||||
usart_send(usart, data);
|
||||
}
|
||||
|
||||
bool usart_is_recv_ready(uint32_t usart)
|
||||
{
|
||||
return ((USART_FR(usart) & USART_FR_RXFE) == 0);
|
||||
}
|
||||
|
||||
bool usart_is_send_ready(uint32_t usart)
|
||||
{
|
||||
return ((USART_FR(usart) & USART_FR_BUSY) == 0);
|
||||
}
|
||||
|
||||
uint16_t usart_recv_blocking(uint32_t usart)
|
||||
{
|
||||
while (!usart_is_recv_ready(usart));
|
||||
return usart_recv(usart);
|
||||
}
|
||||
|
||||
void usart_enable_rx_interrupt(uint32_t usart)
|
||||
{
|
||||
USART_IM(usart) |= USART_IM_RX;
|
||||
}
|
||||
|
||||
void usart_enable_tx_interrupt(uint32_t usart)
|
||||
{
|
||||
USART_IM(usart) |= USART_IM_TX;
|
||||
}
|
||||
|
||||
void usart_disable_rx_interrupt(uint32_t usart)
|
||||
{
|
||||
USART_IM(usart) &= (~USART_IM_RX);
|
||||
}
|
||||
|
||||
void usart_disable_tx_interrupt(uint32_t usart)
|
||||
{
|
||||
USART_IM(usart) &= (~USART_IM_TX);
|
||||
}
|
||||
|
||||
void usart_clear_rx_interrupt(uint32_t usart)
|
||||
{
|
||||
USART_IC(usart) |= USART_IC_RX;
|
||||
}
|
||||
|
||||
void usart_clear_tx_interrupt(uint32_t usart)
|
||||
{
|
||||
USART_IC(usart) |= USART_IC_TX;
|
||||
}
|
||||
|
||||
bool usart_get_interrupt_source(uint32_t usart, uint32_t flag)
|
||||
{
|
||||
return ((USART_RIS(usart) & flag) != 0);
|
||||
}
|
||||
53
libopencm3/lib/lm4f/Makefile
Normal file
53
libopencm3/lib/lm4f/Makefile
Normal file
@@ -0,0 +1,53 @@
|
||||
##
|
||||
## This file is part of the libopencm3 project.
|
||||
##
|
||||
## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
## Copyright (C) 2013 Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
||||
##
|
||||
## 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/>.
|
||||
##
|
||||
|
||||
LIBNAME = libopencm3_lm4f
|
||||
SRCLIBDIR ?= ..
|
||||
|
||||
FP_FLAGS ?= -mfloat-abi=hard -mfpu=fpv4-sp-d16
|
||||
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-m4 -mthumb $(FP_FLAGS) -Wstrict-prototypes \
|
||||
-ffunction-sections -fdata-sections -MD -DLM4F
|
||||
TGT_CFLAGS += $(DEBUG_FLAGS)
|
||||
TGT_CFLAGS += $(STANDARD_FLAGS)
|
||||
# ARFLAGS = rcsv
|
||||
ARFLAGS = rcs
|
||||
|
||||
OBJS += assert.o
|
||||
OBJS += gpio.o
|
||||
OBJS += rcc.o
|
||||
OBJS += systemcontrol.o
|
||||
OBJS += uart.o
|
||||
OBJS += vector.o
|
||||
|
||||
OBJS += usb.o usb_control.o usb_standard.o usb_msc.o
|
||||
OBJS += usb_hid.o
|
||||
OBJS += usb_audio.o usb_cdc.o usb_midi.o
|
||||
OBJS += usb_lm4f.o
|
||||
|
||||
VPATH += ../usb:../cm3
|
||||
|
||||
include ../Makefile.include
|
||||
598
libopencm3/lib/lm4f/gpio.c
Normal file
598
libopencm3/lib/lm4f/gpio.c
Normal file
@@ -0,0 +1,598 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2011 Gareth McMullin <gareth@blacksphere.co.nz>
|
||||
* Copyright (C) 2013 Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/** @defgroup gpio_file GPIO
|
||||
*
|
||||
*
|
||||
* @ingroup LM4Fxx
|
||||
*
|
||||
* @version 1.0.0
|
||||
*
|
||||
* @author @htmlonly © @endhtmlonly 2011
|
||||
* Gareth McMullin <gareth@blacksphere.co.nz>
|
||||
* @author @htmlonly © @endhtmlonly 2013
|
||||
* Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
||||
*
|
||||
* @date 16 March 2013
|
||||
*
|
||||
* LGPL License Terms @ref lgpl_license
|
||||
*
|
||||
* @brief <b>libopencm3 LM4F General Purpose I/O</b>
|
||||
*
|
||||
* The LM4F GPIO API provides functionality for accessing the GPIO pins of the
|
||||
* LM4F.
|
||||
*
|
||||
* @attention @code An important aspect to consider is that libopencm3 uses the
|
||||
* AHB aperture for accessing the GPIO registers on the LM4F. The AHB must be
|
||||
* explicitly enabled with a call to gpio_enable_ahb_aperture() before accessing
|
||||
* any GPIO functionality.
|
||||
* @endcode
|
||||
*
|
||||
* Please see the individual GPIO modules for more details. To use the GPIO, the
|
||||
* gpio.h header needs to be included:
|
||||
* @code{.c}
|
||||
* #include <libopencm3/lm4f/gpio.h>
|
||||
* @endcode
|
||||
*/
|
||||
|
||||
/**@{*/
|
||||
|
||||
#include <libopencm3/lm4f/gpio.h>
|
||||
#include <libopencm3/lm4f/systemcontrol.h>
|
||||
|
||||
/* Value we need to write to unlock the GPIO commit register */
|
||||
#define GPIO_LOCK_UNLOCK_CODE 0x4C4F434B
|
||||
|
||||
|
||||
/** @defgroup gpio_config GPIO pin configuration
|
||||
* @ingroup gpio_file
|
||||
*
|
||||
* \brief <b>Enabling and configuring GPIO pins</b>
|
||||
*
|
||||
* @section gpio_api_enable Enabling GPIO ports
|
||||
* @attention
|
||||
* Before accessing GPIO functionality through this API, the AHB aperture for
|
||||
* GPIO ports must be enabled via a call to @ref gpio_enable_ahb_aperture().
|
||||
* Failing to do so will cause a hard fault.
|
||||
*
|
||||
* @note
|
||||
* Once the AHB aperture is enabled, GPIO registers can no longer be accessed
|
||||
* via the APB aperture. The two apertures are mutually exclusive.
|
||||
*
|
||||
* Enabling the AHB aperture only needs to be done once. However, in order to
|
||||
* access a certain GPIO port, its clock must also be enabled. Enabling the
|
||||
* GPIO clock needs to be done for every port that will be used.
|
||||
*
|
||||
* For example, to enable GPIOA and GPIOD:
|
||||
* @code{.c}
|
||||
* // Make sure we can access the GPIO via the AHB aperture
|
||||
* gpio_enable_ahb_aperture();
|
||||
* ...
|
||||
* // Enable GPIO ports A and D
|
||||
* periph_clock_enable(RCC_GPIOA);
|
||||
* periph_clock_enable(RCC_GPIOD);
|
||||
* @endcode
|
||||
*
|
||||
* On reset all ports are configured as digital floating inputs (no pull-up or
|
||||
* pull-down), except for special function pins.
|
||||
*
|
||||
*
|
||||
* @section gpio_api_in Configuring pins as inputs
|
||||
*
|
||||
* Configuring GPIO pins as inputs is done with @ref gpio_mode_setup(), with
|
||||
* @ref GPIO_MODE_INPUT for the mode parameter. The direction of the pull-up
|
||||
* must be specified with the same call
|
||||
*
|
||||
* For example, PA2, PA3, and PA4 as inputs, with pull-up on PA4:
|
||||
* @code{.c}
|
||||
* gpio_mode_setup(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO2 | GPIO3);
|
||||
* gpio_mode_setup(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_PULLUP, GPIO4);
|
||||
* @endcode
|
||||
*
|
||||
*
|
||||
* @section gpio_api_out Configuring pins as outputs
|
||||
*
|
||||
* Output pins have more configuration options than input pins. LM4F pins can be
|
||||
* configured as either push-pull, or open drain. The drive strength of each pin
|
||||
* can be adjusted between 2mA, 4mA, or 8mA. Slew-rate control is available when
|
||||
* the pins are configured to drive 8mA. These extra options can be specified
|
||||
* with @ref gpio_set_output_config().
|
||||
* The default is push-pull configuration with 2mA drive capability.
|
||||
*
|
||||
* @note
|
||||
* @ref gpio_set_output_config() controls different capabilities than the
|
||||
* similar sounding gpio_set_output_options() from the STM GPIO API. They are
|
||||
* intentionally named differently to prevent confusion between the two. They
|
||||
* are API incompatible.
|
||||
*
|
||||
* For example, to set PA2 to output push-pull with a drive strength of 8mA:
|
||||
* @code{.c}
|
||||
* gpio_mode_setup(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO2);
|
||||
* gpio_set_output_config(GPIOA, GPIO_OTYPE_PP, GPIO_DRIVE_8MA, GPIO2);
|
||||
* @endcode
|
||||
*
|
||||
*
|
||||
* @section gpio_api_analog Configuring pins as analog function
|
||||
*
|
||||
* Configuring GPIO pins to their analog function is done with
|
||||
* @ref gpio_mode_setup(), with @ref GPIO_MODE_ANALOG for the mode parameter.
|
||||
*
|
||||
* Suppose PD4 and PD5 are the USB pins. To enable their analog functionality
|
||||
* (USB D+ and D- in this case), use:
|
||||
* @code
|
||||
* // Mux USB pins to their analog function
|
||||
* gpio_mode_setup(GPIOD, GPIO_MODE_ANALOG, GPIO_PUPD_NONE, GPIO4 | GPIO5);
|
||||
* @endcode
|
||||
*
|
||||
* @section gpio_api_alf_func Configuring pins as alternate functions
|
||||
*
|
||||
* Most pins have alternate functions associated with them. When a pin is set to
|
||||
* an alternate function, it is multiplexed to one of the dedicated hardware
|
||||
* peripheral in the chip. The alternate function mapping can be found in the
|
||||
* part's datasheet, and usually varies between arts of the same family.
|
||||
*
|
||||
* Multiplexing a pin, or group of pins to an alternate function is done with
|
||||
* @ref gpio_set_af(). Because AF0 is not used on the LM4F, passing 0 as the
|
||||
* alt_func_num parameter will disable the alternate function of the given pins.
|
||||
*
|
||||
* @code
|
||||
* // Mux PB0 and PB1 to AF1 (UART1 TX/RX in this case)
|
||||
* gpio_set_af(GPIOB, 1, GPIO0 | GPIO1);
|
||||
* @endcode
|
||||
*
|
||||
* @section gpio_api_sfpins Changing configuration of special function pins
|
||||
*
|
||||
* On the LM4F, the NMI and JTAG/SWD default to their alternate function. These
|
||||
* pins cannot normally be committed to GPIO usage. To enable these special
|
||||
* function pins to be used as GPIO, they must be unlocked. This may be achieved
|
||||
* via @ref gpio_unlock_commit. Once a special function pin is unlocked, its
|
||||
* settings may be altered in the usual way.
|
||||
*
|
||||
* For example, to unlock the PF0 pin (NMI on the LM4F120):
|
||||
* @code
|
||||
* // PF0 is an NMI pin, and needs to be unlocked
|
||||
* gpio_unlock_commit(GPIOF, GPIO0);
|
||||
* // Now the pin can be configured
|
||||
* gpio_mode_setup(RGB_PORT, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP, btnpins);
|
||||
* @endcode
|
||||
*/
|
||||
/**@{*/
|
||||
|
||||
/**
|
||||
* \brief Enable access to GPIO registers via the AHB aperture
|
||||
*
|
||||
* All GPIO registers are accessed in libopencm3 via the AHB aperture. It
|
||||
* provides faster control over the older APB aperture. This aperture must be
|
||||
* enabled before calling any other gpio_*() function.
|
||||
*
|
||||
*/
|
||||
void gpio_enable_ahb_aperture(void)
|
||||
{
|
||||
SYSCTL_GPIOHBCTL = 0xffffffff;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Configure a group of pins
|
||||
*
|
||||
* Sets the Pin direction, analog/digital mode, and pull-up configuration of
|
||||
* or a set of GPIO pins on a given GPIO port.
|
||||
*
|
||||
* @param[in] gpioport GPIO block register address base @ref gpio_reg_base
|
||||
* @param[in] mode Pin mode (@ref gpio_mode) \n
|
||||
* - GPIO_MODE_OUTPUT -- Configure pin as output \n
|
||||
* - GPIO_MODE_INPUT -- Configure pin as input \n
|
||||
* - GPIO_MODE_ANALOG -- Configure pin as analog function
|
||||
* @param[in] pullup Pin pullup/pulldown configuration (@ref gpio_pullup) \n
|
||||
* - GPIO_PUPD_NONE -- Do not pull the pin high or low \n
|
||||
* - GPIO_PUPD_PULLUP -- Pull the pin high \n
|
||||
* - GPIO_PUPD_PULLDOWN -- Pull the pin low
|
||||
* @param[in] gpios @ref gpio_pin_id. Any combination of pins may be specified
|
||||
* by OR'ing then together
|
||||
*/
|
||||
void gpio_mode_setup(uint32_t gpioport, enum gpio_mode mode,
|
||||
enum gpio_pullup pullup, uint8_t gpios)
|
||||
{
|
||||
switch (mode) {
|
||||
case GPIO_MODE_OUTPUT:
|
||||
GPIO_DIR(gpioport) |= gpios;
|
||||
GPIO_DEN(gpioport) |= gpios;
|
||||
GPIO_AMSEL(gpioport) &= ~gpios;
|
||||
break;
|
||||
case GPIO_MODE_INPUT:
|
||||
GPIO_DIR(gpioport) &= ~gpios;
|
||||
GPIO_DEN(gpioport) |= gpios;
|
||||
GPIO_AMSEL(gpioport) &= ~gpios;
|
||||
break;
|
||||
case GPIO_MODE_ANALOG:
|
||||
GPIO_DEN(gpioport) &= ~gpios;
|
||||
GPIO_AMSEL(gpioport) |= gpios;
|
||||
break;
|
||||
default:
|
||||
/* Don't do anything */
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Setting a bit in the GPIO_PDR register clears the corresponding bit
|
||||
* in the GPIO_PUR register, and vice-versa.
|
||||
*/
|
||||
switch (pullup) {
|
||||
case GPIO_PUPD_PULLUP:
|
||||
GPIO_PUR(gpioport) |= gpios;
|
||||
break;
|
||||
case GPIO_PUPD_PULLDOWN:
|
||||
GPIO_PDR(gpioport) |= gpios;
|
||||
break;
|
||||
case GPIO_PUPD_NONE: /* Fall through */
|
||||
default:
|
||||
GPIO_PUR(gpioport) &= ~gpios;
|
||||
GPIO_PDR(gpioport) &= ~gpios;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Configure output parameters of a group of pins
|
||||
*
|
||||
* Sets the output configuration and drive strength, of or a set of GPIO pins
|
||||
* for a set of GPIO pins in output mode.
|
||||
*
|
||||
* @param[in] gpioport GPIO block register address base @ref gpio_reg_base
|
||||
* @param[in] otype Output driver configuration (@ref gpio_output_type) \n
|
||||
* - GPIO_OTYPE_PP -- Configure pin driver as push-pull \n
|
||||
* - GPIO_OTYPE_OD -- Configure pin driver as open drain
|
||||
* @param[in] drive Pin drive strength (@ref gpio_drive_strength) \n
|
||||
* - GPIO_DRIVE_2MA -- 2mA drive \n
|
||||
* - GPIO_DRIVE_4MA -- 4mA drive \n
|
||||
* - GPIO_DRIVE_8MA -- 8mA drive \n
|
||||
* - GPIO_DRIVE_8MA_SLEW_CTL -- 8mA drive with slew rate
|
||||
* control
|
||||
* @param[in] gpios @ref gpio_pin_id. Any combination of pins may be specified
|
||||
* by OR'ing then together
|
||||
*/
|
||||
void gpio_set_output_config(uint32_t gpioport, enum gpio_output_type otype,
|
||||
enum gpio_drive_strength drive, uint8_t gpios)
|
||||
{
|
||||
if (otype == GPIO_OTYPE_OD) {
|
||||
GPIO_ODR(gpioport) |= gpios;
|
||||
} else {
|
||||
GPIO_ODR(gpioport) &= ~gpios;
|
||||
}
|
||||
|
||||
/*
|
||||
* Setting a bit in the GPIO_DRxR register clears the corresponding bit
|
||||
* in the other GPIO_DRyR registers, and vice-versa.
|
||||
*/
|
||||
switch (drive) {
|
||||
case GPIO_DRIVE_8MA_SLEW_CTL:
|
||||
GPIO_DR8R(gpioport) |= gpios;
|
||||
GPIO_SLR(gpioport) |= gpios;
|
||||
break;
|
||||
case GPIO_DRIVE_8MA:
|
||||
GPIO_DR8R(gpioport) |= gpios;
|
||||
GPIO_SLR(gpioport) &= ~gpios;
|
||||
break;
|
||||
case GPIO_DRIVE_4MA:
|
||||
GPIO_DR4R(gpioport) |= gpios;
|
||||
break;
|
||||
case GPIO_DRIVE_2MA: /* Fall through */
|
||||
default:
|
||||
GPIO_DR2R(gpioport) |= gpios;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#define PCTL_AF(pin, af) ((af) << ((pin) << 2))
|
||||
#define PCTL_MASK(pin) PCTL_AF((pin), 0xf)
|
||||
/**
|
||||
* \brief Multiplex group of pins to the given alternate function
|
||||
*
|
||||
* Mux the pin or group of pins to the given alternate function. Note that a
|
||||
* number of pins may be set but only with a single AF number. This is useful
|
||||
* when one or more of a peripheral's pins are assigned to the same alternate
|
||||
* function.
|
||||
*
|
||||
* Because AF0 is not used on the LM4F, passing 0 as the alt_func_num parameter
|
||||
* will disable the alternate function of the given pins.
|
||||
*
|
||||
* @param[in] gpioport GPIO block register address base @ref gpio_reg_base
|
||||
* @param[in] alt_func_num Pin alternate function number or 0 to disable the
|
||||
* alternate function multiplexing.
|
||||
* @param[in] gpios @ref gpio_pin_id. Any combination of pins may be specified
|
||||
* by OR'ing then together
|
||||
*/
|
||||
void gpio_set_af(uint32_t gpioport, uint8_t alt_func_num, uint8_t gpios)
|
||||
{
|
||||
uint32_t pctl32;
|
||||
uint8_t pin_mask;
|
||||
int i;
|
||||
|
||||
/* Did we mean to disable the alternate function? */
|
||||
if (alt_func_num == 0) {
|
||||
GPIO_AFSEL(gpioport) &= ~gpios;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Enable the alternate function */
|
||||
GPIO_AFSEL(gpioport) |= gpios;
|
||||
/* Alternate functions are digital */
|
||||
GPIO_DEN(gpioport) |= gpios;
|
||||
|
||||
/* Now take care of the actual multiplexing */
|
||||
pctl32 = GPIO_PCTL(gpioport);
|
||||
for (i = 0; i < 8; i++) {
|
||||
pin_mask = (1 << i);
|
||||
|
||||
if (!(gpios & pin_mask)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
pctl32 &= ~PCTL_MASK(i);
|
||||
pctl32 |= PCTL_AF(i, (alt_func_num & 0xf));
|
||||
}
|
||||
|
||||
GPIO_PCTL(gpioport) = pctl32;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Unlock the commit control of a special function pin
|
||||
*
|
||||
* Unlocks the commit control of the given pin or group of pins. If a pin is a
|
||||
* JTAG/SWD or NMI, the pin may then be reconfigured as a GPIO pin. If the pin
|
||||
* is not locked by default, this has no effect.
|
||||
*
|
||||
* @param[in] gpioport GPIO block register address base @ref gpio_reg_base
|
||||
* @param[in] gpios @ref gpio_pin_id. Any combination of pins may be specified
|
||||
* by OR'ing then together.
|
||||
*/
|
||||
void gpio_unlock_commit(uint32_t gpioport, uint8_t gpios)
|
||||
{
|
||||
/* Unlock the GPIO_CR register */
|
||||
GPIO_LOCK(gpioport) = GPIO_LOCK_UNLOCK_CODE;
|
||||
/* Enable committing changes */
|
||||
GPIO_CR(gpioport) |= gpios;
|
||||
/* Lock the GPIO_CR register */
|
||||
GPIO_LOCK(gpioport) = ~GPIO_LOCK_UNLOCK_CODE;
|
||||
}
|
||||
/**@}*/
|
||||
|
||||
/** @defgroup gpio_control GPIO pin control
|
||||
* @ingroup gpio_file
|
||||
*
|
||||
* \brief <b>Controlling GPIO pins</b>
|
||||
*
|
||||
* Each I/O port has 8 individually configurable bits. When reading and writing
|
||||
* data to the GPIO ports, address bits [9:2] mask the pins to be read or
|
||||
* written. This mechanism makes all GPIO port reads and writes on the LM4F
|
||||
* atomic operations. The GPIO API takes full advantage of this fact to preserve
|
||||
* the atomicity of these operations.
|
||||
*
|
||||
* Setting or clearing a group of bits can be accomplished with @ref gpio_set()
|
||||
* and @ref gpio_clear() respectively. These operation use the masking mechanism
|
||||
* described above to only affect the specified pins.
|
||||
*
|
||||
* Sometimes it is more appropriate to read or set the level of a group of pins
|
||||
* on a port, in one atomic operation. Reading the status can be accomplished
|
||||
* with @ref gpio_read(). The result is equivalent to reading all the pins, then
|
||||
* masking only the desired pins; however, the masking is done in hardware, and
|
||||
* does not require an extra hardware operation.
|
||||
*
|
||||
* Writing a group of pins can be accomplished with @ref gpio_write(). The mask
|
||||
* ('gpios' parameter) is applied in hardware, and the masked pins are not
|
||||
* affected, regardless of the value of the respective bits written to the GPIO
|
||||
* port.
|
||||
*
|
||||
* Two extra functions are provided, @ref gpio_port_read() and
|
||||
* @ref gpio_port_write(). They are functionally identical to
|
||||
* @ref gpio_read (port, GPIO_ALL) and @ref gpio_write (port, GPIO_ALL, val)
|
||||
* respectively. Hence, they are also atomic.
|
||||
*
|
||||
* GPIO pins may be toggled with @ref gpio_toggle(). This function does not
|
||||
* translate to an atomic operation.
|
||||
*
|
||||
* @note
|
||||
* The @ref gpio_toggle() operation is the only GPIO port operation which is not
|
||||
* atomic. It involves a read-modify-write cycle.
|
||||
*
|
||||
* Suppose PA0, PA1, PA2, and PA3 are to be modified without affecting the other
|
||||
* pins on port A. This is common when controlling, for example, a 4-bit bus:
|
||||
* @code{.c}
|
||||
* // Pins 4,5,6, and 7 are unaffected, regardless of the bits in val
|
||||
* gpio_write(GPIOA, GPIO0 | GPIO1 | GPIO2 | GPIO3, val);
|
||||
* // Wait a bit then send the other 4 bits
|
||||
* wait_a_bit();
|
||||
* gpio_write(GPIOA, GPIO0 | GPIO1 | GPIO2 | GPIO3, val >> 4);
|
||||
* @endcode
|
||||
*
|
||||
* Suppose a LED is connected to PD4, and we want to flash the LED for a brief
|
||||
* period of time:
|
||||
* @code
|
||||
* gpio_set(GPIOD, GPIO4);
|
||||
* wait_a_bit();
|
||||
* gpio_set(GPIOD, GPIO4);
|
||||
* @endcode
|
||||
*/
|
||||
/**@{*/
|
||||
/**
|
||||
* \brief Toggle a Group of Pins
|
||||
*
|
||||
* Toggle one or more pins of the given GPIO port.
|
||||
*
|
||||
* @param[in] gpioport GPIO block register address base @ref gpio_reg_base
|
||||
* @param[in] gpios Pin identifiers. @ref gpio_pin_id
|
||||
*/
|
||||
void gpio_toggle(uint32_t gpioport, uint8_t gpios)
|
||||
{
|
||||
/* The mask makes sure we only toggle the GPIOs we want to */
|
||||
GPIO_DATA(gpioport)[gpios] ^= GPIO_ALL;
|
||||
}
|
||||
/**@}*/
|
||||
|
||||
|
||||
/** @defgroup gpio_irq GPIO Interrupt control
|
||||
* @ingroup gpio_file
|
||||
*
|
||||
* \brief <b>Configuring interrupts from GPIO pins</b>
|
||||
*
|
||||
* GPIO pins can trigger interrupts on either edges or levels. The type of
|
||||
* trigger can be configured with @ref gpio_configure_int_trigger(). To have an
|
||||
* event on the given pin generate an interrupt, its interrupt source must be
|
||||
* unmasked. This can be achieved with @ref gpio_enable_interrupts(). Interrupts
|
||||
* which are no longer needed can be disabled through
|
||||
* @ref gpio_disable_interrupts().
|
||||
*
|
||||
* In order for the interrupt to generate an IRQ and a call to the interrupt
|
||||
* service routine, the interrupt for the GPIO port must be routed through the
|
||||
* NVIC with @ref nvic_enable_irq(). For this last step, the nvic.h header is
|
||||
* needed:
|
||||
* @code{.c}
|
||||
* #include <libopencm3/lm4f/nvic.h>
|
||||
* @endcode
|
||||
*
|
||||
* Enabling an interrupt is as simple as configuring the desired trigger,
|
||||
* unmasking the desired interrupt, and routing the desired GPIO port's
|
||||
* interrupt through the NVIC.
|
||||
* @code{.c}
|
||||
* // Trigger interrupt on each rising edge
|
||||
* gpio_configure_trigger(GPIOF, GPIO_TRIG_EDGE_RISE, GPIO0 | GPIO4);
|
||||
* // Unmask the interrupt on those pins
|
||||
* gpio_enable_interrupts(GPIOF, GPIO0 | GPIO4);
|
||||
* // Enable the interrupt in the NVIC as well
|
||||
* nvic_enable_irq(NVIC_GPIOF_IRQ);
|
||||
* @endcode
|
||||
*
|
||||
* After interrupts are properly enabled and routed through the NVIC, when an
|
||||
* event occurs, the appropriate IRQ flag is set by hardware, and execution
|
||||
* jumps to the GPIO ISR. The ISR should query the IRQ flags to determine which
|
||||
* event caused the interrupt. For this, use @ref gpio_is_interrupt_source(),
|
||||
* with the desired GPIO flag. After one or more interrupt sources are
|
||||
* serviced, the IRQ flags must be cleared by the ISR. This can be done with
|
||||
* @ref gpio_clear_interrupt_flag().
|
||||
*
|
||||
* A typical GPIO ISR may look like the following:
|
||||
* @code{.c}
|
||||
* void gpiof_isr(void)
|
||||
* {
|
||||
* uint8_t serviced_irqs = 0;
|
||||
*
|
||||
* // Process individual IRQs
|
||||
* if (gpio_is_interrupt_source(GPIOF, GPIO0)) {
|
||||
* process_gpio0_event();
|
||||
* serviced_irq |= GPIO0;
|
||||
* }
|
||||
* if (gpio_is_interrupt_source(GPIOF, GPIO4)) {
|
||||
* process_gpio4_event();
|
||||
* serviced_irq |= GPIO4;
|
||||
* }
|
||||
*
|
||||
* // Clear the interrupt flag for the processed IRQs
|
||||
* gpio_clear_interrupt_flag(GPIOF, serviced_irqs);
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
/**@{*/
|
||||
/**
|
||||
* \brief Configure the interrupt trigger on the given GPIO pins
|
||||
*
|
||||
* Sets the Pin direction, analog/digital mode, and pull-up configuration of
|
||||
* or a set of GPIO pins on a given GPIO port.
|
||||
*
|
||||
* @param[in] gpioport GPIO block register address base @ref gpio_reg_base
|
||||
* @param[in] trigger Trigger configuration (@ref gpio_trigger) \n
|
||||
* - GPIO_TRIG_LVL_LOW -- Trigger on low level \n
|
||||
* - GPIO_TRIG_LVL_HIGH -- Trigger on high level \n
|
||||
* - GPIO_TRIG_EDGE_FALL -- Trigger on falling edges \n
|
||||
* - GPIO_TRIG_EDGE_RISE -- Trigger on rising edges \n
|
||||
* - GPIO_TRIG_EDGE_BOTH -- Trigger on all edges
|
||||
* @param[in] gpios @ref gpio_pin_id. Any combination of pins may be specified
|
||||
* by OR'ing then together
|
||||
*/
|
||||
void gpio_configure_trigger(uint32_t gpioport, enum gpio_trigger trigger,
|
||||
uint8_t gpios)
|
||||
{
|
||||
switch (trigger) {
|
||||
case GPIO_TRIG_LVL_LOW:
|
||||
GPIO_IS(gpioport) |= gpios;
|
||||
GPIO_IEV(gpioport) &= ~gpios;
|
||||
break;
|
||||
case GPIO_TRIG_LVL_HIGH:
|
||||
GPIO_IS(gpioport) |= gpios;
|
||||
GPIO_IEV(gpioport) |= gpios;
|
||||
break;
|
||||
case GPIO_TRIG_EDGE_FALL:
|
||||
GPIO_IS(gpioport) &= ~gpios;
|
||||
GPIO_IBE(gpioport) &= ~gpios;
|
||||
GPIO_IEV(gpioport) &= ~gpios;
|
||||
break;
|
||||
case GPIO_TRIG_EDGE_RISE:
|
||||
GPIO_IS(gpioport) &= ~gpios;
|
||||
GPIO_IBE(gpioport) &= ~gpios;
|
||||
GPIO_IEV(gpioport) |= gpios;
|
||||
break;
|
||||
case GPIO_TRIG_EDGE_BOTH:
|
||||
GPIO_IS(gpioport) &= ~gpios;
|
||||
GPIO_IBE(gpioport) |= gpios;
|
||||
break;
|
||||
default:
|
||||
/* Don't do anything */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enable interrupts on specified GPIO pins
|
||||
*
|
||||
* Enable interrupts on the specified GPIO pins
|
||||
*
|
||||
* Note that the NVIC must be enabled and properly configured for the interrupt
|
||||
* to be routed to the CPU.
|
||||
*
|
||||
* @param[in] gpioport GPIO block register address base @ref gpio_reg_base
|
||||
* @param[in] gpios @ref gpio_pin_id. Pins whose interrupts to enable. Any
|
||||
* combination of pins may be specified by OR'ing them
|
||||
* together.
|
||||
*/
|
||||
void gpio_enable_interrupts(uint32_t gpioport, uint8_t gpios)
|
||||
{
|
||||
GPIO_IM(gpioport) |= gpios;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Disable interrupts on specified GPIO pins
|
||||
*
|
||||
* Disable interrupts on the specified GPIO pins
|
||||
*
|
||||
* Note that the NVIC must be enabled and properly configured for the interrupt
|
||||
* to be routed to the CPU.
|
||||
*
|
||||
* @param[in] gpioport GPIO block register address base @ref gpio_reg_base
|
||||
* @param[in] gpios @ref gpio_pin_id. Pins whose interrupts to disable. Any
|
||||
* combination of pins may be specified by OR'ing them
|
||||
* together.
|
||||
*/
|
||||
void gpio_disable_interrupts(uint32_t gpioport, uint8_t gpios)
|
||||
{
|
||||
GPIO_IM(gpioport) |= gpios;
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
|
||||
/**@}*/
|
||||
|
||||
499
libopencm3/lib/lm4f/rcc.c
Normal file
499
libopencm3/lib/lm4f/rcc.c
Normal file
@@ -0,0 +1,499 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup rcc_file RCC
|
||||
*
|
||||
* @ingroup LM4Fxx
|
||||
*
|
||||
@author @htmlonly © @endhtmlonly 2012
|
||||
Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
||||
|
||||
* \brief <b>libopencm3 LM4F Clock control API</b>
|
||||
*
|
||||
* The LM4F clock API provides functionality for manipulating the system clock,
|
||||
* oscillator, and PLL. Functions are provided for fine-grained control of clock
|
||||
* control registers, while also providing higher level functionality to easily
|
||||
* configure the main system clock source.
|
||||
*
|
||||
* The following code snippet uses fine-grained mechanisms to configures the
|
||||
* chip to run off an external 16MHz crystal, and use the PLL to derive a clock
|
||||
* frequency of 80MHz.
|
||||
* @code{.c}
|
||||
* // A divisor of 5 gives us a clock of 400/5 = 80MHz
|
||||
* #define PLLDIV_80MHZ 5
|
||||
*
|
||||
* // Enable the main oscillator
|
||||
* rcc_enable_main_osc();
|
||||
*
|
||||
* // Make RCC2 override RCC
|
||||
* rcc_enable_rcc2();
|
||||
*
|
||||
* // Set XTAL value to 16MHz
|
||||
* rcc_configure_xtal(XTAL_16M);
|
||||
* // Set the oscillator source as the main oscillator
|
||||
* rcc_set_osc_source(OSCSRC_MOSC);
|
||||
* // Enable the PLL
|
||||
* rcc_pll_on();
|
||||
*
|
||||
* // Change the clock divisor
|
||||
* rcc_set_pll_divisor(PLLDIV_80MHZ);
|
||||
*
|
||||
* // We cannot use the PLL as a clock source until it locks
|
||||
* rcc_wait_for_pll_ready();
|
||||
* // Disable PLL bypass to derive the system clock from the PLL clock
|
||||
* rcc_pll_bypass_disable();
|
||||
*
|
||||
* // Keep track of frequency
|
||||
* lm4f_rcc_sysclk_freq = 80E6;
|
||||
* @endcode
|
||||
*
|
||||
* The same can be achieved by a simple call to high-level routines:
|
||||
* @code
|
||||
* // A divisor of 5 gives us a clock of 400/5 = 80MHz
|
||||
* #define PLLDIV_80MHZ 5
|
||||
*
|
||||
* rcc_sysclk_config(OSCSRC_MOSC, XTAL_16M, PLLDIV_80MHZ);
|
||||
* @endcode
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <libopencm3/lm4f/rcc.h>
|
||||
|
||||
/**
|
||||
* @defgroup rcc_low_level Low-level clock control API
|
||||
@ingroup rcc_file
|
||||
* @{
|
||||
*/
|
||||
/**
|
||||
* \brief System clock frequency
|
||||
*
|
||||
* This variable is provided to keep track of the system clock frequency. It
|
||||
* should be updated every time the system clock is changed via the fine-grained
|
||||
* mechanisms. The initial value is 16MHz, which corresponds to the clock of the
|
||||
* internal 16MHz oscillator.
|
||||
*
|
||||
* High-level routines update the system clock automatically.
|
||||
* For read access, it is recommended to access this variable via
|
||||
* @code
|
||||
* rcc_get_system_clock_frequency();
|
||||
* @endcode
|
||||
*
|
||||
* If write access is desired (i.e. when changing the system clock via the
|
||||
* fine-grained mechanisms), then include the following line in your code:
|
||||
* @code
|
||||
* extern uint32_t lm4f_rcc_sysclk_freq;
|
||||
* @endcode
|
||||
*/
|
||||
uint32_t lm4f_rcc_sysclk_freq = 16000000;
|
||||
|
||||
|
||||
/**
|
||||
* \brief Configure the crystal type connected to the device.
|
||||
*
|
||||
* Configure the crystal type connected between the OSCO and OSCI pins by
|
||||
* writing the appropriate value to the XTAL field in SYSCTL_RCC. The PLL
|
||||
* parameters are automatically adjusted in hardware to provide a PLL clock of
|
||||
* 400MHz.
|
||||
*
|
||||
* @param[in] xtal predefined crystal type @see xtal_t
|
||||
*/
|
||||
void rcc_configure_xtal(enum xtal_t xtal)
|
||||
{
|
||||
uint32_t reg32;
|
||||
|
||||
reg32 = SYSCTL_RCC;
|
||||
reg32 &= ~SYSCTL_RCC_XTAL_MASK;
|
||||
reg32 |= (xtal & SYSCTL_RCC_XTAL_MASK);
|
||||
SYSCTL_RCC = reg32;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Disable the main oscillator
|
||||
*
|
||||
* Sets the IOSCDIS bit in SYSCTL_RCC, disabling the main oscillator.
|
||||
*/
|
||||
void rcc_disable_main_osc(void)
|
||||
{
|
||||
SYSCTL_RCC |= SYSCTL_RCC_MOSCDIS;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Disable the internal oscillator
|
||||
*
|
||||
* Sets the IOSCDIS bit in SYSCTL_RCC, disabling the internal oscillator.
|
||||
*/
|
||||
void rcc_disable_interal_osc(void)
|
||||
{
|
||||
SYSCTL_RCC |= SYSCTL_RCC_IOSCDIS;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enable the main oscillator
|
||||
*
|
||||
* Clears the MOSCDIS bit in SYSCTL_RCC, enabling the main oscillator.
|
||||
*/
|
||||
void rcc_enable_main_osc(void)
|
||||
{
|
||||
SYSCTL_RCC &= ~SYSCTL_RCC_MOSCDIS;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enable the internal oscillator
|
||||
*
|
||||
* Clears the IOSCDIS bit in SYSCTL_RCC, enabling the internal oscillator.
|
||||
*/
|
||||
void rcc_enable_interal_osc(void)
|
||||
{
|
||||
SYSCTL_RCC &= ~SYSCTL_RCC_IOSCDIS;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enable the use of SYSCTL_RCC2 register for clock control
|
||||
*
|
||||
* Enables the USERCC2 bit in SYSCTTL_RCC2. Settings in SYSCTL_RCC2 will
|
||||
* override settings in SYSCTL_RCC.
|
||||
* This function must be called before other calls to manipulate the clock, as
|
||||
* libopencm3 uses the SYSCTL_RCC2 register.
|
||||
*/
|
||||
void rcc_enable_rcc2(void)
|
||||
{
|
||||
SYSCTL_RCC2 |= SYSCTL_RCC2_USERCC2;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Power down the main PLL
|
||||
*
|
||||
* Sets the SYSCTL_RCC2_PWRDN2 in SYSCTL_RCC2 to power down the PLL.
|
||||
*
|
||||
* USERCC2 must have been set by a call to rcc_enable_rcc2() before calling this
|
||||
* function.
|
||||
*/
|
||||
void rcc_pll_off(void)
|
||||
{
|
||||
SYSCTL_RCC2 |= SYSCTL_RCC2_PWRDN2;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Power up the main PLL
|
||||
*
|
||||
* Clears the PWRDN2 in SYSCTL_RCC2 to power on the PLL.
|
||||
*
|
||||
* USERCC2 must have been set by a call to rcc_enable_rcc2() before calling this
|
||||
* function.
|
||||
*/
|
||||
void rcc_pll_on(void)
|
||||
{
|
||||
SYSCTL_RCC2 &= ~SYSCTL_RCC2_PWRDN2;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set the oscillator source to be used by the system clock
|
||||
*
|
||||
* Set the clock source for the system clock.
|
||||
*
|
||||
* USERCC2 must have been set by a call to rcc_enable_rcc2() before calling this
|
||||
* function.
|
||||
*/
|
||||
void rcc_set_osc_source(enum osc_src src)
|
||||
{
|
||||
uint32_t reg32;
|
||||
|
||||
reg32 = SYSCTL_RCC2;
|
||||
reg32 &= ~SYSCTL_RCC2_OSCSRC2_MASK;
|
||||
reg32 |= (src & SYSCTL_RCC2_OSCSRC2_MASK);
|
||||
SYSCTL_RCC2 = reg32;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Disable the PLL bypass and use the PLL clock
|
||||
*
|
||||
* Clear BYPASS2 in SYSCTL_RCC2. The system clock is derived from the PLL
|
||||
* clock divided by the divisor specified in SYSDIV2.
|
||||
*
|
||||
* USERCC2 must have been set by a call to rcc_enable_rcc2() before calling this
|
||||
* function.
|
||||
*/
|
||||
void rcc_pll_bypass_disable(void)
|
||||
{
|
||||
SYSCTL_RCC2 &= ~SYSCTL_RCC2_BYPASS2;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enable the PLL bypass and use the oscillator clock
|
||||
*
|
||||
* Set BYPASS2 in SYSCTL_RCC2. The system clock is derived from the oscillator
|
||||
* clock divided by the divisor specified in SYSDIV2.
|
||||
*
|
||||
* USERCC2 must have been set by a call to rcc_enable_rcc2() before calling this
|
||||
* function.
|
||||
*/
|
||||
void rcc_pll_bypass_enable(void)
|
||||
{
|
||||
SYSCTL_RCC2 |= SYSCTL_RCC2_BYPASS2;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set the PLL clock divisor (from 400MHz)
|
||||
*
|
||||
* Set the binary divisor used to predivide the system clock down for use as the
|
||||
* timing reference for the PWM module. The divisor is expected to be a divisor
|
||||
* from 400MHz, not 200MHz. The DIV400 is also set.
|
||||
*
|
||||
* Specifies the divisor that used to generate the system clock from either the
|
||||
* PLL output or the oscillator source (depending on the BYPASS2 bit in
|
||||
* SYSCTL_RCC2). SYSDIV2 is used for the divisor when both the USESYSDIV bit in
|
||||
* SYSCTL_RCC is set.
|
||||
*
|
||||
* USERCC2 must have been set by a call to rcc_enable_rcc2() before calling this
|
||||
* function.
|
||||
*
|
||||
* @param[in] div clock divisor to apply to the 400MHz PLL clock. It is the
|
||||
* caller's responsibility to ensure that the divisor will not create
|
||||
* a system clock that is out of spec.
|
||||
*/
|
||||
void rcc_set_pll_divisor(uint8_t div400)
|
||||
{
|
||||
uint32_t reg32;
|
||||
|
||||
SYSCTL_RCC |= SYSCTL_RCC_USESYSDIV;
|
||||
|
||||
reg32 = SYSCTL_RCC2;
|
||||
reg32 &= ~SYSCTL_RCC2_SYSDIV400_MASK;
|
||||
reg32 |= ((div400 - 1) << 22) & SYSCTL_RCC2_SYSDIV400_MASK;
|
||||
/* We are expecting a divider from 400MHz */
|
||||
reg32 |= SYSCTL_RCC2_DIV400;
|
||||
SYSCTL_RCC2 = reg32;
|
||||
}
|
||||
/**
|
||||
* \brief Set the PWM unit clock divisor
|
||||
*
|
||||
* Set the binary divisor used to predivide the system clock down for use as the
|
||||
* timing reference for the PWM module.
|
||||
*
|
||||
* @param[in] div clock divisor to use @see pwm_clkdiv_t
|
||||
*/
|
||||
void rcc_set_pwm_divisor(enum pwm_clkdiv div)
|
||||
{
|
||||
uint32_t reg32;
|
||||
|
||||
reg32 = SYSCTL_RCC;
|
||||
reg32 &= ~SYSCTL_RCC_PWMDIV_MASK;
|
||||
reg32 |= (div & SYSCTL_RCC_PWMDIV_MASK);
|
||||
SYSCTL_RCC = reg32;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Power down the USB PLL
|
||||
*
|
||||
* Sets the USBPWRDN in SYSCTL_RCC2 to power down the USB PLL.
|
||||
*
|
||||
* USERCC2 must have been set by a call to rcc_enable_rcc2() before calling this
|
||||
* function.
|
||||
*/
|
||||
void rcc_usb_pll_off(void)
|
||||
{
|
||||
SYSCTL_RCC2 |= SYSCTL_RCC2_USBPWRDN;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Power up the USB PLL
|
||||
*
|
||||
* Clears the USBPWRDN in SYSCTL_RCC2 to power on the USB PLL.
|
||||
*
|
||||
* USERCC2 must have been set by a call to rcc_enable_rcc2() before calling this
|
||||
* function.
|
||||
*/
|
||||
void rcc_usb_pll_on(void)
|
||||
{
|
||||
SYSCTL_RCC2 &= ~SYSCTL_RCC2_USBPWRDN;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Wait for main PLL to lock
|
||||
*
|
||||
* Waits until the LOCK bit in SYSCTL_PLLSTAT is set. This guarantees that the
|
||||
* PLL is locked, and ready to use.
|
||||
*/
|
||||
void rcc_wait_for_pll_ready(void)
|
||||
{
|
||||
while (!(SYSCTL_PLLSTAT & SYSCTL_PLLSTAT_LOCK));
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup rcc_high_level High-level clock control API
|
||||
@ingroup rcc_file
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* \brief Change the PLL divisor
|
||||
*
|
||||
* Changes the divisor applied to the 400MHz PLL clock. The PLL must have
|
||||
* previously been configured by selecting an appropriate XTAL value, and
|
||||
* turning on the PLL. This function does not reconfigure the XTAL value or
|
||||
* oscillator source. It only changes the PLL divisor.
|
||||
*
|
||||
* The PLL is bypassed before modifying the divisor, and the function blocks
|
||||
* until the PLL is locked, then the bypass is disabled, before returning.
|
||||
*
|
||||
* @param [in] pll_div400 The clock divisor to apply to the 400MHz PLL clock.
|
||||
*/
|
||||
void rcc_change_pll_divisor(uint8_t pll_div400)
|
||||
{
|
||||
/* Bypass the PLL while its settings are modified */
|
||||
rcc_pll_bypass_enable();
|
||||
/* Change the clock divisor */
|
||||
rcc_set_pll_divisor(pll_div400);
|
||||
/* We cannot use the PLL as a clock source until it locks */
|
||||
rcc_wait_for_pll_ready();
|
||||
/* Disable PLL bypass to derive the system clock from the PLL clock */
|
||||
rcc_pll_bypass_disable();
|
||||
/* Update the system clock frequency for housekeeping */
|
||||
lm4f_rcc_sysclk_freq = (uint32_t)400E6 / pll_div400;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Get the system clock frequency
|
||||
*
|
||||
* @return System clock frequency in Hz
|
||||
*/
|
||||
uint32_t rcc_get_system_clock_frequency(void)
|
||||
{
|
||||
return lm4f_rcc_sysclk_freq;
|
||||
}
|
||||
|
||||
/* Get the clock frequency corresponding to a given XTAL value */
|
||||
static uint32_t xtal_to_freq(enum xtal_t xtal)
|
||||
{
|
||||
const uint32_t freqs[] = {
|
||||
4000000, /* XTAL_4M */
|
||||
4096000, /* XTAL_4M_096 */
|
||||
4915200, /* XTAL_4M_9152 */
|
||||
5000000, /* ,XTAL_5M */
|
||||
5120000, /* XTAL_5M_12 */
|
||||
6000000, /* XTAL_6M */
|
||||
6144000, /* XTAL_6M_144 */
|
||||
7372800, /* XTAL_7M_3728 */
|
||||
8000000, /* XTAL_8M */
|
||||
8192000, /* XTAL_8M_192 */
|
||||
10000000, /* XTAL_10M */
|
||||
12000000, /* XTAL_12M */
|
||||
12288000, /* XTAL_12M_288 */
|
||||
13560000, /* XTAL_13M_56 */
|
||||
14318180, /* XTAL_14M_31818 */
|
||||
16000000, /* XTAL_16M */
|
||||
16384000, /* XTAL_16M_384 */
|
||||
18000000, /* XTAL_18M */
|
||||
20000000, /* XTAL_20M */
|
||||
24000000, /* XTAL_24M */
|
||||
25000000, /* XTAL_25M */
|
||||
};
|
||||
|
||||
return freqs[xtal - XTAL_4M];
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Configure the system clock source
|
||||
*
|
||||
* Sets up the system clock, including configuring the oscillator source, and
|
||||
* PLL to achieve the desired system clock frequency. Where applicable, The LM4F
|
||||
* clock API uses the new RCC2 register to configure clock parameters.
|
||||
*
|
||||
* Enables the main oscillator if the clock source is OSCSRC_MOSC. If the main
|
||||
* oscillator was previously enabled, it will not be disabled. If desired, it
|
||||
* can be separately disabled by a call to rcc_disable_main_osc().
|
||||
*
|
||||
* Configures the system clock to run from the 400MHz PLL with a divisor of
|
||||
* pll_div400 applied. If pll_div400 is 0, then the PLL is disabled, and the
|
||||
* system clock is configured to run off a "raw" clock. If the PLL was
|
||||
* previously powered on, it will not be disabled. If desired, it can de powered
|
||||
* off by a call to rcc_pll_off().
|
||||
*
|
||||
* @param [in] osc_src Oscillator from where to derive the system clock.
|
||||
* @param [in] xtal Type of crystal connected to the OSCO/OSCI pins
|
||||
* @param [in] pll_div400 The clock divisor to apply to the 400MHz PLL clock.
|
||||
* If 0, then the PLL is disabled, and the system runs
|
||||
* off a "raw" clock.
|
||||
*
|
||||
* @return System clock frequency in Hz
|
||||
*/
|
||||
void rcc_sysclk_config(enum osc_src src, enum xtal_t xtal, uint8_t pll_div400)
|
||||
{
|
||||
/*
|
||||
* We could be using the PLL at this point, or we could be running of a
|
||||
* raw clock. Either way, it is safer to bypass the PLL now.
|
||||
*/
|
||||
rcc_pll_bypass_enable();
|
||||
|
||||
/* Enable the main oscillator, if needed */
|
||||
if (src == OSCSRC_MOSC) {
|
||||
rcc_enable_main_osc();
|
||||
}
|
||||
|
||||
/* Make RCC2 override RCC */
|
||||
rcc_enable_rcc2();
|
||||
|
||||
/* Set XTAL value to 16MHz */
|
||||
rcc_configure_xtal(xtal);
|
||||
/* Set the oscillator source */
|
||||
rcc_set_osc_source(src);
|
||||
if (pll_div400) {
|
||||
/* Enable the PLL */
|
||||
rcc_pll_on();
|
||||
/* Configure the PLL to the divisor we want */
|
||||
rcc_change_pll_divisor(pll_div400);
|
||||
} else {
|
||||
/* We are running off a raw clock */
|
||||
switch (src) {
|
||||
case OSCSRC_PIOSC:
|
||||
lm4f_rcc_sysclk_freq = 16000000;
|
||||
break;
|
||||
case OSCSRC_PIOSC_D4:
|
||||
lm4f_rcc_sysclk_freq = 4000000;
|
||||
break;
|
||||
case OSCSRC_MOSC:
|
||||
lm4f_rcc_sysclk_freq = xtal_to_freq(xtal);
|
||||
break;
|
||||
case OSCSRC_32K_EXT:
|
||||
lm4f_rcc_sysclk_freq = 32768;
|
||||
break;
|
||||
case OSCSRC_30K_INT: /* Fall through. */
|
||||
default:
|
||||
/*
|
||||
* We either are running off the internal 30KHz
|
||||
* oscillator, which is +- 50% imprecise, or we got a
|
||||
* bad osc_src parameter.
|
||||
*/
|
||||
lm4f_rcc_sysclk_freq = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @}
|
||||
* @}
|
||||
*/
|
||||
40
libopencm3/lib/lm4f/systemcontrol.c
Normal file
40
libopencm3/lib/lm4f/systemcontrol.c
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
||||
*
|
||||
* 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/lm4f/systemcontrol.h>
|
||||
|
||||
/**
|
||||
* \brief Enable the clock source for the peripheral
|
||||
*
|
||||
* @param[in] periph peripheral and clock type to enable @see lm4f_clken
|
||||
*/
|
||||
void periph_clock_enable(enum lm4f_clken periph)
|
||||
{
|
||||
MMIO32(SYSCTL_BASE + (periph >> 5)) |= 1 << (periph & 0x1f);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Disable the clock source for the peripheral
|
||||
*
|
||||
* @param[in] periph peripheral and clock type to enable @see lm4f_clken
|
||||
*/
|
||||
void periph_clock_disable(enum lm4f_clken periph)
|
||||
{
|
||||
MMIO32(SYSCTL_BASE + (periph >> 5)) &= ~(1 << (periph & 0x1f));
|
||||
}
|
||||
627
libopencm3/lib/lm4f/uart.c
Normal file
627
libopencm3/lib/lm4f/uart.c
Normal file
@@ -0,0 +1,627 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @defgroup uart_file UART
|
||||
*
|
||||
* @ingroup LM4Fxx
|
||||
*
|
||||
* @author @htmlonly © @endhtmlonly 2013 Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
||||
*
|
||||
* \brief <b>libopencm3 LM4F Universal Asynchronous Receiver Transmitter</b>
|
||||
*
|
||||
* The LM4F UART API provides functionality for accessing the UART hardware of
|
||||
* the LM4F.
|
||||
*
|
||||
* Please see the individual UART modules for more details. To use the UART, the
|
||||
* uart.h header needs to be included:
|
||||
* @code{.c}
|
||||
* #include <libopencm3/lm4f/uart.h>
|
||||
* @endcode
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <libopencm3/lm4f/uart.h>
|
||||
#include <libopencm3/lm4f/systemcontrol.h>
|
||||
#include <libopencm3/lm4f/rcc.h>
|
||||
|
||||
/** @defgroup uart_config UART configuration
|
||||
* @ingroup uart_file
|
||||
*
|
||||
* \brief <b>Enabling and configuring the UART</b>
|
||||
*
|
||||
* Enabling the UART is a two step process. The GPIO on which the UART resides
|
||||
* must be enabled, and the UART pins must be configured as alternate function,
|
||||
* digital pins. Pins must also be muxed to the appropriate alternate function.
|
||||
* This is done with the GPIO API.
|
||||
*
|
||||
* The second step involves enabling and the UART itself. The UART should be
|
||||
* disabled while it is being configured.
|
||||
* -# The UART clock must be enabled with @ref periph_clock_enable().
|
||||
* -# The UART must be disabled with @ref uart_disable().
|
||||
* -# The UART clock source should be chosen before setting the baudrate.
|
||||
* -# Baudrate, data bits, stop bit length, and parity can be configured.
|
||||
* -# If needed, enable CTS or RTS lines via the @ref uart_set_flow_control().
|
||||
* -# The UART can now be enabled with @ref uart_enable().
|
||||
*
|
||||
* For example, to enable UART1 at 115200 8n1 with hardware flow control:
|
||||
* @code{.c}
|
||||
* // Enable the UART clock
|
||||
* periph_clock_enable(RCC_UART1);
|
||||
* // We need a brief delay before we can access UART config registers
|
||||
* __asm__("nop"); __asm__("nop"); __asm__("nop");
|
||||
* // Disable the UART while we mess with its settings
|
||||
* uart_disable(UART1);
|
||||
* // Configure the UART clock source as precision internal oscillator
|
||||
* uart_clock_from_piosc();
|
||||
* // Set communication parameters
|
||||
* uart_set_baudrate(UART1, 115200);
|
||||
* uart_set_databits(UART1, 8);
|
||||
* uart_set_parity(UART1, UART_PARITY_NONE);
|
||||
* uart_set_stopbits(UART1, 1);
|
||||
* // Enable RTC and CTS lines
|
||||
* uart_set_flow_control(UART1, UART_FLOWCTL_HARD_RTS_CTS);
|
||||
* // Now that we're done messing with the settings, enable the UART
|
||||
* uart_enable(UART1);
|
||||
* @endcode
|
||||
*/
|
||||
/**@{*/
|
||||
/**
|
||||
* \brief Enable the UART
|
||||
*
|
||||
* Enable the UART. The Rx and Tx lines are also enabled.
|
||||
*
|
||||
* @param[in] uart UART block register address base @ref uart_reg_base
|
||||
*/
|
||||
void uart_enable(uint32_t uart)
|
||||
{
|
||||
UART_CTL(uart) |= (UART_CTL_UARTEN | UART_CTL_RXE | UART_CTL_TXE);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Disable the UART
|
||||
*
|
||||
* @param[in] uart UART block register address base @ref uart_reg_base
|
||||
*/
|
||||
void uart_disable(uint32_t uart)
|
||||
{
|
||||
UART_CTL(uart) &= ~UART_CTL_UARTEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set UART baudrate
|
||||
*
|
||||
* @param[in] uart UART block register address base @ref uart_reg_base
|
||||
* @param[in] baud Baud rate in bits per second (bps).*
|
||||
*/
|
||||
void uart_set_baudrate(uint32_t uart, uint32_t baud)
|
||||
{
|
||||
uint32_t clock;
|
||||
|
||||
/* Are we running off the internal clock or system clock? */
|
||||
if (UART_CC(uart) == UART_CC_CS_PIOSC) {
|
||||
clock = 16000000;
|
||||
} else {
|
||||
clock = rcc_get_system_clock_frequency();
|
||||
}
|
||||
|
||||
/* Find the baudrate divisor */
|
||||
uint32_t div = (((clock * 8) / baud) + 1) / 2;
|
||||
|
||||
/* Set the baudrate divisors */
|
||||
UART_IBRD(uart) = div / 64;
|
||||
UART_FBRD(uart) = div % 64;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set UART databits
|
||||
*
|
||||
* @param[in] uart UART block register address base @ref uart_reg_base
|
||||
* @param[in] databits number of data bits per transmission.
|
||||
*/
|
||||
void uart_set_databits(uint32_t uart, uint8_t databits)
|
||||
{
|
||||
uint32_t reg32, bitint32_t;
|
||||
|
||||
/* This has the same effect as using UART_LCRH_WLEN_5/6/7/8 directly */
|
||||
bitint32_t = (databits - 5) << 5;
|
||||
|
||||
/* TODO: What about 9 data bits? */
|
||||
|
||||
reg32 = UART_LCRH(uart);
|
||||
reg32 &= ~UART_LCRH_WLEN_MASK;
|
||||
reg32 |= bitint32_t;
|
||||
UART_LCRH(uart) = reg32;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set UART stopbits
|
||||
*
|
||||
* @param[in] uart UART block register address base @ref uart_reg_base
|
||||
* @param[in] bits the requested number of stopbits, either 1 or 2.
|
||||
*/
|
||||
void uart_set_stopbits(uint32_t uart, uint8_t stopbits)
|
||||
{
|
||||
if (stopbits == 2) {
|
||||
UART_LCRH(uart) |= UART_LCRH_STP2;
|
||||
} else {
|
||||
UART_LCRH(uart) &= ~UART_LCRH_STP2;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set UART parity
|
||||
*
|
||||
* @param[in] uart UART block register address base @ref uart_reg_base
|
||||
* @param[in] bits the requested parity scheme.
|
||||
*/
|
||||
void uart_set_parity(uint32_t uart, enum uart_parity parity)
|
||||
{
|
||||
uint32_t reg32;
|
||||
|
||||
reg32 = UART_LCRH(uart);
|
||||
reg32 |= UART_LCRH_PEN;
|
||||
reg32 &= ~(UART_LCRH_SPS | UART_LCRH_EPS);
|
||||
|
||||
switch (parity) {
|
||||
case UART_PARITY_NONE:
|
||||
/* Once we disable parity the other bits are meaningless */
|
||||
UART_LCRH(uart) &= ~UART_LCRH_PEN;
|
||||
return;
|
||||
case UART_PARITY_ODD:
|
||||
break;
|
||||
case UART_PARITY_EVEN:
|
||||
reg32 |= UART_LCRH_EPS;
|
||||
break;
|
||||
case UART_PARITY_STICK_0:
|
||||
reg32 |= (UART_LCRH_SPS | UART_LCRH_EPS);
|
||||
break;
|
||||
case UART_PARITY_STICK_1:
|
||||
reg32 |= UART_LCRH_SPS;
|
||||
break;
|
||||
}
|
||||
|
||||
UART_LCRH(uart) = reg32;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set the flow control scheme
|
||||
*
|
||||
* Set the flow control scheme by enabling or disabling RTS and CTS lines. This
|
||||
* will only have effect if the given UART supports the RTS and CTS lines.
|
||||
*
|
||||
* @param[in] uart UART block register address base @ref uart_reg_base
|
||||
* @param[in] flow The flow control scheme to use (none, RTS, CTS or both) \n
|
||||
* UART_FLOWCTL_RTS -- enable the RTS line \n
|
||||
* UART_FLOWCTL_CTS -- enable the CTS line \n
|
||||
* UART_FLOWCTL_RTS_CTS -- enable both RTS and CTS lines
|
||||
*/
|
||||
void uart_set_flow_control(uint32_t uart, enum uart_flowctl flow)
|
||||
{
|
||||
uint32_t reg32 = UART_CTL(uart);
|
||||
|
||||
reg32 &= ~(UART_CTL_RTSEN | UART_CTL_CTSEN);
|
||||
|
||||
if (flow == UART_FLOWCTL_RTS) {
|
||||
reg32 |= UART_CTL_RTSEN;
|
||||
} else if (flow == UART_FLOWCTL_CTS) {
|
||||
reg32 |= UART_CTL_CTSEN;
|
||||
} else if (flow == UART_FLOWCTL_RTS_CTS) {
|
||||
reg32 |= (UART_CTL_RTSEN | UART_CTL_CTSEN);
|
||||
}
|
||||
|
||||
UART_CTL(uart) = reg32;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Clock the UART module from the internal oscillator
|
||||
*
|
||||
* @param[in] uart UART block register address base @ref uart_reg_base
|
||||
*/
|
||||
void uart_clock_from_piosc(uint32_t uart)
|
||||
{
|
||||
UART_CC(uart) = UART_CC_CS_PIOSC;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Clock the UART module from the system clock
|
||||
*
|
||||
* @param[in] uart UART block register address base @ref uart_reg_base
|
||||
*/
|
||||
void uart_clock_from_sysclk(uint32_t uart)
|
||||
{
|
||||
UART_CC(uart) = UART_CC_CS_SYSCLK;
|
||||
}
|
||||
/**@}*/
|
||||
|
||||
/** @defgroup uart_send_recv UART transmission and reception
|
||||
* @ingroup uart_file
|
||||
*
|
||||
* \brief <b>Sending and receiving data through the UART</b>
|
||||
*
|
||||
* Primitives for sending and receiving data are provided, @ref uart_send() and
|
||||
* @ref uart_recv(). These primitives do not check if data can be transmitted
|
||||
* or wait for data. If waiting until data is available or can be transmitted is
|
||||
* desired, blocking primitives are also available, @ref uart_send_blocking()
|
||||
* and @ref uart_recv_blocking().
|
||||
*
|
||||
* These primitives only handle one byte at at time, and thus may be unsuited
|
||||
* for some applications. You may also consider using @ref uart_dma.
|
||||
*/
|
||||
/**@{*/
|
||||
/**
|
||||
* \brief UART Send a Data Word.
|
||||
*
|
||||
* @param[in] uart UART block register address base @ref uart_reg_base
|
||||
* @param[in] data data to send.
|
||||
*/
|
||||
void uart_send(uint32_t uart, uint16_t data)
|
||||
{
|
||||
data &= 0xFF;
|
||||
UART_DR(uart) = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief UART Read a Received Data Word.
|
||||
*
|
||||
* @param[in] uart UART block register address base @ref uart_reg_base
|
||||
* @return data from the Rx FIFO.
|
||||
*/
|
||||
uint16_t uart_recv(uint32_t uart)
|
||||
{
|
||||
return UART_DR(uart) & UART_DR_DATA_MASK;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief UART Wait for Transmit Data Buffer Not Full
|
||||
*
|
||||
* Blocks until the transmit data FIFO is not empty and can accept the next data
|
||||
* word.
|
||||
* \n
|
||||
* Even if the FIFO is not empty, this function will return as long as there is
|
||||
* room for at least one more word.
|
||||
*
|
||||
* @param[in] uart UART block register address base @ref uart_reg_base
|
||||
*/
|
||||
void uart_wait_send_ready(uint32_t uart)
|
||||
{
|
||||
/* Wait until the Tx FIFO is no longer full */
|
||||
while (UART_FR(uart) & UART_FR_TXFF);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief UART Wait for Received Data Available
|
||||
*
|
||||
* Blocks until the receive data FIFO holds a at least valid received data word.
|
||||
*
|
||||
* @param[in] uart UART block register address base @ref uart_reg_base
|
||||
*/
|
||||
void uart_wait_recv_ready(uint32_t uart)
|
||||
{
|
||||
/* Wait until the Tx FIFO is no longer empty */
|
||||
while (UART_FR(uart) & UART_FR_RXFE);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief UART Send Data Word with Blocking
|
||||
*
|
||||
* Blocks until the transmit data FIFO can accept the next data word for
|
||||
* transmission.
|
||||
*
|
||||
* @param[in] uart UART block register address base @ref uart_reg_base
|
||||
*/
|
||||
void uart_send_blocking(uint32_t uart, uint16_t data)
|
||||
{
|
||||
uart_wait_send_ready(uart);
|
||||
uart_send(uart, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief UART Read a Received Data Word with Blocking.
|
||||
*
|
||||
* Wait until a data word has been received then return the word.
|
||||
*
|
||||
* @param[in] uart UART block register address base @ref uart_reg_base
|
||||
* @return data from the Rx FIFO.
|
||||
*/
|
||||
uint16_t uart_recv_blocking(uint32_t uart)
|
||||
{
|
||||
uart_wait_recv_ready(uart);
|
||||
return uart_recv(uart);
|
||||
}
|
||||
/**@}*/
|
||||
|
||||
/** @defgroup uart_irq UART Interrupt control
|
||||
* @ingroup uart_file
|
||||
*
|
||||
* \brief <b>Configuring interrupts from the UART</b>
|
||||
*
|
||||
* To have an event generate an interrupt, its interrupt source must be
|
||||
* unmasked. This can be achieved with @ref uart_enable_interrupts(). Interrupts
|
||||
* which are no longer needed can be disabled through
|
||||
* @ref uart_disable_interrupts().
|
||||
*
|
||||
* In order for the interrupt to generate an IRQ and a call to the interrupt
|
||||
* service routine, the interrupt for the target UART must be routed through the
|
||||
* NVIC with @ref nvic_enable_irq(). For this last step, the nvic.h header is
|
||||
* needed:
|
||||
* @code{.c}
|
||||
* #include <libopencm3/lm4f/nvic.h>
|
||||
* @endcode
|
||||
*
|
||||
* Enabling an interrupt is as simple as unmasking the desired interrupt, and
|
||||
* routing the desired UART's interrupt through the NVIC.
|
||||
* @code{.c}
|
||||
* // Unmask receive interrupt
|
||||
* uart_enable_rx_interrupt(UART0);
|
||||
* // Make sure the interrupt is routed through the NVIC
|
||||
* nvic_enable_irq(NVIC_UART0_IRQ);
|
||||
* @endcode
|
||||
*
|
||||
* If a more than one interrupt is to be enabled at one time, the interrupts
|
||||
* can be enabled by a single call to @ref uart_enable_interrupts().
|
||||
* For example:
|
||||
* @code{.c}
|
||||
* // Unmask receive, CTS, and RI, interrupts
|
||||
* uart_enable_interrupts(UART0, UART_INT_RX | UART_INT_RI | UART_INT_CTS);
|
||||
* @endcode
|
||||
*
|
||||
* After interrupts are properly enabled and routed through the NVIC, when an
|
||||
* event occurs, the appropriate IRQ flag is set by hardware, and execution
|
||||
* jumps to the UART ISR. The ISR should query the IRQ flags to determine which
|
||||
* event caused the interrupt. For this, use @ref uart_is_interrupt_source(),
|
||||
* with the desired UART_INT flag. After one or more interrupt sources are
|
||||
* serviced, the IRQ flags must be cleared by the ISR. This can be done with
|
||||
* @ref uart_clear_interrupt_flag().
|
||||
*
|
||||
* A typical UART ISR may look like the following:
|
||||
* @code{.c}
|
||||
* void uart0_isr(void)
|
||||
* {
|
||||
* uint32_t serviced_irqs = 0;
|
||||
*
|
||||
* // Process individual IRQs
|
||||
* if (uart_is_interrupt_source(UART0, UART_INT_RX)) {
|
||||
* process_rx_event();
|
||||
* serviced_irq |= UART_INT_RX;
|
||||
* }
|
||||
* if (uart_is_interrupt_source(UART0, UART_INT_CTS)) {
|
||||
* process_cts_event();
|
||||
* serviced_irq |= UART_INT_CTS;
|
||||
* }
|
||||
*
|
||||
* // Clear the interrupt flag for the processed IRQs
|
||||
* uart_clear_interrupt_flag(UART0, serviced_irqs);
|
||||
* }
|
||||
* @endcode
|
||||
*/
|
||||
/**@{*/
|
||||
/**
|
||||
* \brief Enable Specific UART Interrupts
|
||||
*
|
||||
* Enable any combination of interrupts. Interrupts may be OR'ed together to
|
||||
* enable them with one call. For example, to enable both the RX and CTS
|
||||
* interrupts, pass (UART_INT_RX | UART_INT_CTS)
|
||||
*
|
||||
* Note that the NVIC must be enabled and properly configured for the interrupt
|
||||
* to be routed to the CPU.
|
||||
*
|
||||
* @param[in] uart UART block register address base @ref uart_reg_base
|
||||
* @param[in] ints Interrupts which to enable. Any combination of interrupts may
|
||||
* be specified by OR'ing then together
|
||||
*/
|
||||
void uart_enable_interrupts(uint32_t uart, enum uart_interrupt_flag ints)
|
||||
{
|
||||
UART_IM(uart) |= ints;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enable Specific UART Interrupts
|
||||
*
|
||||
* Disabe any combination of interrupts. Interrupts may be OR'ed together to
|
||||
* disable them with one call. For example, to disable both the RX and CTS
|
||||
* interrupts, pass (UART_INT_RX | UART_INT_CTS)
|
||||
*
|
||||
* @param[in] uart UART block register address base @ref uart_reg_base
|
||||
* @param[in] ints Interrupts which to disable. Any combination of interrupts
|
||||
* may be specified by OR'ing then together
|
||||
*/
|
||||
void uart_disable_interrupts(uint32_t uart, enum uart_interrupt_flag ints)
|
||||
{
|
||||
UART_IM(uart) &= ~ints;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enable the UART Receive Interrupt.
|
||||
*
|
||||
* Note that the NVIC must be enabled and properly configured for the interrupt
|
||||
* to be routed to the CPU.
|
||||
*
|
||||
* @param[in] uart UART block register address base @ref uart_reg_base
|
||||
*/
|
||||
void uart_enable_rx_interrupt(uint32_t uart)
|
||||
{
|
||||
uart_enable_interrupts(uart, UART_INT_RX);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Disable the UART Receive Interrupt.
|
||||
*
|
||||
* @param[in] uart UART block register address base @ref uart_reg_base
|
||||
*/
|
||||
void uart_disable_rx_interrupt(uint32_t uart)
|
||||
{
|
||||
uart_disable_interrupts(uart, UART_INT_RX);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enable the UART Transmit Interrupt.
|
||||
*
|
||||
* Note that the NVIC must be enabled and properly configured for the interrupt
|
||||
* to be routed to the CPU.
|
||||
*
|
||||
* @param[in] uart UART block register address base @ref uart_reg_base
|
||||
*/
|
||||
void uart_enable_tx_interrupt(uint32_t uart)
|
||||
{
|
||||
uart_enable_interrupts(uart, UART_INT_TX);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Disable the UART Transmit Interrupt.
|
||||
*
|
||||
* @param[in] uart UART block register address base @ref uart_reg_base
|
||||
*/
|
||||
void uart_disable_tx_interrupt(uint32_t uart)
|
||||
{
|
||||
uart_disable_interrupts(uart, UART_INT_TX);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Mark interrupt as serviced
|
||||
*
|
||||
* After an interrupt is services, its flag must be cleared. If the flag is not
|
||||
* cleared, then execution will jump back to the start of the ISR after the ISR
|
||||
* returns.
|
||||
*
|
||||
* @param[in] uart UART block register address base @ref uart_reg_base
|
||||
* @param[in] ints Interrupts which to clear. Any combination of interrupts may
|
||||
* be specified by OR'ing then together
|
||||
*/
|
||||
void uart_clear_interrupt_flag(uint32_t uart, enum uart_interrupt_flag ints)
|
||||
{
|
||||
UART_ICR(uart) |= ints;
|
||||
}
|
||||
/**@}*/
|
||||
|
||||
/** @defgroup uart_dma UART DMA control
|
||||
* @ingroup uart_file
|
||||
*
|
||||
* \brief <b>Enabling Direct Memory Access transfers for the UART</b>
|
||||
*
|
||||
*/
|
||||
/**@{*/
|
||||
|
||||
/**
|
||||
* \brief Enable the UART Receive DMA.
|
||||
*
|
||||
* @param[in] uart UART block register address base @ref uart_reg_base
|
||||
*/
|
||||
void uart_enable_rx_dma(uint32_t uart)
|
||||
{
|
||||
UART_DMACTL(uart) |= UART_DMACTL_RXDMAE;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Disable the UART Receive DMA.
|
||||
*
|
||||
* @param[in] uart UART block register address base @ref uart_reg_base
|
||||
*/
|
||||
void uart_disable_rx_dma(uint32_t uart)
|
||||
{
|
||||
UART_DMACTL(uart) &= ~UART_DMACTL_RXDMAE;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Enable the UART Transmit DMA.
|
||||
*
|
||||
* @param[in] uart UART block register address base @ref uart_reg_base
|
||||
*/
|
||||
void uart_enable_tx_dma(uint32_t uart)
|
||||
{
|
||||
UART_DMACTL(uart) |= UART_DMACTL_TXDMAE;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Disable the UART Transmit DMA.
|
||||
*
|
||||
* @param[in] uart UART block register address base @ref uart_reg_base
|
||||
*/
|
||||
void uart_disable_tx_dma(uint32_t uart)
|
||||
{
|
||||
UART_DMACTL(uart) &= ~UART_DMACTL_TXDMAE;
|
||||
}
|
||||
/**@}*/
|
||||
|
||||
/** @defgroup uart_fifo UART FIFO control
|
||||
* @ingroup uart_file
|
||||
*
|
||||
* \brief <b>Enabling and controlling UART FIFO</b>
|
||||
*
|
||||
* The UART on the LM4F can either be used with a single character TX and RX
|
||||
* buffer, or with a 8 character TX and RX FIFO. In order to use the FIFO it
|
||||
* must be enabled, this is done with uart_enable_fifo() and can be disabled
|
||||
* again with uart_disable_fifo(). On reset the FIFO is disabled, and it must
|
||||
* be explicitly be enabled.
|
||||
*
|
||||
* When enabling the UART FIFOs, RX and TX interrupts are triggered according
|
||||
* to the amount of data in the FIFOs. For the RX FIFO the trigger level is
|
||||
* defined by how full the FIFO is. The TX FIFO trigger level is defined by
|
||||
* how empty the FIFO is instead.
|
||||
*
|
||||
* For example, to enable the FIFOs and trigger interrupts for a single
|
||||
* received and single transmitted character:
|
||||
* @code{.c}
|
||||
* uart_enable_fifo(UART0);
|
||||
* uart_set_fifo_trigger_levels(UART0, UART_FIFO_RX_TRIG_1_8,
|
||||
* UART_FIFO_TX_TRIG_7_8);
|
||||
* @endcode
|
||||
*/
|
||||
/**@{*/
|
||||
|
||||
/**
|
||||
* \brief Enable FIFO for the UART.
|
||||
*
|
||||
* @param[in] uart UART block register address base @ref uart_reg_base
|
||||
*/
|
||||
void uart_enable_fifo(uint32_t uart)
|
||||
{
|
||||
UART_LCRH(uart) |= UART_LCRH_FEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Disable FIFO for the UART.
|
||||
*
|
||||
* @param[in] uart UART block register address base @ref uart_reg_base
|
||||
*/
|
||||
void uart_disable_fifo(uint32_t uart)
|
||||
{
|
||||
UART_LCRH(uart) &= ~UART_LCRH_FEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Set the FIFO trigger levels.
|
||||
*
|
||||
* @param[in] uart UART block register address base @ref uart_reg_base
|
||||
* @param[in] rx_level Trigger level for RX FIFO
|
||||
* @param[in] tx_level Trigger level for TX FIFO
|
||||
*/
|
||||
void uart_set_fifo_trigger_levels(uint32_t uart,
|
||||
enum uart_fifo_rx_trigger_level rx_level,
|
||||
enum uart_fifo_tx_trigger_level tx_level)
|
||||
{
|
||||
UART_IFLS(uart) = rx_level | tx_level;
|
||||
}
|
||||
/**@}*/
|
||||
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
24
libopencm3/lib/lm4f/vector_chipset.c
Normal file
24
libopencm3/lib/lm4f/vector_chipset.c
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2016 Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
static void pre_main(void)
|
||||
{
|
||||
/* Enable FPU */
|
||||
SCB_CPACR |= SCB_CPACR_FULL * (SCB_CPACR_CP10 | SCB_CPACR_CP11);
|
||||
}
|
||||
41
libopencm3/lib/lpc13xx/Makefile
Normal file
41
libopencm3/lib/lpc13xx/Makefile
Normal file
@@ -0,0 +1,41 @@
|
||||
##
|
||||
## This file is part of the libopencm3 project.
|
||||
##
|
||||
## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
##
|
||||
## 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/>.
|
||||
##
|
||||
|
||||
LIBNAME = libopencm3_lpc13xx
|
||||
SRCLIBDIR ?= ..
|
||||
|
||||
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-m3 -mthumb $(FP_FLAGS) -Wstrict-prototypes \
|
||||
-ffunction-sections -fdata-sections -MD -DLPC13XX
|
||||
TGT_CFLAGS += $(DEBUG_FLAGS)
|
||||
TGT_CFLAGS += $(STANDARD_FLAGS)
|
||||
# ARFLAGS = rcsv
|
||||
ARFLAGS = rcs
|
||||
|
||||
OBJS += gpio.o
|
||||
|
||||
VPATH += ../cm3
|
||||
|
||||
include ../Makefile.include
|
||||
42
libopencm3/lib/lpc13xx/gpio.c
Normal file
42
libopencm3/lib/lpc13xx/gpio.c
Normal file
@@ -0,0 +1,42 @@
|
||||
/** @defgroup gpio_file GPIO
|
||||
|
||||
@ingroup LPC13xx
|
||||
|
||||
@brief <b>libopencm3 LPC13xx General Purpose I/O</b>
|
||||
|
||||
@version 1.0.0
|
||||
|
||||
@author @htmlonly © @endhtmlonly 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
|
||||
LGPL License Terms @ref lgpl_license
|
||||
*/
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2010 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
*
|
||||
* 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/lpc13xx/gpio.h>
|
||||
|
||||
void gpio_set(uint32_t gpioport, uint16_t gpios)
|
||||
{
|
||||
GPIO_DATA(gpioport) = gpios;
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
|
||||
42
libopencm3/lib/lpc17xx/Makefile
Normal file
42
libopencm3/lib/lpc17xx/Makefile
Normal file
@@ -0,0 +1,42 @@
|
||||
##
|
||||
## This file is part of the libopencm3 project.
|
||||
##
|
||||
## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
##
|
||||
## 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/>.
|
||||
##
|
||||
|
||||
LIBNAME = libopencm3_lpc17xx
|
||||
SRCLIBDIR ?= ..
|
||||
|
||||
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-m3 -mthumb $(FP_FLAGS) -Wstrict-prototypes \
|
||||
-ffunction-sections -fdata-sections -MD -DLPC17XX
|
||||
TGT_CFLAGS += $(DEBUG_FLAGS)
|
||||
TGT_CFLAGS += $(STANDARD_FLAGS)
|
||||
# ARFLAGS = rcsv
|
||||
ARFLAGS = rcs
|
||||
|
||||
OBJS += gpio.o
|
||||
OBJS += pwr.o
|
||||
|
||||
VPATH += ../cm3
|
||||
|
||||
include ../Makefile.include
|
||||
48
libopencm3/lib/lpc17xx/gpio.c
Normal file
48
libopencm3/lib/lpc17xx/gpio.c
Normal file
@@ -0,0 +1,48 @@
|
||||
/** @defgroup gpio_file GPIO
|
||||
|
||||
@ingroup LPC17xx
|
||||
|
||||
@brief <b>libopencm3 LPC17xx General Purpose I/O</b>
|
||||
|
||||
@version 1.0.0
|
||||
|
||||
@author @htmlonly © @endhtmlonly 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
|
||||
LGPL License Terms @ref lgpl_license
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2010 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
*
|
||||
* 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/lpc17xx/gpio.h>
|
||||
|
||||
void gpio_set(uint32_t gpioport, uint32_t gpios)
|
||||
{
|
||||
GPIO_SET(gpioport) = gpios;
|
||||
}
|
||||
|
||||
void gpio_clear(uint32_t gpioport, uint32_t gpios)
|
||||
{
|
||||
GPIO_CLR(gpioport) = gpios;
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
|
||||
48
libopencm3/lib/lpc17xx/pwr.c
Normal file
48
libopencm3/lib/lpc17xx/pwr.c
Normal file
@@ -0,0 +1,48 @@
|
||||
/** @defgroup pwr-file PWR
|
||||
|
||||
@ingroup LPC17xx
|
||||
|
||||
@brief <b>libopencm3 LPC17xx Power Control</b>
|
||||
|
||||
@version 1.0.0
|
||||
|
||||
@author @htmlonly © @endhtmlonly 2013 Silvio Gissi <silvio.gissi@outlook.com>
|
||||
|
||||
LGPL License Terms @ref lgpl_license
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2013 Silvio Gissi <silvio.gissi@outlook.com>
|
||||
*
|
||||
* 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/lpc17xx/pwr.h>
|
||||
|
||||
void pwr_enable_peripherals(uint32_t peripherals)
|
||||
{
|
||||
PWR_PCONP |= peripherals;
|
||||
}
|
||||
|
||||
void pwr_disable_peripherals(uint32_t peripherals)
|
||||
{
|
||||
PWR_PCONP &= ~peripherals;
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
|
||||
53
libopencm3/lib/lpc43xx/gpio.c
Normal file
53
libopencm3/lib/lpc43xx/gpio.c
Normal file
@@ -0,0 +1,53 @@
|
||||
/** @defgroup gpio_file GPIO
|
||||
|
||||
@ingroup LPC43xx
|
||||
|
||||
@brief <b>libopencm3 LPC43xx General Purpose I/O</b>
|
||||
|
||||
@version 1.0.0
|
||||
|
||||
@author @htmlonly © @endhtmlonly 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
|
||||
LGPL License Terms @ref lgpl_license
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2010 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
*
|
||||
* 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/lpc43xx/gpio.h>
|
||||
|
||||
void gpio_set(uint32_t gpioport, uint32_t gpios)
|
||||
{
|
||||
GPIO_SET(gpioport) = gpios;
|
||||
}
|
||||
|
||||
void gpio_clear(uint32_t gpioport, uint32_t gpios)
|
||||
{
|
||||
GPIO_CLR(gpioport) = gpios;
|
||||
}
|
||||
|
||||
void gpio_toggle(uint32_t gpioport, uint32_t gpios)
|
||||
{
|
||||
GPIO_NOT(gpioport) = gpios;
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
|
||||
102
libopencm3/lib/lpc43xx/i2c.c
Normal file
102
libopencm3/lib/lpc43xx/i2c.c
Normal file
@@ -0,0 +1,102 @@
|
||||
/** @defgroup i2c_file I2C
|
||||
|
||||
@ingroup LPC43xx
|
||||
|
||||
@brief <b>libopencm3 LPC43xx I2C</b>
|
||||
|
||||
@version 1.0.0
|
||||
|
||||
@author @htmlonly © @endhtmlonly 2012 Michael Ossmann <mike@ossmann.com>
|
||||
|
||||
LGPL License Terms @ref lgpl_license
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2012 Michael Ossmann <mike@ossmann.com>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This is a very minimal I2C driver just to make sure we can get the
|
||||
* peripheral working.
|
||||
*/
|
||||
|
||||
/**@{*/
|
||||
|
||||
#include <libopencm3/lpc43xx/i2c.h>
|
||||
#include <libopencm3/lpc43xx/scu.h>
|
||||
#include <libopencm3/lpc43xx/cgu.h>
|
||||
|
||||
void i2c0_init(const uint16_t duty_cycle_count)
|
||||
{
|
||||
/* enable input on SCL and SDA pins */
|
||||
SCU_SFSI2C0 = SCU_I2C0_NOMINAL;
|
||||
|
||||
I2C0_SCLH = duty_cycle_count;
|
||||
I2C0_SCLL = duty_cycle_count;
|
||||
|
||||
/* clear the control bits */
|
||||
I2C0_CONCLR = (I2C_CONCLR_AAC | I2C_CONCLR_SIC
|
||||
| I2C_CONCLR_STAC | I2C_CONCLR_I2ENC);
|
||||
|
||||
/* enable I2C0 */
|
||||
I2C0_CONSET = I2C_CONSET_I2EN;
|
||||
}
|
||||
|
||||
/* transmit start bit */
|
||||
void i2c0_tx_start(void)
|
||||
{
|
||||
I2C0_CONCLR = I2C_CONCLR_SIC;
|
||||
I2C0_CONSET = I2C_CONSET_STA;
|
||||
while (!(I2C0_CONSET & I2C_CONSET_SI));
|
||||
I2C0_CONCLR = I2C_CONCLR_STAC;
|
||||
}
|
||||
|
||||
/* transmit data byte */
|
||||
void i2c0_tx_byte(uint8_t byte)
|
||||
{
|
||||
if (I2C0_CONSET & I2C_CONSET_STA) {
|
||||
I2C0_CONCLR = I2C_CONCLR_STAC;
|
||||
}
|
||||
I2C0_DAT = byte;
|
||||
I2C0_CONCLR = I2C_CONCLR_SIC;
|
||||
while (!(I2C0_CONSET & I2C_CONSET_SI));
|
||||
}
|
||||
|
||||
/* receive data byte */
|
||||
uint8_t i2c0_rx_byte(void)
|
||||
{
|
||||
if (I2C0_CONSET & I2C_CONSET_STA) {
|
||||
I2C0_CONCLR = I2C_CONCLR_STAC;
|
||||
}
|
||||
I2C0_CONCLR = I2C_CONCLR_SIC;
|
||||
while (!(I2C0_CONSET & I2C_CONSET_SI));
|
||||
return I2C0_DAT;
|
||||
}
|
||||
|
||||
/* transmit stop bit */
|
||||
void i2c0_stop(void)
|
||||
{
|
||||
if (I2C0_CONSET & I2C_CONSET_STA) {
|
||||
I2C0_CONCLR = I2C_CONCLR_STAC;
|
||||
}
|
||||
I2C0_CONSET = I2C_CONSET_STO;
|
||||
I2C0_CONCLR = I2C_CONCLR_SIC;
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
|
||||
58
libopencm3/lib/lpc43xx/ipc.c
Normal file
58
libopencm3/lib/lpc43xx/ipc.c
Normal file
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2012 Benjamin Vernoux <titanmkd@gmail.com>
|
||||
*
|
||||
* 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/lpc43xx/ipc.h>
|
||||
#include <libopencm3/lpc43xx/creg.h>
|
||||
#include <libopencm3/lpc43xx/rgu.h>
|
||||
|
||||
/* Set M0 in reset mode */
|
||||
void ipc_halt_m0(void)
|
||||
{
|
||||
volatile uint32_t rst_active_status1;
|
||||
|
||||
/* Check if M0 is reset by reading status */
|
||||
rst_active_status1 = RESET_ACTIVE_STATUS1;
|
||||
|
||||
/* If the M0 has reset not asserted, halt it... */
|
||||
while (rst_active_status1 & RESET_CTRL1_M0APP_RST) {
|
||||
RESET_CTRL1 = ((~rst_active_status1) | RESET_CTRL1_M0APP_RST);
|
||||
rst_active_status1 = RESET_ACTIVE_STATUS1;
|
||||
}
|
||||
}
|
||||
|
||||
void ipc_start_m0(uint32_t cm0_baseaddr)
|
||||
{
|
||||
volatile uint32_t rst_active_status1;
|
||||
|
||||
/* Set M0 memory mapping to point to start of M0 image */
|
||||
CREG_M0APPMEMMAP = cm0_baseaddr;
|
||||
|
||||
/* Start/run M0 core */
|
||||
|
||||
/* Release Slave from reset, first read status */
|
||||
rst_active_status1 = RESET_ACTIVE_STATUS1;
|
||||
|
||||
/* If the M0 is being held in reset, release it */
|
||||
/* 1 = no reset, 0 = reset */
|
||||
while (!(rst_active_status1 & RESET_CTRL1_M0APP_RST)) {
|
||||
RESET_CTRL1 = ((~rst_active_status1) & ~RESET_CTRL1_M0APP_RST);
|
||||
rst_active_status1 = RESET_ACTIVE_STATUS1;
|
||||
}
|
||||
}
|
||||
|
||||
43
libopencm3/lib/lpc43xx/m0/Makefile
Normal file
43
libopencm3/lib/lpc43xx/m0/Makefile
Normal file
@@ -0,0 +1,43 @@
|
||||
##
|
||||
## This file is part of the libopencm3 project.
|
||||
##
|
||||
## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
## Copyright (C) 2012 Michael Ossmann <mike@ossmann.com>
|
||||
## Copyright (C) 2012/2013 Benjamin Vernoux <titanmkd@gmail.com>
|
||||
##
|
||||
## 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/>.
|
||||
##
|
||||
|
||||
LIBNAME = libopencm3_lpc43xx_m0
|
||||
SRCLIBDIR ?= ../..
|
||||
|
||||
CC = $(PREFIX)gcc
|
||||
AR = $(PREFIX)ar
|
||||
TGT_CFLAGS = -O2 -Wall -Wextra -I../../../include -fno-common \
|
||||
-mcpu=cortex-m0 -mthumb -Wstrict-prototypes \
|
||||
-ffunction-sections -fdata-sections -MD -DLPC43XX -DLPC43XX_M0
|
||||
TGT_CFLAGS += $(DEBUG_FLAGS)
|
||||
TGT_CFLAGS += $(STANDARD_FLAGS)
|
||||
# ARFLAGS = rcsv
|
||||
ARFLAGS = rcs
|
||||
|
||||
# LPC43xx common files for M4 / M0
|
||||
OBJ_LPC43XX = gpio.o scu.o i2c.o ssp.o uart.o timer.o
|
||||
|
||||
#LPC43xx M0 specific file + Generic LPC43xx M4/M0 files
|
||||
OBJS = $(OBJ_LPC43XX)
|
||||
|
||||
VPATH += ../:../../cm3
|
||||
|
||||
include ../../Makefile.include
|
||||
50
libopencm3/lib/lpc43xx/m4/Makefile
Normal file
50
libopencm3/lib/lpc43xx/m4/Makefile
Normal file
@@ -0,0 +1,50 @@
|
||||
##
|
||||
## This file is part of the libopencm3 project.
|
||||
##
|
||||
## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
## Copyright (C) 2012 Michael Ossmann <mike@ossmann.com>
|
||||
## Copyright (C) 2012 Benjamin Vernoux <titanmkd@gmail.com>
|
||||
## Copyright (C) 2013 Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
||||
##
|
||||
## 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/>.
|
||||
##
|
||||
|
||||
LIBNAME = libopencm3_lpc43xx
|
||||
SRCLIBDIR ?= ../..
|
||||
|
||||
FP_FLAGS ?= -mfloat-abi=hard -mfpu=fpv4-sp-d16
|
||||
CC = $(PREFIX)gcc
|
||||
AR = $(PREFIX)ar
|
||||
TGT_CFLAGS = -O2 \
|
||||
-Wall -Wextra -Wimplicit-function-declaration \
|
||||
-Wredundant-decls -Wmissing-prototypes -Wstrict-prototypes \
|
||||
-Wundef -Wshadow \
|
||||
-I../../../include -fno-common \
|
||||
-mcpu=cortex-m4 -mthumb -Wstrict-prototypes \
|
||||
-ffunction-sections -fdata-sections -MD \
|
||||
$(FP_FLAGS) -DLPC43XX -DLPC43XX_M4
|
||||
TGT_CFLAGS += $(DEBUG_FLAGS)
|
||||
TGT_CFLAGS += $(STANDARD_FLAGS)
|
||||
|
||||
ARFLAGS = rcs
|
||||
|
||||
# LPC43xx common files for M4 / M0
|
||||
OBJ_LPC43XX = gpio.o scu.o i2c.o ssp.o uart.o timer.o
|
||||
|
||||
#LPC43xx M4 specific file + Generic LPC43xx M4/M0 files
|
||||
OBJS = $(OBJ_LPC43XX) ipc.o
|
||||
|
||||
VPATH += ../:../../cm3
|
||||
|
||||
include ../../Makefile.include
|
||||
48
libopencm3/lib/lpc43xx/m4/vector_chipset.c
Normal file
48
libopencm3/lib/lpc43xx/m4/vector_chipset.c
Normal file
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2010 Piotr Esden-Tempski <piotr@esden.net>
|
||||
* Copyright (C) 2012 Michael Ossmann <mike@ossmann.com>
|
||||
*
|
||||
* 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/cm3/common.h>
|
||||
|
||||
extern unsigned _etext_ram, _text_ram, _etext_rom;
|
||||
|
||||
#define CREG_M4MEMMAP MMIO32((0x40043000U + 0x100))
|
||||
|
||||
static void pre_main(void)
|
||||
{
|
||||
volatile unsigned *src, *dest;
|
||||
|
||||
/* Copy the code from ROM to Real RAM (if enabled) */
|
||||
if ((&_etext_ram-&_text_ram) > 0) {
|
||||
src = &_etext_rom-(&_etext_ram-&_text_ram);
|
||||
/* Change Shadow memory to ROM (for Debug Purpose in case Boot
|
||||
* has not set correctly the M4MEMMAP because of debug)
|
||||
*/
|
||||
CREG_M4MEMMAP = (unsigned long)src;
|
||||
|
||||
for (dest = &_text_ram; dest < &_etext_ram; ) {
|
||||
*dest++ = *src++;
|
||||
}
|
||||
|
||||
/* Change Shadow memory to Real RAM */
|
||||
CREG_M4MEMMAP = (unsigned long)&_text_ram;
|
||||
|
||||
/* Continue Execution in RAM */
|
||||
}
|
||||
}
|
||||
52
libopencm3/lib/lpc43xx/scu.c
Normal file
52
libopencm3/lib/lpc43xx/scu.c
Normal file
@@ -0,0 +1,52 @@
|
||||
/** @defgroup scu_file System Control Unit
|
||||
|
||||
@ingroup LPC43xx
|
||||
|
||||
@brief <b>libopencm3 LPC43xx System Control Unit</b>
|
||||
|
||||
@version 1.0.0
|
||||
|
||||
@author @htmlonly © @endhtmlonly 2012 Benjamin Vernoux <titanmkd@gmail.com>
|
||||
|
||||
LGPL License Terms @ref lgpl_license
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2012 Benjamin Vernoux <titanmkd@gmail.com>
|
||||
*
|
||||
* 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/lpc43xx/scu.h>
|
||||
|
||||
/* For pin_conf_normal value see scu.h define SCU_CONF_XXX or Configuration for
|
||||
* different I/O pins types
|
||||
*/
|
||||
void scu_pinmux(scu_grp_pin_t group_pin, uint32_t scu_conf)
|
||||
{
|
||||
MMIO32(group_pin) = scu_conf;
|
||||
}
|
||||
|
||||
/* For other special SCU register USB1, I2C0, ADC0/1, DAC, EMC clock delay See
|
||||
* scu.h
|
||||
*/
|
||||
|
||||
/* For Pin interrupt select register see scu.h SCU_PINTSEL0 & SCU_PINTSEL1 */
|
||||
|
||||
/**@}*/
|
||||
|
||||
140
libopencm3/lib/lpc43xx/ssp.c
Normal file
140
libopencm3/lib/lpc43xx/ssp.c
Normal file
@@ -0,0 +1,140 @@
|
||||
/** @defgroup ssp_file SSP
|
||||
|
||||
@ingroup LPC43xx
|
||||
|
||||
@brief <b>libopencm3 LPC43xx SSP</b>
|
||||
|
||||
@version 1.0.0
|
||||
|
||||
@author @htmlonly © @endhtmlonly 2012 Benjamin Vernoux <titanmkd@gmail.com>
|
||||
|
||||
LGPL License Terms @ref lgpl_license
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2012 Benjamin Vernoux <titanmkd@gmail.com>
|
||||
*
|
||||
* 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/lpc43xx/ssp.h>
|
||||
#include <libopencm3/lpc43xx/cgu.h>
|
||||
|
||||
/* Disable SSP */
|
||||
void ssp_disable(ssp_num_t ssp_num)
|
||||
{
|
||||
uint32_t ssp_port;
|
||||
|
||||
if (ssp_num == SSP0_NUM) {
|
||||
ssp_port = SSP0;
|
||||
} else {
|
||||
ssp_port = SSP1;
|
||||
}
|
||||
/* Disable SSP */
|
||||
SSP_CR1(ssp_port) = 0x0;
|
||||
}
|
||||
|
||||
/*
|
||||
* SSP Init function
|
||||
*/
|
||||
void ssp_init(ssp_num_t ssp_num,
|
||||
ssp_datasize_t data_size,
|
||||
ssp_frame_format_t frame_format,
|
||||
ssp_cpol_cpha_t cpol_cpha_format,
|
||||
uint8_t serial_clock_rate,
|
||||
uint8_t clk_prescale,
|
||||
ssp_mode_t mode,
|
||||
ssp_master_slave_t master_slave,
|
||||
ssp_slave_option_t slave_option)
|
||||
{
|
||||
uint32_t ssp_port;
|
||||
uint32_t clock;
|
||||
|
||||
if (ssp_num == SSP0_NUM) {
|
||||
ssp_port = SSP0;
|
||||
} else {
|
||||
ssp_port = SSP1;
|
||||
}
|
||||
|
||||
/* use PLL1 as clock source for SSP1 */
|
||||
CGU_BASE_SSP1_CLK =
|
||||
CGU_BASE_SSP1_CLK_CLK_SEL(CGU_SRC_PLL1)
|
||||
| CGU_BASE_SSP1_CLK_AUTOBLOCK;
|
||||
|
||||
/* Disable SSP before to configure it */
|
||||
SSP_CR1(ssp_port) = 0x0;
|
||||
|
||||
/* Configure SSP */
|
||||
clock = serial_clock_rate;
|
||||
SSP_CPSR(ssp_port) = clk_prescale;
|
||||
SSP_CR0(ssp_port) =
|
||||
(data_size | frame_format | cpol_cpha_format | (clock<<8));
|
||||
|
||||
/* Enable SSP */
|
||||
SSP_CR1(ssp_port) = (SSP_ENABLE | mode | master_slave | slave_option);
|
||||
}
|
||||
|
||||
static void ssp_wait_until_not_busy(ssp_num_t ssp_num)
|
||||
{
|
||||
uint32_t ssp_port;
|
||||
|
||||
if (ssp_num == SSP0_NUM) {
|
||||
ssp_port = SSP0;
|
||||
} else {
|
||||
ssp_port = SSP1;
|
||||
}
|
||||
|
||||
while ((SSP_SR(ssp_port) & SSP_SR_BSY));
|
||||
}
|
||||
|
||||
/* This Function Wait Data TX Ready, and Write Data to SSP */
|
||||
uint16_t ssp_transfer(ssp_num_t ssp_num, uint16_t data)
|
||||
{
|
||||
uint32_t ssp_port;
|
||||
|
||||
if (ssp_num == SSP0_NUM) {
|
||||
ssp_port = SSP0;
|
||||
} else {
|
||||
ssp_port = SSP1;
|
||||
}
|
||||
|
||||
/* Wait Until FIFO not full */
|
||||
while ((SSP_SR(ssp_port) & SSP_SR_TNF) == 0);
|
||||
|
||||
SSP_DR(ssp_port) = data;
|
||||
|
||||
/* Wait for not busy, since we're controlling CS# of
|
||||
* devices manually and need to wait for the data to
|
||||
* be sent. It may also be important to wait here
|
||||
* in case we're configuring devices via SPI and also
|
||||
* with GPIO control -- we need to know when SPI
|
||||
* commands are effective before altering a device's
|
||||
* state with GPIO. I'm thinking the MAX2837, for
|
||||
* example...
|
||||
*/
|
||||
ssp_wait_until_not_busy(ssp_num);
|
||||
|
||||
/* Wait Until Data Received (Rx FIFO not Empty) */
|
||||
while ((SSP_SR(ssp_port) & SSP_SR_RNE) == 0);
|
||||
|
||||
return SSP_DR(ssp_port);
|
||||
}
|
||||
|
||||
|
||||
/**@}*/
|
||||
|
||||
72
libopencm3/lib/lpc43xx/timer.c
Normal file
72
libopencm3/lib/lpc43xx/timer.c
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2013 Ben Gamari <bgamari@physics.umass.edu>
|
||||
*
|
||||
* 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/>.
|
||||
*
|
||||
* This provides the code for the "next gen" EXTI block provided in F2/F4/L1
|
||||
* devices. (differences only in the source selection)
|
||||
*/
|
||||
|
||||
#include <libopencm3/lpc43xx/timer.h>
|
||||
|
||||
void timer_reset(uint32_t timer_peripheral)
|
||||
{
|
||||
TIMER_TCR(timer_peripheral) |= TIMER_TCR_CRST;
|
||||
TIMER_TCR(timer_peripheral) &= ~TIMER_TCR_CRST;
|
||||
}
|
||||
|
||||
void timer_enable_counter(uint32_t timer_peripheral)
|
||||
{
|
||||
TIMER_TCR(timer_peripheral) |= TIMER_TCR_CEN;
|
||||
}
|
||||
|
||||
void timer_disable_counter(uint32_t timer_peripheral)
|
||||
{
|
||||
TIMER_TCR(timer_peripheral) &= ~TIMER_TCR_CEN;
|
||||
}
|
||||
|
||||
void timer_set_counter(uint32_t timer_peripheral, uint32_t count)
|
||||
{
|
||||
TIMER_TC(timer_peripheral) = count;
|
||||
}
|
||||
|
||||
uint32_t timer_get_counter(uint32_t timer_peripheral)
|
||||
{
|
||||
return TIMER_TC(timer_peripheral);
|
||||
}
|
||||
|
||||
uint32_t timer_get_prescaler(uint32_t timer_peripheral)
|
||||
{
|
||||
return TIMER_PR(timer_peripheral);
|
||||
}
|
||||
|
||||
void timer_set_prescaler(uint32_t timer_peripheral, uint32_t prescaler)
|
||||
{
|
||||
TIMER_PR(timer_peripheral) = prescaler;
|
||||
}
|
||||
|
||||
void timer_set_mode(uint32_t timer_peripheral, uint32_t mode)
|
||||
{
|
||||
TIMER_CTCR(timer_peripheral) = mode |
|
||||
(TIMER_CTCR(timer_peripheral) & TIMER_CTCR_MODE_MASK);
|
||||
}
|
||||
|
||||
void timer_set_count_input(uint32_t timer_peripheral, uint32_t input)
|
||||
{
|
||||
TIMER_CTCR(timer_peripheral) = input |
|
||||
(TIMER_CTCR(timer_peripheral) & TIMER_CTCR_CINSEL_MASK);
|
||||
}
|
||||
|
||||
243
libopencm3/lib/lpc43xx/uart.c
Normal file
243
libopencm3/lib/lpc43xx/uart.c
Normal file
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2012 Benjamin Vernoux <titanmkd@gmail.com>
|
||||
*
|
||||
* 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/lpc43xx/uart.h>
|
||||
#include <libopencm3/lpc43xx/cgu.h>
|
||||
|
||||
#define UART_SRC_32K 0x00
|
||||
#define UART_SRC_IRC 0x01
|
||||
#define UART_SRC_ENET_RX 0x02
|
||||
#define UART_SRC_ENET_TX 0x03
|
||||
#define UART_SRC_GP_CLKIN 0x04
|
||||
#define UART_SRC_XTAL 0x06
|
||||
#define UART_SRC_PLL0USB 0x07
|
||||
#define UART_SRC_PLL0AUDIO 0x08
|
||||
#define UART_SRC_PLL1 0x09
|
||||
#define UART_SRC_IDIVA 0x0C
|
||||
#define UART_SRC_IDIVB 0x0D
|
||||
#define UART_SRC_IDIVC 0x0E
|
||||
#define UART_SRC_IDIVD 0x0F
|
||||
#define UART_SRC_IDIVE 0x10
|
||||
|
||||
#define UART_CGU_AUTOBLOCK_CLOCK_BIT 11
|
||||
/* clock source selection (5 bits) */
|
||||
#define UART_CGU_BASE_CLK_SEL_SHIFT 24
|
||||
|
||||
uint32_t dummy_read;
|
||||
|
||||
/*
|
||||
* UART Init function
|
||||
*/
|
||||
void uart_init(uart_num_t uart_num, uart_databit_t data_nb_bits,
|
||||
uart_stopbit_t data_nb_stop, uart_parity_t data_parity,
|
||||
uint16_t uart_divisor, uint8_t uart_divaddval, uint8_t uart_mulval)
|
||||
{
|
||||
uint32_t lcr_config;
|
||||
uint32_t uart_port;
|
||||
|
||||
uart_port = uart_num;
|
||||
|
||||
switch (uart_num) {
|
||||
case UART0_NUM:
|
||||
/* use PLL1 as clock source for UART0 */
|
||||
CGU_BASE_UART0_CLK = (1<<UART_CGU_AUTOBLOCK_CLOCK_BIT) |
|
||||
(CGU_SRC_PLL1<<UART_CGU_BASE_CLK_SEL_SHIFT);
|
||||
break;
|
||||
|
||||
case UART1_NUM:
|
||||
/* use PLL1 as clock source for UART1 */
|
||||
CGU_BASE_UART1_CLK = (1<<UART_CGU_AUTOBLOCK_CLOCK_BIT) |
|
||||
(CGU_SRC_PLL1<<UART_CGU_BASE_CLK_SEL_SHIFT);
|
||||
break;
|
||||
|
||||
case UART2_NUM:
|
||||
/* use PLL1 as clock source for UART2 */
|
||||
CGU_BASE_UART2_CLK = (1<<UART_CGU_AUTOBLOCK_CLOCK_BIT) |
|
||||
(CGU_SRC_PLL1<<UART_CGU_BASE_CLK_SEL_SHIFT);
|
||||
break;
|
||||
|
||||
case UART3_NUM:
|
||||
/* use PLL1 as clock source for UART3 */
|
||||
CGU_BASE_UART3_CLK = (1<<UART_CGU_AUTOBLOCK_CLOCK_BIT) |
|
||||
(CGU_SRC_PLL1<<UART_CGU_BASE_CLK_SEL_SHIFT);
|
||||
break;
|
||||
|
||||
default:
|
||||
return; /* error */
|
||||
}
|
||||
|
||||
/* FIFOs RX/TX Enabled and Reset RX/TX FIFO (DMA Mode is also cleared)*/
|
||||
UART_FCR(uart_port) = (UART_FCR_FIFO_EN | UART_FCR_RX_RS |
|
||||
UART_FCR_TX_RS);
|
||||
/* Disable FIFO */
|
||||
UART_FCR(uart_port) = 0;
|
||||
|
||||
/* Dummy read (to clear existing data) */
|
||||
while (UART_LSR(uart_port) & UART_LSR_RDR) {
|
||||
dummy_read = UART_RBR(uart_port);
|
||||
}
|
||||
|
||||
/* Wait end of TX & disable TX */
|
||||
UART_TER(uart_port) = UART_TER_TXEN;
|
||||
|
||||
/* Wait for current transmit complete */
|
||||
while (!(UART_LSR(uart_port) & UART_LSR_THRE));
|
||||
|
||||
/* Disable Tx */
|
||||
UART_TER(uart_port) = 0;
|
||||
|
||||
/* Disable interrupt */
|
||||
UART_IER(uart_port) = 0;
|
||||
|
||||
/* Set LCR to default state */
|
||||
UART_LCR(uart_port) = 0;
|
||||
|
||||
/* Set ACR to default state */
|
||||
UART_ACR(uart_port) = 0;
|
||||
|
||||
/* Dummy Read to Clear Status */
|
||||
dummy_read = UART_LSR(uart_port);
|
||||
|
||||
/*
|
||||
Table 835. USART Fractional Divider Register:
|
||||
UARTbaudrate = PCLK / ( 16* (((256*DLM)+ DLL)*(1+(DivAddVal/MulVal))) )
|
||||
The value of MULVAL and DIVADDVAL should comply to the following
|
||||
conditions:
|
||||
1. 1 <= MULVAL <= 15
|
||||
2. 0 <= DIVADDVAL <= 14
|
||||
3. DIVADDVAL < MULVAL
|
||||
*/
|
||||
|
||||
/* Set DLAB Bit */
|
||||
UART_LCR(uart_port) |= UART_LCR_DLAB_EN;
|
||||
UART_DLM(uart_port) = UART_LOAD_DLM(uart_divisor);
|
||||
UART_DLL(uart_port) = UART_LOAD_DLL(uart_divisor);
|
||||
/* Clear DLAB Bit */
|
||||
UART_LCR(uart_port) &= (~UART_LCR_DLAB_EN) & UART_LCR_BITMASK;
|
||||
UART_FDR(uart_port) = UART_FDR_BITMASK &
|
||||
(UART_FDR_MULVAL(uart_mulval) | UART_FDR_DIVADDVAL(uart_divaddval));
|
||||
|
||||
/* Read LCR config & Force Enable of Divisor Latches Access */
|
||||
lcr_config = (UART_LCR(uart_port) & UART_LCR_DLAB_EN) &
|
||||
UART_LCR_BITMASK;
|
||||
lcr_config |= data_nb_bits; /* Set Nb Data Bits */
|
||||
lcr_config |= data_nb_stop; /* Set Nb Stop Bits */
|
||||
lcr_config |= data_parity; /* Set Data Parity */
|
||||
|
||||
/* Write LCR (only 8bits) */
|
||||
UART_LCR(uart_port) = (lcr_config & UART_LCR_BITMASK);
|
||||
|
||||
/* Enable TX */
|
||||
UART_TER(uart_port) = UART_TER_TXEN;
|
||||
}
|
||||
|
||||
/*
|
||||
* This Function return if data are received or not received.
|
||||
*/
|
||||
uart_rx_data_ready_t uart_rx_data_ready(uart_num_t uart_num)
|
||||
{
|
||||
uint32_t uart_port;
|
||||
uint8_t uart_status;
|
||||
uart_rx_data_ready_t data_ready;
|
||||
|
||||
uart_port = uart_num;
|
||||
|
||||
uart_status = UART_LSR(uart_port) & 0xFF;
|
||||
|
||||
/* Check Error */
|
||||
if ((uart_status & UART_LSR_ERROR_MASK) == 0) {
|
||||
/* No errors check if data is ready */
|
||||
if ((uart_status & UART_LSR_RDR) == 0) {
|
||||
data_ready = UART_RX_NO_DATA;
|
||||
} else {
|
||||
data_ready = UART_RX_DATA_READY;
|
||||
}
|
||||
} else {
|
||||
/* UART Error */
|
||||
data_ready = UART_RX_DATA_ERROR;
|
||||
}
|
||||
|
||||
return data_ready;
|
||||
}
|
||||
|
||||
/*
|
||||
* This Function Wait until Data RX Ready, and return Data Read from UART.
|
||||
*/
|
||||
uint8_t uart_read(uart_num_t uart_num)
|
||||
{
|
||||
uint32_t uart_port;
|
||||
uint8_t uart_val;
|
||||
|
||||
uart_port = uart_num;
|
||||
|
||||
/* Wait Until Data Received (Rx Data Not Ready) */
|
||||
while ((UART_LSR(uart_port) & UART_LSR_RDR) == 0);
|
||||
|
||||
uart_val = (UART_RBR(uart_port) & UART_RBR_MASKBIT);
|
||||
|
||||
return uart_val;
|
||||
}
|
||||
|
||||
/*
|
||||
* This Function Wait until Data RX Ready, and return Data Read from UART.
|
||||
*/
|
||||
uint8_t uart_read_timeout(uart_num_t uart_num, uint32_t rx_timeout_nb_cycles,
|
||||
uart_error_t *error)
|
||||
{
|
||||
uint32_t uart_port;
|
||||
uint8_t uart_val;
|
||||
uint32_t counter;
|
||||
|
||||
uart_port = uart_num;
|
||||
|
||||
/* Wait Until Data Received (Rx Data Not Ready) */
|
||||
counter = 0;
|
||||
while ((UART_LSR(uart_port) & UART_LSR_RDR) == 0) {
|
||||
if (rx_timeout_nb_cycles > 0) {
|
||||
counter++;
|
||||
if (counter >= rx_timeout_nb_cycles) {
|
||||
*error = UART_TIMEOUT_ERROR;
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uart_val = (UART_RBR(uart_port) & UART_RBR_MASKBIT);
|
||||
|
||||
/* Clear error */
|
||||
*error = UART_NO_ERROR;
|
||||
|
||||
return uart_val;
|
||||
}
|
||||
|
||||
/* This Function Wait Data TX Ready, and Write Data to UART
|
||||
if rx_timeout_nb_cycles = 0 Infinite wait
|
||||
*/
|
||||
void uart_write(uart_num_t uart_num, uint8_t data)
|
||||
{
|
||||
uint32_t uart_port;
|
||||
|
||||
uart_port = uart_num;
|
||||
|
||||
/* Wait Until FIFO not full */
|
||||
while ((UART_LSR(uart_port) & UART_LSR_THRE) == 0);
|
||||
|
||||
UART_THR(uart_port) = data;
|
||||
}
|
||||
|
||||
46
libopencm3/lib/msp432/e4/Makefile
Normal file
46
libopencm3/lib/msp432/e4/Makefile
Normal file
@@ -0,0 +1,46 @@
|
||||
##
|
||||
## This file is part of the libopencm3 project.
|
||||
##
|
||||
## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
## Copyright (C) 2013 Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
||||
## Copyright (C) 2018 Dmitry Rezvanov <dmitry.rezvanov@yandex.ru>
|
||||
##
|
||||
## 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/>.
|
||||
##
|
||||
|
||||
LIBNAME = libopencm3_msp432e4
|
||||
SRCLIBDIR ?= ../..
|
||||
|
||||
FP_FLAGS ?= -mfloat-abi=hard -mfpu=fpv4-sp-d16
|
||||
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-m4 -mthumb $(FP_FLAGS) \
|
||||
-Wstrict-prototypes \
|
||||
-ffunction-sections -fdata-sections -MD -DMSP432E4
|
||||
TGT_CFLAGS += $(DEBUG_FLAGS)
|
||||
TGT_CFLAGS += $(STANDARD_FLAGS)
|
||||
# ARFLAGS = rcsv
|
||||
ARFLAGS = rcs
|
||||
|
||||
OBJS += gpio.o
|
||||
OBJS += systemcontrol.o
|
||||
|
||||
VPATH += ../:../../cm3:../common
|
||||
|
||||
include ../../Makefile.include
|
||||
448
libopencm3/lib/msp432/e4/gpio.c
Normal file
448
libopencm3/lib/msp432/e4/gpio.c
Normal file
@@ -0,0 +1,448 @@
|
||||
/** @defgroup gpio_file General-Purpose I/O
|
||||
*
|
||||
* @ingroup MSP432E4xx
|
||||
*
|
||||
* @brief libopencm3 MSP432E4xx General Purpose Input/Outputs
|
||||
*
|
||||
* @version 1.0.0
|
||||
*
|
||||
* @date 23 September 2018
|
||||
*
|
||||
* LGPL License Terms @ref lgpl_license
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2011 Gareth McMullin <gareth@blacksphere.co.nz>
|
||||
* Copyright (C) 2013 Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
||||
* Copyright (C) 2018 Dmitry Rezvanov <dmitry.rezvanov@yandex.ru>
|
||||
*
|
||||
* 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/msp432/e4/gpio.h>
|
||||
#include <libopencm3/msp432/e4/systemcontrol.h>
|
||||
|
||||
/** @brief General Purpose Input/Outputs Set Pin Mode
|
||||
*
|
||||
* Sets the Pin Direction, Analog/Digital Mode and Output Pin Pull,
|
||||
* for a set of GPIO pins on a given GPIO port.
|
||||
*
|
||||
* @param[in] gpioport GPIO block register address base @ref gpio_reg_base
|
||||
* @param[in] mode Pin mode @ref gpio_mode
|
||||
* - GPIO_MODE_OUTPUT -- Configure pin as output
|
||||
* - GPIO_MODE_INPUT -- Configure pin as input
|
||||
* - GPIO_MODE_ANALOG -- Configure pin as analog function
|
||||
* @param[in] pull_up_down Pin pull up/down configuration @ref gpio_pull_up_down
|
||||
* - GPIO_PUPD_NONE -- Do not pull the pin high or low
|
||||
* - GPIO_PUPD_PULLUP -- Pull the pin high
|
||||
* - GPIO_PUPD_PULLDOWN -- Pull the pin low
|
||||
* @param[in] gpios Pin identifiers @ref gpio_pin_id. If multiple pins are
|
||||
* to be set, use bitwise OR '|' to separate them.
|
||||
*/
|
||||
void gpio_mode_setup(uint32_t gpioport, enum gpio_mode mode,
|
||||
enum gpio_pull_up_down pull_up_down, uint8_t gpios)
|
||||
{
|
||||
GPIO_AFSEL(gpioport) &= ~gpios;
|
||||
|
||||
switch (mode) {
|
||||
case GPIO_MODE_OUTPUT:
|
||||
GPIO_DIR(gpioport) |= gpios;
|
||||
GPIO_DEN(gpioport) |= gpios;
|
||||
GPIO_AMSEL(gpioport) &= ~gpios;
|
||||
break;
|
||||
case GPIO_MODE_INPUT:
|
||||
GPIO_DIR(gpioport) &= ~gpios;
|
||||
GPIO_DEN(gpioport) |= gpios;
|
||||
GPIO_AMSEL(gpioport) &= ~gpios;
|
||||
break;
|
||||
case GPIO_MODE_ANALOG:
|
||||
GPIO_AFSEL(gpioport) |= gpios;
|
||||
GPIO_DEN(gpioport) &= ~gpios;
|
||||
GPIO_AMSEL(gpioport) |= gpios;
|
||||
break;
|
||||
default:
|
||||
/* Don't do anything */
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* Setting a bit in the GPIO_PDR register clears the corresponding bit
|
||||
* in the GPIO_PUR register, and vice-versa.
|
||||
*/
|
||||
switch (pull_up_down) {
|
||||
case GPIO_PUPD_PULLUP:
|
||||
GPIO_PDR(gpioport) &= ~gpios;
|
||||
GPIO_PUR(gpioport) |= gpios;
|
||||
break;
|
||||
case GPIO_PUPD_PULLDOWN:
|
||||
GPIO_PUR(gpioport) &= ~gpios;
|
||||
GPIO_PDR(gpioport) |= gpios;
|
||||
break;
|
||||
case GPIO_PUPD_NONE: /* Fall through */
|
||||
default:
|
||||
GPIO_PUR(gpioport) &= ~gpios;
|
||||
GPIO_PDR(gpioport) &= ~gpios;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** @brief General Purpose Input/Outputs Set Output Options
|
||||
*
|
||||
* When the pin is set to output mode, this sets the configuration
|
||||
* (open drain/push pull), drive strength, speed and slew rate control,
|
||||
* for a set of GPIO pins on a given GPIO port.
|
||||
*
|
||||
* @param[in] gpioport GPIO block register address base @ref gpio_reg_base
|
||||
* @param[in] otype Output driver configuration @ref gpio_output_type
|
||||
* - GPIO_OTYPE_PP -- Configure pin driver as push-pull \n
|
||||
* - GPIO_OTYPE_OD -- Configure pin driver as open drain
|
||||
* @param[in] drive Pin drive strength @ref gpio_drive_strength
|
||||
* - GPIO_DRIVE_2MA -- 2mA drive \n
|
||||
* - GPIO_DRIVE_4MA -- 4mA drive \n
|
||||
* - GPIO_DRIVE_6MA -- 4mA drive \n
|
||||
* - GPIO_DRIVE_8MA -- 8mA drive \n
|
||||
* - GPIO_DRIVE_10MA -- 10mA drive \n
|
||||
* - GPIO_DRIVE_12MA -- 12mA drive
|
||||
* @param[in] slewctl Pin slew rate control select @ref gpio_slew_ctl
|
||||
* @note Available only for 8, 10 and 12-ma drive strength.
|
||||
* - GPIO_SLEW_CTL_ENABLE -- Slew rate control enable
|
||||
* - GPIO_SLEW_CTL_DISABLE -- Slew rate control disable
|
||||
* @param[in] gpios Pin identifiers @ref gpio_pin_id. If multiple pins are
|
||||
* to be set, use bitwise OR '|' to separate them.
|
||||
*/
|
||||
void gpio_set_output_options(uint32_t gpioport,
|
||||
enum gpio_output_type otype,
|
||||
enum gpio_drive_strength drive,
|
||||
enum gpio_slew_ctl slewctl,
|
||||
uint8_t gpios)
|
||||
{
|
||||
uint8_t i;
|
||||
uint8_t pin_mask;
|
||||
|
||||
if (otype == GPIO_OTYPE_OD) {
|
||||
GPIO_ODR(gpioport) |= gpios;
|
||||
} else {
|
||||
GPIO_ODR(gpioport) &= ~gpios;
|
||||
}
|
||||
|
||||
GPIO_PP(gpioport) |= GPIO_PP_EDE;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
pin_mask = (1 << i);
|
||||
|
||||
if (!(gpios & pin_mask)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
GPIO_PC(gpioport) &= ~GPIO_PC_EDM_MASK(i);
|
||||
GPIO_PC(gpioport) |= GPIO_PC_EDM(i, GPIO_PC_EDM_FULL_RANGE);
|
||||
}
|
||||
|
||||
GPIO_DR4R(gpioport) &= ~gpios;
|
||||
GPIO_DR8R(gpioport) &= ~gpios;
|
||||
GPIO_DR12R(gpioport) &= ~gpios;
|
||||
|
||||
switch (drive) {
|
||||
case GPIO_DRIVE_4MA:
|
||||
GPIO_DR4R(gpioport) |= gpios;
|
||||
break;
|
||||
case GPIO_DRIVE_6MA:
|
||||
GPIO_DR8R(gpioport) |= gpios;
|
||||
break;
|
||||
case GPIO_DRIVE_8MA:
|
||||
GPIO_DR4R(gpioport) |= gpios;
|
||||
GPIO_DR8R(gpioport) |= gpios;
|
||||
break;
|
||||
case GPIO_DRIVE_10MA:
|
||||
GPIO_DR8R(gpioport) |= gpios;
|
||||
GPIO_DR12R(gpioport) |= gpios;
|
||||
break;
|
||||
case GPIO_DRIVE_12MA:
|
||||
GPIO_DR4R(gpioport) |= gpios;
|
||||
GPIO_DR8R(gpioport) |= gpios;
|
||||
GPIO_DR12R(gpioport) |= gpios;
|
||||
break;
|
||||
case GPIO_DRIVE_2MA: /* Fall through */
|
||||
default:
|
||||
/* don't anything */
|
||||
break;
|
||||
}
|
||||
|
||||
if ((slewctl == GPIO_SLEW_CTL_ENABLE) &&
|
||||
((drive == GPIO_DRIVE_8MA) || (drive == GPIO_DRIVE_10MA) ||
|
||||
(drive == GPIO_DRIVE_12MA))) {
|
||||
GPIO_SLR(gpioport) |= gpios;
|
||||
} else {
|
||||
GPIO_SLR(gpioport) &= ~gpios;
|
||||
}
|
||||
}
|
||||
|
||||
/** @brief General Purpose Input/Outputs Set Alternate Function Selection
|
||||
*
|
||||
* Mux the pin or group of pins to the given alternate function. Note that a
|
||||
* number of pins may be set but only with a single AF number.
|
||||
*
|
||||
* Because AF0 is not used on the MSP432E4,
|
||||
* passing GPIO_AF_DISABLE as the alt_func_num parameter will disable
|
||||
* the alternate function of the given pins.
|
||||
*
|
||||
* @param[in] gpioport GPIO block register address base @ref gpio_reg_base
|
||||
* @param[in] alt_func_num Pin alternate function number or GPIO_AF_DISABLE to
|
||||
* disable the alternate function multiplexing.
|
||||
* @param[in] gpios Pin identifiers @ref gpio_pin_id. If multiple pins are
|
||||
* to be set, use bitwise OR '|' to separate them.
|
||||
*/
|
||||
void gpio_set_af(uint32_t gpioport, uint8_t alt_func_num, uint8_t gpios)
|
||||
{
|
||||
uint32_t pctl32;
|
||||
uint8_t pin_mask;
|
||||
uint8_t i;
|
||||
|
||||
/* Did we mean to disable the alternate function? */
|
||||
if (alt_func_num == 0) {
|
||||
GPIO_AFSEL(gpioport) &= ~gpios;
|
||||
return;
|
||||
}
|
||||
|
||||
/* Enable the alternate function */
|
||||
GPIO_AFSEL(gpioport) |= gpios;
|
||||
|
||||
/* Now take care of the actual multiplexing */
|
||||
pctl32 = GPIO_PCTL(gpioport);
|
||||
for (i = 0; i < 8; i++) {
|
||||
pin_mask = (1 << i);
|
||||
|
||||
if (!(gpios & pin_mask)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
pctl32 &= ~GPIO_PCTL_MASK(i);
|
||||
pctl32 |= GPIO_PCTL_AF(i, (alt_func_num & 0xf));
|
||||
}
|
||||
|
||||
GPIO_PCTL(gpioport) = pctl32;
|
||||
}
|
||||
|
||||
/** @brief General Purpose Input/Outputs Configure Interrupt Trigger
|
||||
*
|
||||
* Sets the trigger level/edge, for a set of GPIO pins on a given GPIO port.
|
||||
*
|
||||
* @param[in] gpioport GPIO block register address base @ref gpio_reg_base
|
||||
* @param[in] trigger Trigger configuration @ref gpio_trigger
|
||||
* - GPIO_TRIG_LVL_LOW -- Trigger on low level
|
||||
* - GPIO_TRIG_LVL_HIGH -- Trigger on high level
|
||||
* - GPIO_TRIG_EDGE_FALL -- Trigger on falling edges
|
||||
* - GPIO_TRIG_EDGE_RISE -- Trigger on rising edges
|
||||
* - GPIO_TRIG_EDGE_BOTH -- Trigger on all edges
|
||||
* @param[in] gpios Pin identifiers @ref gpio_pin_id. If multiple pins are
|
||||
* to be configure, use bitwise OR '|' to separate them.
|
||||
*/
|
||||
void gpio_configure_trigger(uint32_t gpioport, enum gpio_trigger trigger,
|
||||
uint8_t gpios)
|
||||
{
|
||||
switch (trigger) {
|
||||
case GPIO_TRIG_LVL_LOW:
|
||||
GPIO_IS(gpioport) |= gpios;
|
||||
GPIO_IEV(gpioport) &= ~gpios;
|
||||
break;
|
||||
case GPIO_TRIG_LVL_HIGH:
|
||||
GPIO_IS(gpioport) |= gpios;
|
||||
GPIO_IEV(gpioport) |= gpios;
|
||||
break;
|
||||
case GPIO_TRIG_EDGE_FALL:
|
||||
GPIO_IS(gpioport) &= ~gpios;
|
||||
GPIO_IBE(gpioport) &= ~gpios;
|
||||
GPIO_IEV(gpioport) &= ~gpios;
|
||||
break;
|
||||
case GPIO_TRIG_EDGE_RISE:
|
||||
GPIO_IS(gpioport) &= ~gpios;
|
||||
GPIO_IBE(gpioport) &= ~gpios;
|
||||
GPIO_IEV(gpioport) |= gpios;
|
||||
break;
|
||||
case GPIO_TRIG_EDGE_BOTH:
|
||||
GPIO_IS(gpioport) &= ~gpios;
|
||||
GPIO_IBE(gpioport) |= gpios;
|
||||
break;
|
||||
default:
|
||||
/* Don't do anything */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** @brief General Purpose Input/Outputs Set a Group of Pins Atomic
|
||||
*
|
||||
* Set one or more pins of the given GPIO port to 1 in an atomic operation.
|
||||
*
|
||||
* @param[in] gpioport GPIO block register address base @ref gpio_reg_base
|
||||
* @param[in] gpios Pin identifiers @ref gpio_pin_id. If multiple pins are
|
||||
* to be changed, use bitwise OR '|' to separate them.
|
||||
*/
|
||||
void gpio_set(uint32_t gpioport, uint8_t gpios)
|
||||
{
|
||||
GPIO_DATA(gpioport)[gpios] = 0xFF;
|
||||
}
|
||||
|
||||
/** @brief General Purpose Input/Outputs Clear a Group of Pins Atomic
|
||||
*
|
||||
* Clear one or more pins of the given GPIO port to 0 in an atomic operation.
|
||||
*
|
||||
* @param[in] gpioport GPIO block register address base @ref gpio_reg_base
|
||||
* @param[in] gpios Pin identifiers @ref gpio_pin_id. If multiple pins are
|
||||
* to be changed, use bitwise OR '|' to separate them.
|
||||
*/
|
||||
void gpio_clear(uint32_t gpioport, uint8_t gpios)
|
||||
{
|
||||
GPIO_DATA(gpioport)[gpios] = 0x0;
|
||||
}
|
||||
|
||||
/** @brief General Purpose Input/Outputs Read a Group of Pins
|
||||
*
|
||||
* @param[in] gpioport GPIO block register address base @ref gpio_reg_base
|
||||
* @param[in] gpios Pin identifiers @ref gpio_pin_id. If multiple pins are
|
||||
* to be read, use bitwise OR '|' to separate them.
|
||||
*
|
||||
* @return Unsigned int8 value of the pin values. The bit position of the pin
|
||||
value returned corresponds to the pin number.
|
||||
*/
|
||||
uint8_t gpio_get(uint32_t gpioport, uint8_t gpios)
|
||||
{
|
||||
return (uint8_t)GPIO_DATA(gpioport)[gpios];
|
||||
}
|
||||
|
||||
/** @brief General Purpose Input/Outputs Toggle a Group of Pins
|
||||
*
|
||||
* Toggle one or more pins of the given GPIO port.
|
||||
* The non-toggled pins are not affected.
|
||||
*
|
||||
* @param[in] gpioport GPIO block register address base @ref gpio_reg_base
|
||||
* @param[in] gpios Pin identifiers @ref gpio_pin_id. If multiple pins are
|
||||
* to be changed, use bitwise OR '|' to separate them.
|
||||
*/
|
||||
void gpio_toggle(uint32_t gpioport, uint8_t gpios)
|
||||
{
|
||||
/* The mask makes sure we only toggle the GPIOs we want to */
|
||||
GPIO_DATA(gpioport)[gpios] ^= GPIO_ALL;
|
||||
}
|
||||
|
||||
/** @brief General Purpose Input/Outputs Read from a Port
|
||||
*
|
||||
* Read the current value of the given GPIO port.
|
||||
*
|
||||
* @param[in] gpioport GPIO block register address base @ref gpio_reg_base
|
||||
*
|
||||
* @return Unsigned int8. The value held in the specified GPIO port.
|
||||
*/
|
||||
uint8_t gpio_port_read(uint32_t gpioport)
|
||||
{
|
||||
return (uint8_t)GPIO_DATA(gpioport)[GPIO_ALL];
|
||||
}
|
||||
|
||||
/** @brief General Purpose Input/Outputs Write to a Port
|
||||
*
|
||||
* Write a value to the given GPIO port.
|
||||
*
|
||||
* @param[in] gpioport GPIO block register address base @ref gpio_reg_base
|
||||
* @param[in] data Unsigned int8. The value to be written to the GPIO port.
|
||||
*/
|
||||
void gpio_port_write(uint32_t gpioport, uint8_t data)
|
||||
{
|
||||
GPIO_DATA(gpioport)[GPIO_ALL] = data;
|
||||
}
|
||||
|
||||
/** @brief General Purpose Input/Outputs Enable Interrupts on specified pins
|
||||
*
|
||||
* Enable interrupts on the specified GPIO pins.
|
||||
*
|
||||
* @note The NVIC must be enabled and properly configured for the interrupt
|
||||
* to be routed to the CPU.
|
||||
*
|
||||
* @param[in] gpioport GPIO block register address base @ref gpio_reg_base)
|
||||
* @param[in] gpios Pin identifiers @ref gpio_pin_id.
|
||||
* Pins whose interrupts to enable.
|
||||
* If multiple pins are to be enable interrupt,
|
||||
* use bitwise OR '|' to separate them.
|
||||
*/
|
||||
void gpio_enable_interrupts(uint32_t gpioport, uint8_t gpios)
|
||||
{
|
||||
GPIO_IM(gpioport) |= gpios;
|
||||
}
|
||||
|
||||
/** @brief General Purpose Input/Outputs Disable interrupts on specified pins
|
||||
*
|
||||
* Disable interrupts on the specified GPIO pins.
|
||||
*
|
||||
* @param[in] gpioport GPIO block register address base @ref gpio_reg_base
|
||||
* @param[in] gpios Pin identifiers @ref gpio_pin_id.
|
||||
* Pins whose interrupts to disable.
|
||||
* If multiple pins are to be disable interrupt,
|
||||
* use bitwise OR '|' to separate them.
|
||||
*/
|
||||
void gpio_disable_interrupts(uint32_t gpioport, uint8_t gpios)
|
||||
{
|
||||
GPIO_IM(gpioport) &= ~gpios;
|
||||
}
|
||||
|
||||
/** @brief General Purpose Input/Outputs Unlock The Commit Control
|
||||
*
|
||||
* Unlocks the commit control of the given pin or group of pins. If a pin is a
|
||||
* JTAG/SWD or NMI, the pin may then be reconfigured as a GPIO pin. If the pin
|
||||
* is not locked by default, this has no effect.
|
||||
*
|
||||
* @param[in] gpioport GPIO block register address base @ref gpio_reg_base
|
||||
* @param[in] gpios Pin identifiers @ref gpio_pin_id.
|
||||
* If multiple pins are to be unlock,
|
||||
* use bitwise OR '|' to separate them.
|
||||
*/
|
||||
void gpio_unlock_commit(uint32_t gpioport, uint8_t gpios)
|
||||
{
|
||||
/* Unlock the GPIO_CR register */
|
||||
GPIO_LOCK(gpioport) = GPIO_LOCK_UNLOCK_CODE;
|
||||
/* Enable committing changes */
|
||||
GPIO_CR(gpioport) |= gpios;
|
||||
/* Lock the GPIO_CR register */
|
||||
GPIO_LOCK(gpioport) = ~GPIO_LOCK_UNLOCK_CODE;
|
||||
}
|
||||
|
||||
/** @brief General Purpose Input/Outputs Determine if interrupt is generated
|
||||
* by the given pin
|
||||
*
|
||||
* @param[in] gpioport GPIO block register address base @ref gpio_reg_base
|
||||
* @param[in] gpios Source pin identifiers @ref gpio_pin_id.
|
||||
* If multiple pins are to be check,
|
||||
* use bitwise OR '|' to separate them.
|
||||
*
|
||||
* @return Unsigned int8. The bit position of the pin
|
||||
value returned corresponds to the pin number.
|
||||
*/
|
||||
uint8_t gpio_is_interrupt_source(uint32_t gpioport, uint8_t gpios)
|
||||
{
|
||||
return GPIO_MIS(gpioport) & gpios;
|
||||
}
|
||||
|
||||
/** @brief General Purpose Input/Outputs Mark Interrupt as Serviced
|
||||
*
|
||||
* After an interrupt is services, its flag must be cleared. If the flag is not
|
||||
* cleared, then execution will jump back to the start of the ISR after the ISR
|
||||
* returns.
|
||||
*
|
||||
* @param[in] gpioport GPIO block register address base @ref gpio_reg_base
|
||||
* @param[in] gpios Pin identifiers @ref gpio_pin_id. If multiple pins are
|
||||
* to be clear interrupt flag, use bitwise OR '|' to separate them.
|
||||
*/
|
||||
void gpio_clear_interrupt_flag(uint32_t gpioport, uint8_t gpios)
|
||||
{
|
||||
GPIO_ICR(gpioport) |= gpios;
|
||||
}
|
||||
130
libopencm3/lib/msp432/e4/systemcontrol.c
Normal file
130
libopencm3/lib/msp432/e4/systemcontrol.c
Normal file
@@ -0,0 +1,130 @@
|
||||
/** @defgroup systemcontrol_file System Control
|
||||
*
|
||||
* @ingroup MSP432E4xx
|
||||
*
|
||||
* @brief libopencm3 MSP432E4xx System Control
|
||||
*
|
||||
* @version 1.0.0
|
||||
*
|
||||
* @date 22 July 2018
|
||||
*
|
||||
* LGPL License Terms @ref lgpl_license
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2012 Alexandru Gagniuc <mr.nuke.me@gmail.com>
|
||||
* Copyright (C) 2018 Dmitry Rezvanov <dmitry.rezvanov@yandex.ru>
|
||||
*
|
||||
* 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/msp432/e4/systemcontrol.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#define _SYSCTL_REG(base, i) MMIO32((base) + ((i) >> 5))
|
||||
#define _SYSCTL_BIT(i) (1 << ((i) & 0x1f))
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/** @brief System Control Enable Peripheral Clock
|
||||
*
|
||||
* @param[in] clock_mode ::msp432_clock_mode Clock mode
|
||||
* @param[in] periph ::msp432_periph Peripheral block
|
||||
*/
|
||||
void sysctl_periph_clock_enable(enum msp432_clock_mode clock_mode,
|
||||
enum msp432_periph periph)
|
||||
{
|
||||
_SYSCTL_REG(SYSCTL_BASE + clock_mode, periph) |= _SYSCTL_BIT(periph);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/** @brief System Control Disable Peripheral Clock
|
||||
*
|
||||
* @param[in] clock_mode ::msp432_clock_mode Clock mode
|
||||
* @param[in] periph ::msp432_periph Peripheral block
|
||||
*/
|
||||
void sysctl_periph_clock_disable(enum msp432_clock_mode clock_mode,
|
||||
enum msp432_periph periph)
|
||||
{
|
||||
_SYSCTL_REG(SYSCTL_BASE + clock_mode, periph) &= ~_SYSCTL_BIT(periph);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/** @brief System Control Peripheral Software Reset
|
||||
*
|
||||
* @param[in] periph ::msp432_periph Peripheral block
|
||||
*/
|
||||
void sysctl_periph_reset(enum msp432_periph periph)
|
||||
{
|
||||
_SYSCTL_REG((uint32_t) &SYSCTL_SRWD, periph) |= _SYSCTL_BIT(periph);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/** @brief System Control Peripheral Clear Software Reset
|
||||
*
|
||||
* @param[in] periph ::msp432_periph Peripheral block
|
||||
*/
|
||||
void sysctl_periph_clear_reset(enum msp432_periph periph)
|
||||
{
|
||||
_SYSCTL_REG((uint32_t) &SYSCTL_SRWD, periph) &= ~_SYSCTL_BIT(periph);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/** @brief System Control Peripheral Is Present
|
||||
*
|
||||
* @param[in] periph ::msp432_periph Peripheral block
|
||||
*/
|
||||
bool sysctl_periph_is_present(enum msp432_periph periph)
|
||||
{
|
||||
uint32_t reg32 = _SYSCTL_REG((uint32_t) &SYSCTL_PPWD, periph);
|
||||
uint32_t mask = _SYSCTL_BIT(periph);
|
||||
|
||||
return((reg32 & mask) != 0);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/** @brief System Control Peripheral Is Ready
|
||||
*
|
||||
* @param[in] periph ::msp432_periph Peripheral block
|
||||
*/
|
||||
bool sysctl_periph_is_ready(enum msp432_periph periph)
|
||||
{
|
||||
uint32_t reg32 = _SYSCTL_REG((uint32_t) &SYSCTL_PRWD, periph);
|
||||
uint32_t mask = _SYSCTL_BIT(periph);
|
||||
|
||||
return((reg32 & mask) != 0);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------*/
|
||||
/** @brief System Control Peripheral Set Power State
|
||||
*
|
||||
* @param[in] power_mode ::msp432_power_mode Power mode
|
||||
* @param[in] periph ::msp432_periph Peripheral block
|
||||
*
|
||||
* @note If the module is in run, sleep or deep-sleep mode - the module
|
||||
* is powered and receives a clock regardless of the value of power mode.
|
||||
*/
|
||||
void sysctl_periph_set_power_state(enum msp432_power_mode power_mode,
|
||||
enum msp432_periph periph)
|
||||
{
|
||||
if (power_mode == POWER_ENABLE) {
|
||||
_SYSCTL_REG((uint32_t) &SYSCTL_PCWD, periph) |= _SYSCTL_BIT(periph);
|
||||
} else {
|
||||
_SYSCTL_REG((uint32_t) &SYSCTL_PCWD, periph) &= ~_SYSCTL_BIT(periph);
|
||||
}
|
||||
}
|
||||
|
||||
#undef _SYSCTL_REG
|
||||
#undef _SYSCTL_BIT
|
||||
50
libopencm3/lib/nrf/51/Makefile
Normal file
50
libopencm3/lib/nrf/51/Makefile
Normal file
@@ -0,0 +1,50 @@
|
||||
##
|
||||
## This file is part of the libopencm3 project.
|
||||
## Copyright (C) 2017-2018 Unicore MX project<dev(at)lists(dot)unicore-mx(dot)org>
|
||||
## Copyright (C) 2021 Eduard Drusa <ventyl86(at)netkosice(dot)sk>
|
||||
##
|
||||
## 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/>.
|
||||
##
|
||||
|
||||
LIBNAME = libopencm3_nrf51
|
||||
SRCLIBDIR ?= ../..
|
||||
|
||||
CC = $(PREFIX)gcc
|
||||
AR = $(PREFIX)ar
|
||||
|
||||
FP_FLAGS ?= -msoft-float
|
||||
|
||||
TGT_CFLAGS = -Os -Wall -Wextra -I../../../include -fno-common \
|
||||
-mcpu=cortex-m0 -mthumb $(FP_FLAGS) \
|
||||
-Wredundant-decls -Wmissing-prototypes -Wstrict-prototypes \
|
||||
-ffunction-sections -fdata-sections -MD -DNRF51
|
||||
|
||||
TGT_CFLAGS += $(DEBUG_FLAGS)
|
||||
TGT_CFLAGS += $(STANDARD_FLAGS)
|
||||
# ARFLAGS = rcsv
|
||||
ARFLAGS = rcs
|
||||
|
||||
OBJS += clock_common.o clock.o
|
||||
OBJS += gpio.o
|
||||
OBJS += i2c_common.o
|
||||
OBJS += ppi.o
|
||||
OBJS += rtc.o
|
||||
OBJS += radio_common.o ./radio.o
|
||||
OBJS += timer.o
|
||||
OBJS += uart.o
|
||||
|
||||
VPATH += ../../cm3:../common
|
||||
|
||||
include ../../Makefile.include
|
||||
|
||||
45
libopencm3/lib/nrf/51/clock.c
Normal file
45
libopencm3/lib/nrf/51/clock.c
Normal file
@@ -0,0 +1,45 @@
|
||||
/** @addtogroup clock_file CLOCK peripheral API
|
||||
*
|
||||
* @brief <b>Access functions for the NRF51 Clock Controller </b>
|
||||
*
|
||||
* @ingroup peripheral_apis
|
||||
* LGPL License Terms @ref lgpl_license
|
||||
* @author @htmlonly © @endhtmlonly 2016
|
||||
* Roel Postelmans
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of the unicore-mx 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <libopencm3/nrf/clock.h>
|
||||
#include <libopencm3/nrf/periph.h>
|
||||
/**@{*/
|
||||
|
||||
/** @brief Select nominal frequency of external crystal for HFCLK.
|
||||
*
|
||||
* @details This register has to match the actual crystal used in design to
|
||||
* enable correct behaviour.
|
||||
*
|
||||
* @param[in] freq enum clock_xtal_freq
|
||||
* */
|
||||
void clock_set_xtal_freq(enum clock_xtal_freq freq)
|
||||
{
|
||||
CLOCK_XTALFREQ = freq;
|
||||
}
|
||||
/**@}*/
|
||||
|
||||
66
libopencm3/lib/nrf/51/radio.c
Normal file
66
libopencm3/lib/nrf/51/radio.c
Normal file
@@ -0,0 +1,66 @@
|
||||
/** @addtogroup radio_file RADIO peripheral API
|
||||
*
|
||||
* @brief <b>Access functions for the NRF51 2.4 GHz Radio </b>
|
||||
* @ingroup peripheral_apis
|
||||
* LGPL License Terms @ref lgpl_license
|
||||
* @author @htmlonly © @endhtmlonly 2016
|
||||
* Maxim Sloyko <maxims@google.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of the unicore-mx 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <libopencm3/nrf/ficr.h>
|
||||
#include <libopencm3/nrf/radio.h>
|
||||
|
||||
/**@{*/
|
||||
|
||||
/** @brief Set radio mode.
|
||||
*
|
||||
* @details The function also performs all required overrides for BLE and NRF mode.
|
||||
*
|
||||
* @param[in] mode the new mode.
|
||||
* */
|
||||
void radio_set_mode(enum radio_mode mode)
|
||||
{
|
||||
/* This is alias to memory register, thus volatile */
|
||||
volatile uint32_t *override_pos = 0;
|
||||
if ((RADIO_MODE_BLE_1MBIT == mode)
|
||||
&& (FICR_OVERRIDEEN & ~FICR_OVERRIDEEN_BLE_1MBIT)) {
|
||||
/* Need to use Override */
|
||||
override_pos = &FICR_BLE_1MBIT0;
|
||||
} else if ((RADIO_MODE_NRF_1MBIT == mode)
|
||||
&& (FICR_OVERRIDEEN & ~FICR_OVERRIDEEN_NRF_1MBIT)) {
|
||||
override_pos = &FICR_NRF_1MBIT0;
|
||||
}
|
||||
|
||||
if (override_pos) {
|
||||
uint8_t i;
|
||||
for (i = 0; i <= 4; ++i, ++override_pos) {
|
||||
RADIO_OVERRIDE(i) = *override_pos;
|
||||
}
|
||||
|
||||
RADIO_OVERRIDE(4) |= RADIO_OVERRIDE4_ENABLE;
|
||||
} else {
|
||||
RADIO_OVERRIDE(4) &= ~RADIO_OVERRIDE4_ENABLE;
|
||||
}
|
||||
|
||||
RADIO_MODE = mode;
|
||||
}
|
||||
/**@}*/
|
||||
|
||||
50
libopencm3/lib/nrf/52/Makefile
Normal file
50
libopencm3/lib/nrf/52/Makefile
Normal file
@@ -0,0 +1,50 @@
|
||||
##
|
||||
## This file is part of the libopencm3 project.
|
||||
##
|
||||
## Copyright (C) 2017-2018 Unicore MX project<dev(at)lists(dot)unicore-mx(dot)org>
|
||||
## Copyright (C) 2021 Eduard Drusa <ventyl86(at)netkosice(dot)sk>
|
||||
##
|
||||
## 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/>.
|
||||
##
|
||||
|
||||
LIBNAME = libopencm3_nrf52
|
||||
SRCLIBDIR ?= ../..
|
||||
|
||||
CC = $(PREFIX)gcc
|
||||
AR = $(PREFIX)ar
|
||||
|
||||
FP_FLAGS ?= -mfloat-abi=hard -mfpu=fpv4-sp-d16
|
||||
|
||||
TGT_CFLAGS = -Os -Wall -Wextra -I../../../include -fno-common \
|
||||
-mcpu=cortex-m4 -mthumb $(FP_FLAGS) \
|
||||
-Wredundant-decls -Wmissing-prototypes -Wstrict-prototypes \
|
||||
-ffunction-sections -fdata-sections -MD -DNRF52
|
||||
TGT_CFLAGS += $(DEBUG_FLAGS)
|
||||
TGT_CFLAGS += $(STANDARD_FLAGS)
|
||||
# ARFLAGS = rcsv
|
||||
ARFLAGS = rcs
|
||||
|
||||
OBJS += clock_common.o
|
||||
OBJS += gpio.o
|
||||
OBJS += i2c.o i2c_common.o
|
||||
OBJS += ppi.o
|
||||
OBJS += radio_common.o
|
||||
OBJS += rtc.o
|
||||
OBJS += timer.o
|
||||
OBJS += uart.o
|
||||
|
||||
VPATH += ../../cm3:../common
|
||||
|
||||
include ../../Makefile.include
|
||||
|
||||
62
libopencm3/lib/nrf/52/i2c.c
Normal file
62
libopencm3/lib/nrf/52/i2c.c
Normal file
@@ -0,0 +1,62 @@
|
||||
/** @addtogroup i2c_file I2C peripheral API
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2022 Eduard Drusa <ventyl86(at)netkosice(dot)sk>
|
||||
*
|
||||
* 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/nrf/52/i2c.h>
|
||||
|
||||
/**@{*/
|
||||
|
||||
/** Configure I2C transmit buffer properties
|
||||
*
|
||||
* Configures transmit buffer for EasyDMA transaction. This API
|
||||
* is only available if @ref I2C_MODE_MASTER mode is activated.
|
||||
*
|
||||
* Configures linear TX buffer for EasyDMA transmission.
|
||||
* @param[in] i2c i2c peripheral base, see @ref i2c_block
|
||||
* @param[in] buffer address of buffer start
|
||||
* @param[in] len length of data in the buffer
|
||||
*/
|
||||
void i2c_set_tx_buffer(uint32_t i2c, const uint8_t *buffer, uint8_t len)
|
||||
{
|
||||
I2C_TXDPTR(i2c) = (uint32_t) buffer;
|
||||
I2C_TXDMAXCNT(i2c) = len;
|
||||
I2C_TXDLIST(i2c) = 0;
|
||||
}
|
||||
|
||||
/** Configure I2C receive buffer properties
|
||||
*
|
||||
* Configures receive buffer for EasyDMA transaction. This API
|
||||
* is only available if @ref I2C_MODE_MASTER mode is activated.
|
||||
*
|
||||
* Configures linear RX buffer for EasyDMA transmission.
|
||||
* @param[in] i2c i2c peripheral base, see @ref i2c_block
|
||||
* @param[in] buffer address of buffer start
|
||||
* @param[in] len length of the buffer
|
||||
*/
|
||||
void i2c_set_rx_buffer(uint32_t i2c, uint8_t *buffer, uint8_t len)
|
||||
{
|
||||
I2C_RXDPTR(i2c) = (uint32_t) buffer;
|
||||
I2C_RXDMAXCNT(i2c) = len;
|
||||
I2C_RXDLIST(i2c) = 0;
|
||||
}
|
||||
|
||||
|
||||
/** @} */
|
||||
83
libopencm3/lib/nrf/common/clock_common.c
Normal file
83
libopencm3/lib/nrf/common/clock_common.c
Normal file
@@ -0,0 +1,83 @@
|
||||
/** @addtogroup clock_file CLOCK peripheral API
|
||||
*
|
||||
* @brief <b>Access functions for the Clock Controller</b>
|
||||
*
|
||||
* @ingroup peripheral_apis
|
||||
* LGPL License Terms @ref lgpl_license
|
||||
* @author @htmlonly © @endhtmlonly 2016 Maxim Sloyko <maxims@google.com>
|
||||
* @author @htmlonly © @endhtmlonly 2021 Eduard Drusa <ventyl86 at netkosice dot sk>
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2017-2018 Unicore MX project<dev(at)lists(dot)unicore-mx(dot)org>
|
||||
* Copyright (C) 2021 Eduard Drusa <ventyl86(at)netkosice(dot)sk>
|
||||
*
|
||||
* 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/nrf/clock.h>
|
||||
#include <libopencm3/nrf/periph.h>
|
||||
/**@{*/
|
||||
|
||||
/** @brief Start Low Frequency Clock
|
||||
*
|
||||
* @param[in] wait bool: If true, will busy wait for the clock to start.
|
||||
*/
|
||||
void clock_start_lfclk(bool wait)
|
||||
{
|
||||
PERIPH_TRIGGER_TASK(CLOCK_TASK_LFCLKSTART);
|
||||
if (wait) {
|
||||
while (!(CLOCK_LFCLKSTAT & CLOCK_LFCLKSTAT_STATE));
|
||||
}
|
||||
}
|
||||
|
||||
/** @brief Stop Low Frequency Clock */
|
||||
void clock_stop_lfclk()
|
||||
{
|
||||
PERIPH_TRIGGER_TASK(CLOCK_TASK_LFCLKSTOP);
|
||||
}
|
||||
|
||||
/** @brief Start High Frequency Crystal Oscillator.
|
||||
*
|
||||
* @details Oscillator needs to be running for the radio to work.
|
||||
*
|
||||
* @param[in] wait bool If true, will busy wait for the clock to start.
|
||||
*/
|
||||
void clock_start_hfclk(bool wait)
|
||||
{
|
||||
PERIPH_TRIGGER_TASK(CLOCK_TASK_HFCLKSTART);
|
||||
if (wait) {
|
||||
while (!(CLOCK_HFCLKSTAT & CLOCK_HFCLKSTAT_STATE));
|
||||
}
|
||||
}
|
||||
|
||||
/** @brief Stop High Frequency Crystal Oscillator */
|
||||
void clock_stop_hfclk()
|
||||
{
|
||||
PERIPH_TRIGGER_TASK(CLOCK_TASK_HFCLKSTOP);
|
||||
}
|
||||
|
||||
/** @brief Low Frequency Clock Source.
|
||||
*
|
||||
* @param[in] lfclk_src enum clock_lfclk_src
|
||||
*/
|
||||
void clock_set_lfclk_src(enum clock_lfclk_src lfclk_src)
|
||||
{
|
||||
CLOCK_LFCLKSRC = lfclk_src;
|
||||
}
|
||||
/**@}*/
|
||||
|
||||
208
libopencm3/lib/nrf/common/gpio.c
Normal file
208
libopencm3/lib/nrf/common/gpio.c
Normal file
@@ -0,0 +1,208 @@
|
||||
/** @addtogroup gpio_file GPIO peripheral API
|
||||
*
|
||||
* @brief <b>Access functions for the I/O Controller</b>
|
||||
*
|
||||
* @ingroup peripheral_apis
|
||||
* LGPL License Terms @ref lgpl_license
|
||||
* @author @htmlonly © @endhtmlonly 2016
|
||||
* Maxim Sloyko <maxims@google.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2017-2018 Unicore MX project<dev(at)lists(dot)unicore-mx(dot)org>
|
||||
* Copyright (C) 2021 Eduard Drusa <ventyl86(at)netkosice(dot)sk>
|
||||
*
|
||||
* 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/nrf/gpio.h>
|
||||
|
||||
/** @brief Atomic set output
|
||||
*
|
||||
* @param[in] gpioport Port identifier @ref gpio_port_id
|
||||
* @param[in] gpios Pin identifiers @ref gpio_pin_id
|
||||
*/
|
||||
void gpio_set(uint32_t gpioport, uint32_t gpios)
|
||||
{
|
||||
(void) gpioport;
|
||||
GPIO_OUTSET = gpios;
|
||||
}
|
||||
|
||||
/** @brief Atomic clear output
|
||||
*
|
||||
* @param[in] gpioport Port identifier @ref gpio_port_id
|
||||
* @param[in] gpios Pin identifiers @ref gpio_pin_id
|
||||
*/
|
||||
void gpio_clear(uint32_t gpioport, uint32_t gpios)
|
||||
{
|
||||
(void) gpioport;
|
||||
GPIO_OUTCLR = gpios;
|
||||
}
|
||||
|
||||
/** @brief Toggle output
|
||||
*
|
||||
* @param[in] gpioport Port identifier @ref gpio_port_id
|
||||
* @param[in] gpios Pin identifiers @ref gpio_pin_id
|
||||
*/
|
||||
void gpio_toggle(uint32_t gpioport, uint32_t gpios)
|
||||
{
|
||||
(void) gpioport;
|
||||
uint32_t reg_val = GPIO_OUT;
|
||||
GPIO_OUTCLR = reg_val & gpios;
|
||||
GPIO_OUTSET = (~reg_val) & gpios;
|
||||
}
|
||||
|
||||
/** @brief Read GPIO values
|
||||
*
|
||||
* @param[in] gpioport Port identifier @ref gpio_port_id
|
||||
* @param[in] gpios Pin identifiers @ref gpio_pin_id
|
||||
*/
|
||||
uint32_t gpio_get(uint32_t gpioport, uint32_t gpios)
|
||||
{
|
||||
(void) gpioport;
|
||||
return GPIO_IN & gpios;
|
||||
}
|
||||
|
||||
/** @brief Set GPIO Pin Mode
|
||||
*
|
||||
* Sets the mode (input/output) and configuration (analog/digitial and
|
||||
* open drain/push pull), for a set of GPIO pins on a given GPIO port.
|
||||
*
|
||||
* @param[in] gpioport Port identifier @ref gpio_port_id
|
||||
* @param[in] mode Pin mode @ref gpio_mode
|
||||
* @param[in] pull_up_down Pull up / pull down configuration @ref gpio_pupd
|
||||
* @param[in] gpios Pin identifiers @ref gpio_pin_id
|
||||
* If multiple pins are to be set, use bitwise OR '|' to separate
|
||||
* them.
|
||||
*/
|
||||
void gpio_mode_setup(uint32_t gpioport, uint32_t mode, uint32_t pull_up_down,
|
||||
uint32_t gpios)
|
||||
{
|
||||
(void) gpioport;
|
||||
|
||||
uint8_t i = 0;
|
||||
while (gpios) {
|
||||
if (gpios & 1) {
|
||||
GPIO_PIN_CNF(i) = (
|
||||
GPIO_PIN_CNF(i) &
|
||||
~((GPIO_CNF_MODE_MASK << GPIO_CNF_MODE_SHIFT)
|
||||
| (GPIO_CNF_PUPD_MASK << GPIO_CNF_PUPD_SHIFT)
|
||||
)
|
||||
) | (mode << GPIO_CNF_MODE_SHIFT)
|
||||
| (pull_up_down << GPIO_CNF_PUPD_SHIFT);
|
||||
}
|
||||
++i;
|
||||
gpios >>= 1;
|
||||
}
|
||||
}
|
||||
|
||||
/** Configure GPIO pin input and output specifics.
|
||||
*
|
||||
* Configure drive strength and input sensing for given GPIO port.
|
||||
* @param [in] gpioport GPIO port identifier, see @ref gpio_port_id
|
||||
* @param [in] drive Drive schema used to drive pin, see @ref gpio_drive
|
||||
* @param [in] sense Pin sensing mechanism, see @ref gpio_sense
|
||||
* @param[in] gpios Pin identifiers @ref gpio_pin_id
|
||||
* If multiple pins are to be set, use bitwise OR '|' to separate
|
||||
* them.
|
||||
*/
|
||||
void gpio_set_options(uint32_t gpioport, uint32_t drive, uint32_t sense,
|
||||
uint32_t gpios)
|
||||
{
|
||||
(void) gpioport;
|
||||
|
||||
uint8_t i = 0;
|
||||
while (gpios) {
|
||||
if (gpios & 1) {
|
||||
GPIO_PIN_CNF(i) = (GPIO_PIN_CNF(i) &
|
||||
~((GPIO_CNF_DRIVE_MASK << GPIO_CNF_DRIVE_SHIFT)
|
||||
| (GPIO_CNF_SENSE_MASK << GPIO_CNF_SENSE_SHIFT)
|
||||
)
|
||||
) | (drive << GPIO_CNF_DRIVE_SHIFT)
|
||||
| (sense << GPIO_CNF_SENSE_SHIFT);
|
||||
}
|
||||
++i;
|
||||
gpios >>= 1;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/** @brief Configure Task in GPIO TE Module
|
||||
*
|
||||
* @param[in] task_num uint8_t Task number (0-3)
|
||||
* @param[in] pin_num uint8_t GPIO Pin number (0-31)
|
||||
* @param[in] polarity uint8_t polarity Operation to perform when task is triggered.
|
||||
* @param[in] init uint8_t Initial state of the pin, non-zero means initially active,
|
||||
* zero means initially inactive
|
||||
*/
|
||||
void gpio_configure_task(uint8_t task_num,
|
||||
uint8_t pin_num, uint8_t polarity, uint32_t init)
|
||||
{
|
||||
/* any non-zero value means, that pin is active */
|
||||
if (init) {
|
||||
init = GPIO_TE_CONFIG_OUTINIT;
|
||||
}
|
||||
|
||||
GPIO_TE_CONFIG(task_num) = (GPIO_TE_MODE_TASK << GPIO_TE_CONFIG_MODE_SHIFT)
|
||||
| (pin_num << GPIO_TE_CONFIG_PSEL_SHIFT)
|
||||
| (polarity << GPIO_TE_CONFIG_POLARITY_SHIFT)
|
||||
| init;
|
||||
}
|
||||
|
||||
/** @brief Configure Event in GPIO TE Module
|
||||
*
|
||||
* @param[in] event_num Event number (0-3)
|
||||
* @param[in] pin_num GPIO Pin number (0-31)
|
||||
* @param[in] polarity Operation to perform when task is triggered.
|
||||
*/
|
||||
void gpio_configure_event(uint8_t event_num, uint8_t pin_num, uint8_t polarity)
|
||||
{
|
||||
GPIO_TE_CONFIG(event_num) = (GPIO_TE_MODE_EVENT << GPIO_TE_CONFIG_MODE_SHIFT)
|
||||
| (pin_num << GPIO_TE_CONFIG_PSEL_SHIFT)
|
||||
| (polarity << GPIO_TE_CONFIG_POLARITY_SHIFT);
|
||||
}
|
||||
|
||||
/** @brief Enable GPIO interrupts
|
||||
*
|
||||
* @param[in] mask interrupts to enable.
|
||||
*/
|
||||
void gpio_enable_interrupts(uint32_t mask)
|
||||
{
|
||||
GPIO_INTENSET = mask;
|
||||
}
|
||||
|
||||
/** @brief Disable GPIO interrupts
|
||||
*
|
||||
* @param[in] mask interrupts to disable.
|
||||
*/
|
||||
void gpio_disable_interrupts(uint32_t mask)
|
||||
{
|
||||
GPIO_INTENCLR = mask;
|
||||
}
|
||||
|
||||
/** @brief Disable all GPIO interrupts
|
||||
*
|
||||
*/
|
||||
void gpio_clear_interrupts(void)
|
||||
{
|
||||
GPIO_INTENCLR = 0xffffffff;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
206
libopencm3/lib/nrf/common/i2c_common.c
Normal file
206
libopencm3/lib/nrf/common/i2c_common.c
Normal file
@@ -0,0 +1,206 @@
|
||||
/** @addtogroup i2c_file I2C peripheral API
|
||||
*
|
||||
* @brief <b>Access functions for the I2C Controller</b>
|
||||
*
|
||||
* @ingroup peripheral_apis
|
||||
* LGPL License Terms @ref lgpl_license
|
||||
* @author @htmlonly © @endhtmlonly 2016
|
||||
* Maxim Sloyko <maxims@google.com>
|
||||
* @author @htmlonly © @endhtmlonly 2021 - 2022
|
||||
* Eduard Drusa <ventyl86(at)netkosice(dot)sk>
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2017-2018 Unicore MX project<dev(at)lists(dot)unicore-mx(dot)org>
|
||||
* Copyright (C) 2021 Eduard Drusa <ventyl86(at)netkosice(dot)sk>
|
||||
*
|
||||
* 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/nrf/i2c.h>
|
||||
|
||||
/**@{*/
|
||||
|
||||
/** @brief Enable I2C peripheral
|
||||
*
|
||||
* @param[in] i2c i2c peripheral base, see @ref i2c_block
|
||||
* @param[in] mode i2c @ref i2c_mode
|
||||
*/
|
||||
void i2c_enable(uint32_t i2c, uint32_t mode)
|
||||
{
|
||||
I2C_ENABLE(i2c) = mode;
|
||||
}
|
||||
|
||||
/** @brief Disable I2C peripheral
|
||||
*
|
||||
* @param[in] i2c i2c peripheral base, see @ref i2c_block
|
||||
*/
|
||||
void i2c_disable(uint32_t i2c)
|
||||
{
|
||||
I2C_ENABLE(i2c) = 0;
|
||||
}
|
||||
|
||||
/** @brief Start I2C transmission.
|
||||
*
|
||||
* Starts STARTTX task, which generates start condition on I2C bus and
|
||||
* transmits address previously configured by @ref i2c_set_address.
|
||||
*
|
||||
* @param[in] i2c i2c peripheral base, see @ref i2c_block.
|
||||
*/
|
||||
void i2c_start_tx(uint32_t i2c)
|
||||
{
|
||||
I2C_TASK_STARTTX(i2c) = 1;
|
||||
}
|
||||
|
||||
/** @brief Start I2C reception.
|
||||
*
|
||||
* @param[in] i2c i2c peripheral base, see @ref i2c_block.
|
||||
*/
|
||||
void i2c_start_rx(uint32_t i2c)
|
||||
{
|
||||
I2C_TASK_STARTRX(i2c) = 1;
|
||||
}
|
||||
|
||||
/** @brief Signal stop on I2C line.
|
||||
*
|
||||
* @param[in] i2c i2c peripheral base, see @ref i2c_block.
|
||||
*/
|
||||
void i2c_send_stop(uint32_t i2c)
|
||||
{
|
||||
I2C_TASK_STOP(i2c) = 1;
|
||||
}
|
||||
|
||||
/** @brief Select Fast (400kHz) mode.
|
||||
*
|
||||
* @param[in] i2c i2c peripheral base, see @ref i2c_block.
|
||||
*/
|
||||
void i2c_set_fast_mode(uint32_t i2c)
|
||||
{
|
||||
I2C_FREQUENCY(i2c) = I2C_FREQUENCY_400K;
|
||||
}
|
||||
|
||||
/** @brief Select Standard (100kHz) mode.
|
||||
*
|
||||
* @param[in] i2c i2c peripheral base, see @ref i2c_block.
|
||||
*/
|
||||
void i2c_set_standard_mode(uint32_t i2c)
|
||||
{
|
||||
I2C_FREQUENCY(i2c) = I2C_FREQUENCY_100K;
|
||||
}
|
||||
|
||||
/** @brief Set I2C frequency.
|
||||
*
|
||||
* In addition to Standard (100kHz) and Fast (400kHz) modes
|
||||
* this peripheral also supports 250kHz mode.
|
||||
*
|
||||
* @param[in] i2c i2c peripheral base, see @ref i2c_block
|
||||
* @param[in] freq frequency constant. See @ref i2c_freq_const for details
|
||||
* and note that this is not actually a frequency in Hz or kHz.
|
||||
*/
|
||||
void i2c_set_frequency(uint32_t i2c, uint32_t freq)
|
||||
{
|
||||
I2C_FREQUENCY(i2c) = freq;
|
||||
}
|
||||
|
||||
/** @brief Write Data to TXD register to be sent.
|
||||
*
|
||||
* Writes one byte into transmission buffer. This API is only
|
||||
* available if @ref I2C_MODE_LEGACY is activated.
|
||||
*
|
||||
* @param[in] i2c i2c peripheral base, see @ref i2c_block
|
||||
* @param[in] data byte to send next.
|
||||
*/
|
||||
void i2c_send_data(uint32_t i2c, uint8_t data)
|
||||
{
|
||||
I2C_TXD(i2c) = data;
|
||||
}
|
||||
|
||||
/** @brief Read Data from RXD register.
|
||||
*
|
||||
* Reads one byte from reception buffer. This API is only
|
||||
* available if @ref I2C_MODE_LEGACY is activated.
|
||||
*
|
||||
* @param[in] i2c i2c peripheral base, see @ref i2c_block
|
||||
* @returns data from RXD register.
|
||||
*/
|
||||
uint8_t i2c_get_data(uint32_t i2c)
|
||||
{
|
||||
return (uint8_t)I2C_RXD(i2c);
|
||||
}
|
||||
|
||||
/** @brief Select GPIO pins to be used by this peripheral.
|
||||
*
|
||||
* Configures GPIO pins assigned to SCL and SDA signals. These pins are only occupied
|
||||
* by I2C peripheral whenever it is enabled using @ref i2c_enable. It is possible to
|
||||
* ignore any given signal and not map it to pin by using special value of
|
||||
* @ref GPIO_UNCONNECTED instead of @ref gpio_pin_id values.
|
||||
*
|
||||
* This needs to be configured when no transaction is in progress.
|
||||
*
|
||||
* @param[in] i2c i2c peripheral base, see @ref i2c_block
|
||||
* @param[in] scl_pin GPIO pin used for SCL signal
|
||||
* @param[in] sda_pin GPIO pin used for SDA signal
|
||||
*/
|
||||
void i2c_select_pins(uint32_t i2c, uint32_t scl_pin, uint32_t sda_pin)
|
||||
{
|
||||
if (scl_pin != GPIO_UNCONNECTED) {
|
||||
I2C_PSELSCL(i2c) = __GPIO2PIN(scl_pin);
|
||||
} else {
|
||||
I2C_PSELSCL(i2c) = scl_pin;
|
||||
}
|
||||
|
||||
if (sda_pin != GPIO_UNCONNECTED) {
|
||||
I2C_PSELSDA(i2c) = __GPIO2PIN(sda_pin);
|
||||
} else {
|
||||
I2C_PSELSDA(i2c) = sda_pin;
|
||||
}
|
||||
}
|
||||
|
||||
/** @brief Set 7bit I2C address of the device you wish to communicate with.
|
||||
*
|
||||
* @param[in] i2c i2c peripheral base, see @ref i2c_block
|
||||
* @param[in] addr device address (7bit).
|
||||
*/
|
||||
void i2c_set_address(uint32_t i2c, uint8_t addr)
|
||||
{
|
||||
I2C_ADDRESS(i2c) = addr;
|
||||
}
|
||||
|
||||
/** @brief Resume I2C transaction.
|
||||
*
|
||||
* This function is unusual, but required to implement
|
||||
* i2c exchange with this peripheral.
|
||||
*
|
||||
* @param[in] i2c i2c peripheral base, see @ref i2c_block
|
||||
*/
|
||||
void i2c_resume(uint32_t i2c)
|
||||
{
|
||||
PERIPH_TRIGGER_TASK(I2C_TASK_RESUME(i2c));
|
||||
}
|
||||
|
||||
/** Configure event -> task shortcuts
|
||||
*
|
||||
* Sets new shortcut configuration bitmask for I2C peripheral.
|
||||
*
|
||||
* @param[in] i2c i2c peripheral base, see @ref i2c_block
|
||||
* @param[in] shorts @ref i2c_shorts activated
|
||||
*/
|
||||
void i2c_set_shorts(uint32_t i2c, uint32_t shorts)
|
||||
{
|
||||
I2C_SHORTS(i2c) = shorts;
|
||||
}
|
||||
/**@}*/
|
||||
145
libopencm3/lib/nrf/common/ppi.c
Normal file
145
libopencm3/lib/nrf/common/ppi.c
Normal file
@@ -0,0 +1,145 @@
|
||||
/** @addtogroup ppi_file PPI peripheral API
|
||||
*
|
||||
* @brief <b>Access functions for the Programmable Peripheral Interconnect </b>
|
||||
*
|
||||
* @ingroup peripheral_apis
|
||||
* LGPL License Terms @ref lgpl_license
|
||||
* @author @htmlonly © @endhtmlonly 2016
|
||||
* Maxim Sloyko <maxims@google.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2017-2018 Unicore MX project<dev(at)lists(dot)unicore-mx(dot)org>
|
||||
* Copyright (C) 2021 Eduard Drusa <ventyl86(at)netkosice(dot)sk>
|
||||
*
|
||||
* 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 <stdint.h>
|
||||
|
||||
#include <libopencm3/nrf/ppi.h>
|
||||
/**@{*/
|
||||
|
||||
/** @brief Configure PPI Channel.
|
||||
*
|
||||
* @param[in] chan_num uint8_t Channel number (0-15).
|
||||
* @param[in] eep uint32_t Event endpoint. Memory address of the event endpoint.
|
||||
* @param[in] tep uint32_t Task endpoint. Memory address of the task endpoint.
|
||||
*/
|
||||
void ppi_configure_channel(uint8_t chan_num, uint32_t eep, uint32_t tep)
|
||||
{
|
||||
PPI_CH_EEP(chan_num) = eep;
|
||||
PPI_CH_TEP(chan_num) = tep;
|
||||
}
|
||||
|
||||
/** @brief Enable PPI channels, given the channels mask.
|
||||
*
|
||||
* @param[in] channels uint32_t mask of the channels to enable.
|
||||
*/
|
||||
void ppi_enable_channels(uint32_t channels)
|
||||
{
|
||||
PPI_CHENSET = channels;
|
||||
}
|
||||
|
||||
/** @brief Disable PPI channels, given the channels mask.
|
||||
*
|
||||
* @param[in] channels uint32_t mask of the channels to disable.
|
||||
*/
|
||||
void ppi_disable_channels(uint32_t channels)
|
||||
{
|
||||
PPI_CHENCLR = channels;
|
||||
}
|
||||
|
||||
/** @brief Set channels group, given channels mask.
|
||||
*
|
||||
* @param[in] group uint8_t group number (0-3)
|
||||
* @param[in] channels uint32_t mask of the channels to group together.
|
||||
*/
|
||||
void ppi_set_group(uint8_t group, uint32_t channels)
|
||||
{
|
||||
PPI_CHG(group) = channels;
|
||||
}
|
||||
|
||||
/** @brief Enable previously configured group of channels.
|
||||
*
|
||||
* @param[in] group uint8_t group number (0-3)
|
||||
*/
|
||||
void ppi_enable_group(uint8_t group)
|
||||
{
|
||||
PPI_TASK_CHG_EN(group) = 1;
|
||||
}
|
||||
|
||||
/** @brief Disable previously configured group of channels.
|
||||
*
|
||||
* @param[in] group uint8_t group number (0-3)
|
||||
*/
|
||||
void ppi_disable_group(uint8_t group)
|
||||
{
|
||||
PPI_TASK_CHG_DIS(group) = 1;
|
||||
}
|
||||
|
||||
/** @brief Configure new channel.
|
||||
*
|
||||
* This is the alternative API, which requires the caller to store the mask of used channels.
|
||||
*
|
||||
* @param chan_map uint32_t* The mask of channels that are already in use.
|
||||
* For the first call initialize with zero and pass in.
|
||||
* @param[in] eep uint32_t Event endpoint.
|
||||
* @param[in] tep uint32_t Task endpoint.
|
||||
* @param enable bool If true, enable the channel immediately.
|
||||
* @return The number of the new channel. If there are no channels available, returns 0xff.
|
||||
*/
|
||||
uint8_t ppi_add_channel(uint32_t *chan_map, uint32_t eep, uint32_t tep, bool enable)
|
||||
{
|
||||
/* Find a free channel */
|
||||
uint8_t i;
|
||||
uint32_t chan_bit;
|
||||
for (i = 0, chan_bit = 1; i <= PPI_MAX_PROG_CHANNEL; ++i, chan_bit <<= 1) {
|
||||
if (!(chan_bit & *chan_map)) {
|
||||
*chan_map |= chan_bit;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If all channels are taken, return error. */
|
||||
if (i > PPI_MAX_PROG_CHANNEL) {
|
||||
return 0xff;
|
||||
}
|
||||
|
||||
ppi_configure_channel(i, eep, tep);
|
||||
if (enable) {
|
||||
ppi_enable_channels(chan_bit);
|
||||
}
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
/** @brief Disable channel and remove it from the map of used channels.
|
||||
*
|
||||
* This is the alternative API, which requires the caller to store the mask of used channels.
|
||||
*
|
||||
* @param chan_map uint32_t* The mask of channels that are already in use.
|
||||
* For the first call initialize with zero and pass in.
|
||||
* @param[in] chan_num uint8_t the number of the channel to remove from the map.
|
||||
*/
|
||||
void ppi_remove_channel(uint32_t *chan_map, uint8_t chan_num)
|
||||
{
|
||||
ppi_disable_channels(PPI_CH(chan_num));
|
||||
*chan_map &= ~(PPI_CH(chan_num));
|
||||
}
|
||||
/**@}*/
|
||||
|
||||
250
libopencm3/lib/nrf/common/radio_common.c
Normal file
250
libopencm3/lib/nrf/common/radio_common.c
Normal file
@@ -0,0 +1,250 @@
|
||||
/** @addtogroup radio_file RADIO peripheral API
|
||||
*
|
||||
* @brief <b>Access functions for the 2.4 GHz Radio </b>
|
||||
*
|
||||
* @ingroup peripheral_apis
|
||||
* LGPL License Terms @ref lgpl_license
|
||||
* @author @htmlonly © @endhtmlonly 2016
|
||||
* Maxim Sloyko <maxims@google.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2017-2018 Unicore MX project<dev(at)lists(dot)unicore-mx(dot)org>
|
||||
* Copyright (C) 2021 Eduard Drusa <ventyl86(at)netkosice(dot)sk>
|
||||
*
|
||||
* 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/nrf/ficr.h>
|
||||
#include <libopencm3/nrf/radio.h>
|
||||
|
||||
/**@{*/
|
||||
|
||||
/** @brief Set radio transmission power.
|
||||
*
|
||||
* @details Note, not all supported power levels are BLE compliant.
|
||||
*
|
||||
* @param[in] txpower enum radio_txpower
|
||||
* */
|
||||
void radio_set_txpower(enum radio_txpower txpower)
|
||||
{
|
||||
RADIO_TXPOWER = txpower;
|
||||
}
|
||||
|
||||
/** @brief Set bit transmission order to LSB first. */
|
||||
void radio_set_lsbfirst(void)
|
||||
{
|
||||
RADIO_PCNF1 &= ~RADIO_PCNF1_ENDIAN_BIG;
|
||||
}
|
||||
|
||||
/** @brief Set bit transmission order to MSB first. */
|
||||
void radio_set_msbfirst(void)
|
||||
{
|
||||
RADIO_PCNF1 |= RADIO_PCNF1_ENDIAN_BIG;
|
||||
}
|
||||
|
||||
/** @brief Enable on the air data whitening
|
||||
*
|
||||
* @details the in-memory data will remain unwhitened.
|
||||
* */
|
||||
void radio_enable_whitening(void)
|
||||
{
|
||||
RADIO_PCNF1 |= RADIO_PCNF1_WHITEEN;
|
||||
}
|
||||
|
||||
/** @brief Disable on the air data whitening. */
|
||||
void radio_disable_whitening(void)
|
||||
{
|
||||
RADIO_PCNF1 &= ~RADIO_PCNF1_WHITEEN;
|
||||
}
|
||||
|
||||
/** @brief Set CRC length in number of bytes.
|
||||
*
|
||||
* @param[in] crc_len uint8_t CRC length in number of bytes (1-3), 0 = CRC disabled.
|
||||
*/
|
||||
void radio_set_crclen(uint8_t crc_len)
|
||||
{
|
||||
uint32_t reg_crc = RADIO_CRCCNF;
|
||||
reg_crc &= ~RADIO_CRCCNF_LEN_MASK;
|
||||
RADIO_CRCCNF = reg_crc | RADIO_CRCCNF_LEN_MASKED(crc_len);
|
||||
}
|
||||
|
||||
/** @brief Disable CRC calculation. */
|
||||
void radio_disable_crc(void)
|
||||
{
|
||||
RADIO_CRCCNF &= ~RADIO_CRCCNF_LEN_MASK;
|
||||
}
|
||||
|
||||
/** @brief Enable the peripheral. */
|
||||
void radio_enable(void)
|
||||
{
|
||||
RADIO_POWER = RADIO_POWER_ENABLED;
|
||||
}
|
||||
|
||||
/** @brief Disable the peripheral. */
|
||||
void radio_disable(void)
|
||||
{
|
||||
RADIO_POWER = RADIO_POWER_DISABLED;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Set Base Address length.
|
||||
*
|
||||
* @param[in] ba_len uint8_t Base Address length in number of bytes (2-4).
|
||||
*/
|
||||
void radio_set_balen(uint8_t ba_len)
|
||||
{
|
||||
uint32_t reg_pcnf1 = RADIO_PCNF1;
|
||||
reg_pcnf1 &= ~RADIO_PCNF1_BALEN_MASK;
|
||||
RADIO_PCNF1 = reg_pcnf1 | RADIO_PCNF1_BALEN_MASKED(ba_len);
|
||||
}
|
||||
|
||||
/** @brief Set maximum transmission length in number of bytes.
|
||||
*
|
||||
* @param[in] maxlen uint8_t maximum transmission length.
|
||||
*/
|
||||
void radio_set_maxlen(uint8_t maxlen)
|
||||
{
|
||||
uint32_t reg_pcnf1 = RADIO_PCNF1;
|
||||
reg_pcnf1 &= ~RADIO_PCNF1_MAXLEN_MASK;
|
||||
RADIO_PCNF1 = reg_pcnf1 | RADIO_PCNF1_MAXLEN_MASKED(maxlen);
|
||||
}
|
||||
|
||||
/** @brief Exclude access address from CRC calculation.
|
||||
*
|
||||
* @param[in] is_skip_addr bool If true, CRC will be calculated over PDU only,
|
||||
* if false, it will also include the Access Address.
|
||||
*/
|
||||
void radio_set_crc_skipaddr(bool is_skip_addr)
|
||||
{
|
||||
if (is_skip_addr) {
|
||||
RADIO_CRCCNF |= RADIO_CRCCNF_SKIPADDR;
|
||||
} else {
|
||||
RADIO_CRCCNF &= ~RADIO_CRCCNF_SKIPADDR;
|
||||
}
|
||||
}
|
||||
|
||||
/** @brief Configure the radio to be used in BLE mode.
|
||||
*
|
||||
* @details This needs to be called before the radio can be used in BLE mode.
|
||||
* It will set som BLE standard parameters, like Inter-Frame Spacing time,
|
||||
* LSB first, enable whitening, properly configure CRC (for advertising) and address length.
|
||||
*/
|
||||
void radio_configure_ble(void)
|
||||
{
|
||||
#ifdef NRF51
|
||||
radio_set_mode(RADIO_MODE_BLE_1MBIT);
|
||||
#endif
|
||||
RADIO_TIFS = RADIO_BLE_TIFS;
|
||||
radio_set_lsbfirst();
|
||||
radio_enable_whitening();
|
||||
|
||||
radio_set_crclen(RADIO_BLE_CRCLEN);
|
||||
RADIO_CRCPOLY = RADIO_BLE_CRCPOLY;
|
||||
RADIO_CRCINIT = RADIO_BLE_CRCINIT;
|
||||
radio_set_crc_skipaddr(true);
|
||||
radio_set_balen(3);
|
||||
}
|
||||
|
||||
/** @brief Configure the packet.
|
||||
*
|
||||
* @details See the data sheet for details.
|
||||
*/
|
||||
void radio_configure_packet(uint8_t lf_len_bits, uint8_t s0_len_bytes, uint8_t s1_len_bits)
|
||||
{
|
||||
RADIO_PCNF0 = RADIO_PCNF0_LFLEN_MASKED(lf_len_bits)
|
||||
| RADIO_PCNF0_S0LEN_MASKED(s0_len_bytes)
|
||||
| RADIO_PCNF0_S1LEN_MASKED(s1_len_bits);
|
||||
}
|
||||
|
||||
/** @brief Set radio frequency.
|
||||
*
|
||||
* @param[in] freq uint8_t Frequency offset from 2.4GHz in MHz, for example "29" will
|
||||
* tune the radio to 2429MHz
|
||||
*/
|
||||
void radio_set_frequency(uint8_t freq)
|
||||
{
|
||||
RADIO_FREQUENCY = freq;
|
||||
}
|
||||
|
||||
/** @brief Set Data Whitening Initialization Vector.
|
||||
*
|
||||
* @param[in] iv uint8_t Initialization Vector. For BLE, this is channel index.
|
||||
*/
|
||||
void radio_set_datawhiteiv(uint8_t iv)
|
||||
{
|
||||
RADIO_DATAWHITEIV = iv;
|
||||
}
|
||||
|
||||
/* @brief Set Address (base and prefix)
|
||||
*
|
||||
* @details Note that bases are shared between addresses 1-7,
|
||||
* so changing one of them will change others too.
|
||||
*
|
||||
* @param[in] addr_index uint8_t address index (0-7)
|
||||
* @param[in] base uint32_t base part of the address. If balen < 4, appropriate number
|
||||
* of LSBs will be thrown away.
|
||||
* @param[in] prefix uint8_t Address prefix.
|
||||
*/
|
||||
void radio_set_addr(uint8_t addr_index, uint32_t base, uint8_t prefix)
|
||||
{
|
||||
if (addr_index == 0) {
|
||||
RADIO_BASE0 = base;
|
||||
} else {
|
||||
RADIO_BASE1 = base;
|
||||
}
|
||||
|
||||
uint32_t reg_prefix = RADIO_PREFIX_AP(addr_index);
|
||||
reg_prefix &= ~RADIO_PREFIX_AP_MASK(addr_index);
|
||||
RADIO_PREFIX_AP_SET(addr_index, reg_prefix | RADIO_PREFIX_AP_MASKED(addr_index, prefix));
|
||||
}
|
||||
|
||||
/* @brief Set TX address index
|
||||
*
|
||||
* @details The address needs to be previously configured with radio_set_addr()
|
||||
*
|
||||
* @param[in] address_index uint8_t address index (0-7)
|
||||
*/
|
||||
void radio_set_tx_address(uint8_t addr_index)
|
||||
{
|
||||
RADIO_TXADDRESS = addr_index;
|
||||
}
|
||||
|
||||
/* @brief Set pointer for RX/TX data
|
||||
*
|
||||
* @param[in] packet_ptr uint8_t* packet buffer address.
|
||||
*/
|
||||
void radio_set_packet_ptr(uint8_t *packet_ptr)
|
||||
{
|
||||
RADIO_PACKETPTR = (uint32_t)packet_ptr;
|
||||
}
|
||||
|
||||
/* @brief Enable radio Transmitter */
|
||||
void radio_enable_tx(void)
|
||||
{
|
||||
PERIPH_TRIGGER_TASK(RADIO_TASK_TXEN);
|
||||
}
|
||||
|
||||
/* @brief Enable radio Receiver */
|
||||
void radio_enable_rx(void)
|
||||
{
|
||||
PERIPH_TRIGGER_TASK(RADIO_TASK_RXEN);
|
||||
}
|
||||
|
||||
|
||||
/**@}*/
|
||||
|
||||
116
libopencm3/lib/nrf/common/rtc.c
Normal file
116
libopencm3/lib/nrf/common/rtc.c
Normal file
@@ -0,0 +1,116 @@
|
||||
/** @addtogroup rtc_file RTC peripheral API
|
||||
*
|
||||
* @brief <b>Access functions for the Real Time Counter Controller </b>
|
||||
*
|
||||
* @ingroup peripheral_apis
|
||||
* LGPL License Terms @ref lgpl_license
|
||||
* @author @htmlonly © @endhtmlonly 2016
|
||||
* Maxim Sloyko <maxims@google.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2017-2018 Unicore MX project<dev(at)lists(dot)unicore-mx(dot)org>
|
||||
* Copyright (C) 2021 Eduard Drusa <ventyl86(at)netkosice(dot)sk>
|
||||
*
|
||||
* 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/nrf/rtc.h>
|
||||
/**@{*/
|
||||
|
||||
/** @brief RTC set Prescaler value.
|
||||
*
|
||||
* @details The clock needs to be stopped for this to have any effect.
|
||||
*
|
||||
* @param[in] rtc uint32_t RTC base
|
||||
* @param[in] presc uint16_t 12 bit prescaler value.
|
||||
*/
|
||||
void rtc_set_prescaler(uint32_t rtc, uint16_t presc)
|
||||
{
|
||||
RTC_PRESCALER(rtc) = presc & 0xfff;
|
||||
}
|
||||
|
||||
/** @brief RTC get Counter value.
|
||||
*
|
||||
* @param[in] rtc uint32_t RTC base
|
||||
*/
|
||||
uint32_t rtc_get_counter(uint32_t rtc)
|
||||
{
|
||||
return RTC_COUNTER(rtc);
|
||||
}
|
||||
|
||||
/** @brief Enable events
|
||||
*
|
||||
* @param[in] rtc uint32_t RTC base
|
||||
* @param[in] mask uint32_t which events to enable
|
||||
*/
|
||||
void rtc_enable_events(uint32_t rtc, uint32_t mask)
|
||||
{
|
||||
RTC_EVTENSET(rtc) = mask;
|
||||
}
|
||||
|
||||
/** @brief Disable events
|
||||
*
|
||||
* @param[in] rtc uint32_t RTC base
|
||||
* @param[in] mask uint32_t which events to disable
|
||||
*/
|
||||
void rtc_disable_events(uint32_t rtc, uint32_t mask)
|
||||
{
|
||||
RTC_EVTENCLR(rtc) = mask;
|
||||
}
|
||||
|
||||
/** @brief Start the RTC
|
||||
*
|
||||
* @param[in] rtc uint32_t RTC base
|
||||
*/
|
||||
void rtc_start(uint32_t rtc)
|
||||
{
|
||||
PERIPH_TRIGGER_TASK(RTC_TASK_START(rtc));
|
||||
}
|
||||
|
||||
/** @brief Stop the RTC
|
||||
*
|
||||
* @param[in] rtc uint32_t RTC base
|
||||
*/
|
||||
void rtc_stop(uint32_t rtc)
|
||||
{
|
||||
PERIPH_TRIGGER_TASK(RTC_TASK_STOP(rtc));
|
||||
}
|
||||
|
||||
/** @brief Clear the RTC
|
||||
*
|
||||
* @param[in] rtc uint32_t RTC base
|
||||
*/
|
||||
void rtc_clear(uint32_t rtc)
|
||||
{
|
||||
PERIPH_TRIGGER_TASK(RTC_TASK_CLEAR(rtc));
|
||||
}
|
||||
|
||||
/** @brief Set compare register
|
||||
*
|
||||
* @param[in] rtc uint32_t RTC base
|
||||
* @param[in] cmp uint8_t compare number (0-3)
|
||||
* @param[in] value uint32_t compare value
|
||||
*/
|
||||
void rtc_set_compare(uint32_t rtc, uint8_t cmp, uint32_t value)
|
||||
{
|
||||
if (cmp < 4) {
|
||||
RTC_CC(rtc, cmp) = value;
|
||||
}
|
||||
}
|
||||
/**@}*/
|
||||
|
||||
147
libopencm3/lib/nrf/common/timer.c
Normal file
147
libopencm3/lib/nrf/common/timer.c
Normal file
@@ -0,0 +1,147 @@
|
||||
/** @addtogroup timer_file TIMER peripheral API
|
||||
*
|
||||
* @brief <b>Access functions for the Timer/Counter </b>
|
||||
*
|
||||
* @ingroup peripheral_apis
|
||||
* LGPL License Terms @ref lgpl_license
|
||||
* @author @htmlonly © @endhtmlonly 2016
|
||||
* Maxim Sloyko <maxims@google.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2017-2018 Unicore MX project<dev(at)lists(dot)unicore-mx(dot)org>
|
||||
* Copyright (C) 2021 Eduard Drusa <ventyl86(at)netkosice(dot)sk>
|
||||
*
|
||||
* 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/nrf/timer.h>
|
||||
#include <libopencm3/nrf/clock.h>
|
||||
/**@{*/
|
||||
|
||||
/** @brief Get timer ticks
|
||||
*
|
||||
* @param[in] timer uint32_t timer base
|
||||
* @returns current ticks value
|
||||
*/
|
||||
uint32_t timer_get_ticks(uint32_t timer)
|
||||
{
|
||||
uint32_t ticks;
|
||||
uint32_t cc;
|
||||
|
||||
/* TODO: Check WTF is this doing? */
|
||||
cc = TIMER_CC(0, 0);
|
||||
TIMER_TASK_CAPTURE(timer, 0) = 1;
|
||||
ticks = TIMER_CC(timer, 0);
|
||||
TIMER_CC(timer, 0) = cc;
|
||||
return ticks;
|
||||
}
|
||||
|
||||
/** @brief Set timer mode (counter/timer)
|
||||
*
|
||||
* @param[in] timer uint32_t timer base
|
||||
* @param[in] mode enum timer_mode
|
||||
*/
|
||||
void timer_set_mode(uint32_t timer, enum timer_mode mode)
|
||||
{
|
||||
TIMER_MODE(timer) = mode;
|
||||
}
|
||||
|
||||
/** @brief Set timer bit mode (width)
|
||||
*
|
||||
* @param[in] timer uint32_t timer base
|
||||
* @param[in] bitmode enum timer_bitmode
|
||||
*/
|
||||
void timer_set_bitmode(uint32_t timer, enum timer_bitmode bitmode)
|
||||
{
|
||||
TIMER_BITMODE(timer) = bitmode;
|
||||
}
|
||||
|
||||
/** @brief Start the timer
|
||||
*
|
||||
* @param[in] timer uint32_t timer base
|
||||
*/
|
||||
void timer_start(uint32_t timer)
|
||||
{
|
||||
PERIPH_TRIGGER_TASK(TIMER_TASK_START(timer));
|
||||
}
|
||||
|
||||
/** @brief Stop the timer
|
||||
*
|
||||
* @param[in] timer uint32_t timer base
|
||||
*/
|
||||
void timer_stop(uint32_t timer)
|
||||
{
|
||||
PERIPH_TRIGGER_TASK(TIMER_TASK_STOP(timer));
|
||||
}
|
||||
|
||||
/** @brief Clear the timer
|
||||
*
|
||||
* @param[in] timer uint32_t timer base
|
||||
*/
|
||||
void timer_clear(uint32_t timer)
|
||||
{
|
||||
PERIPH_TRIGGER_TASK(TIMER_TASK_CLEAR(timer));
|
||||
}
|
||||
|
||||
/** @brief Set prescaler value
|
||||
*
|
||||
* @param[in] timer uint32_t timer base
|
||||
* @param[in] presc uint8_t prescaler value
|
||||
*/
|
||||
void timer_set_prescaler(uint32_t timer, uint8_t presc)
|
||||
{
|
||||
TIMER_PRESCALER(timer) = presc & TIMER_PRESCALER_MASK;
|
||||
}
|
||||
|
||||
/** @brief Set compare register
|
||||
*
|
||||
* @param[in] timer uint32_t timer base
|
||||
* @param[in] compare_num uint8_t compare number (0-3)
|
||||
* @param[in] compare_val uint32_t compare value
|
||||
*/
|
||||
void timer_set_compare(uint32_t timer, uint8_t compare_num, uint32_t compare_val)
|
||||
{
|
||||
if (compare_num > 3) {
|
||||
return;
|
||||
}
|
||||
|
||||
TIMER_CC(timer, compare_num) = compare_val;
|
||||
}
|
||||
|
||||
/** @brief Get the timer tick frequency
|
||||
*
|
||||
* @param[in] timer uint32_t timer base
|
||||
* @returns frequency of ticking
|
||||
*/
|
||||
uint32_t timer_get_freq(uint32_t timer)
|
||||
{
|
||||
return CLOCK_PCLK/(1<<TIMER_PRESCALER(timer));
|
||||
}
|
||||
|
||||
/** @brief Get compare register
|
||||
*
|
||||
* @param[in] timer uint32_t timer base
|
||||
* @param[in] compare_num uint8_t compare number (0-3)
|
||||
* @returns compare register value
|
||||
*/
|
||||
uint32_t timer_get_cc(uint32_t timer, uint8_t compare_num)
|
||||
{
|
||||
return TIMER_CC(timer, compare_num);
|
||||
}
|
||||
/**@}*/
|
||||
|
||||
171
libopencm3/lib/nrf/common/uart.c
Normal file
171
libopencm3/lib/nrf/common/uart.c
Normal file
@@ -0,0 +1,171 @@
|
||||
/** @addtogroup uart_file UART peripheral API
|
||||
*
|
||||
* @brief <b>Access functions for the UART controller</b>
|
||||
*
|
||||
* @ingroup peripheral_apis
|
||||
* LGPL License Terms @ref lgpl_license
|
||||
* @author @htmlonly © @endhtmlonly 2016
|
||||
* Maxim Sloyko <maxims@google.com>
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2017-2018 Unicore MX project<dev(at)lists(dot)unicore-mx(dot)org>
|
||||
* Copyright (C) 2021 Eduard Drusa <ventyl86(at)netkosice(dot)sk>
|
||||
*
|
||||
* 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/nrf/uart.h>
|
||||
#include <libopencm3/nrf/gpio.h>
|
||||
/**@{*/
|
||||
|
||||
/** @brief Enable the peripheral
|
||||
*
|
||||
* @param[in] uart uint32_t uart base
|
||||
*/
|
||||
void uart_enable(uint32_t uart)
|
||||
{
|
||||
UART_ENABLE(uart) = UART_ENABLE_ENABLED;
|
||||
}
|
||||
|
||||
/** @brief Disable the peripheral
|
||||
*
|
||||
* @param[in] uart uint32_t uart base
|
||||
*/
|
||||
void uart_disable(uint32_t uart)
|
||||
{
|
||||
UART_ENABLE(uart) = UART_ENABLE_DISABLED;
|
||||
}
|
||||
|
||||
/** @brief Configure UART parameters in single call
|
||||
*
|
||||
* @details Any pin number can be set to 0xff (or any number larger than UART_MAX_PIN)
|
||||
* to disconnect that pin.
|
||||
*
|
||||
* @param[in] uart uint32_t uart base
|
||||
* @param[in] tx_pin uint8_t TX pin number
|
||||
* @param[in] rx_pin uint8_t RX pin number
|
||||
* @param[in] rts_pin uint8_t RTS pin number
|
||||
* @param[in] cts_pin uint8_t CTS pin number
|
||||
* @param[in] br enum uart_baud baud rate
|
||||
* @param[in] enable_parity bool If true, enable parity bit
|
||||
*/
|
||||
void uart_configure(uint32_t uart,
|
||||
uint32_t tx_pin, uint32_t rx_pin, uint32_t rts_pin, uint32_t cts_pin,
|
||||
enum uart_baud br, bool enable_parity)
|
||||
{
|
||||
uart_set_pins(uart, rx_pin, tx_pin, cts_pin, rts_pin);
|
||||
|
||||
uint32_t reg_config = enable_parity ? UART_CONFIG_PARITY : 0;
|
||||
if (rts_pin <= UART_MAX_PIN || cts_pin <= UART_MAX_PIN) {
|
||||
reg_config |= UART_CONFIG_HWFC;
|
||||
}
|
||||
|
||||
UART_CONFIG(uart) = reg_config;
|
||||
uart_set_baudrate(uart, br);
|
||||
}
|
||||
|
||||
/** @brief Select GPIO pins to be used by this peripheral.
|
||||
*
|
||||
* This needs to be configured while UART peripheral is disabled.
|
||||
*
|
||||
* @param[in] uart uart peripheral base.
|
||||
* @param[in] rx RX pin. Use GPIO defines in @ref gpio_pin_id or GPIO_UNCONNECTED
|
||||
* if signal shall not be connected to any pin.
|
||||
* @param[in] tx TX pin. Use GPIO defines in @ref gpio_pin_id or GPIO_UNCONNECTED
|
||||
* if signal shall not be connected to any pin.
|
||||
* @param[in] cts CTS pin. Use GPIO defines in @ref gpio_pin_id or GPIO_UNCONNECTED
|
||||
* if signal shall not be connected to any pin.
|
||||
* @param[in] rts RTS pin. Use GPIO defines in @ref gpio_pin_id or GPIO_UNCONNECTED
|
||||
* if signal shall not be connected to any pin.
|
||||
|
||||
*/
|
||||
void uart_set_pins(uint32_t uart, uint32_t rx, uint32_t tx, uint32_t cts, uint32_t rts)
|
||||
{
|
||||
if (rx != GPIO_UNCONNECTED) {
|
||||
UART_PSELRXD(uart) = __GPIO2PIN(rx);
|
||||
} else {
|
||||
UART_PSELRXD(uart) = rx;
|
||||
}
|
||||
|
||||
if (tx != GPIO_UNCONNECTED) {
|
||||
UART_PSELTXD(uart) = __GPIO2PIN(tx);
|
||||
} else {
|
||||
UART_PSELTXD(uart) = tx;
|
||||
}
|
||||
|
||||
if (cts != GPIO_UNCONNECTED) {
|
||||
UART_PSELCTS(uart) = __GPIO2PIN(cts);
|
||||
} else {
|
||||
UART_PSELCTS(uart) = cts;
|
||||
}
|
||||
|
||||
if (rts != GPIO_UNCONNECTED) {
|
||||
UART_PSELRTS(uart) = __GPIO2PIN(rts);
|
||||
} else {
|
||||
UART_PSELRTS(uart) = rts;
|
||||
}
|
||||
}
|
||||
|
||||
#undef _LOG2
|
||||
|
||||
void uart_set_baudrate(uint32_t uart, enum uart_baud br)
|
||||
{
|
||||
UART_BAUDRATE(uart) = br;
|
||||
}
|
||||
|
||||
void uart_set_parity(uint32_t uart, int parity)
|
||||
{
|
||||
UART_CONFIG(uart) |= parity ? UART_CONFIG_PARITY : 0;
|
||||
}
|
||||
|
||||
void uart_set_flow_control(uint32_t uart, int flow)
|
||||
{
|
||||
UART_CONFIG(uart) |= flow ? UART_CONFIG_HWFC : 0;
|
||||
}
|
||||
|
||||
void uart_start_tx(uint32_t uart)
|
||||
{
|
||||
PERIPH_TRIGGER_TASK(UART_TASK_STARTTX((uart)));
|
||||
}
|
||||
|
||||
void uart_send(uint32_t uart, uint16_t byte)
|
||||
{
|
||||
UART_TXD((uart)) = byte;
|
||||
}
|
||||
|
||||
void uart_stop_tx(uint32_t uart)
|
||||
{
|
||||
PERIPH_TRIGGER_TASK(UART_TASK_STOPTX((uart)));
|
||||
}
|
||||
|
||||
void uart_start_rx(uint32_t uart)
|
||||
{
|
||||
PERIPH_TRIGGER_TASK(UART_TASK_STARTRX((uart)));
|
||||
}
|
||||
|
||||
uint16_t uart_recv(uint32_t uart)
|
||||
{
|
||||
return UART_RXD(uart);
|
||||
}
|
||||
|
||||
void uart_stop_rx(uint32_t uart)
|
||||
{
|
||||
PERIPH_TRIGGER_TASK(UART_TASK_STOPRX((uart)));
|
||||
}
|
||||
/**@}*/
|
||||
|
||||
47
libopencm3/lib/pac55xx/Makefile
Normal file
47
libopencm3/lib/pac55xx/Makefile
Normal file
@@ -0,0 +1,47 @@
|
||||
##
|
||||
## This file is part of the libopencm3 project.
|
||||
##
|
||||
## Copyright (C) 2019 Brian Viele <vielster@allocor.tech>
|
||||
##
|
||||
## 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/>.
|
||||
##
|
||||
## The PAC55xx by Qorvo (formerly ActiveSemi) is a Cortex-M4F based device
|
||||
## which is specialized for motor control and PSC applications.
|
||||
|
||||
LIBNAME = libopencm3_pac55xx
|
||||
SRCLIBDIR ?= ..
|
||||
FP_FLAGS ?= -mfloat-abi=hard -mfpu=fpv4-sp-d16
|
||||
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-m4 -mthumb $(FP_FLAGS) -Wstrict-prototypes \
|
||||
-ffunction-sections -fdata-sections -MD -DPAC55XX
|
||||
TGT_CFLAGS += $(DEBUG_FLAGS)
|
||||
TGT_CFLAGS += $(STANDARD_FLAGS)
|
||||
ARFLAGS = rcs
|
||||
|
||||
OBJS += can.o
|
||||
OBJS += ccs.o
|
||||
OBJS += gpio.o
|
||||
OBJS += memctl.o
|
||||
OBJS += usart.o
|
||||
|
||||
VPATH += ../cm3
|
||||
|
||||
|
||||
include ../Makefile.include
|
||||
460
libopencm3/lib/pac55xx/can.c
Normal file
460
libopencm3/lib/pac55xx/can.c
Normal file
@@ -0,0 +1,460 @@
|
||||
/**
|
||||
* @addtogroup can_api CAN Peripheral API
|
||||
* @ingroup peripheral_apis
|
||||
* @brief <b>PAC55xxxx CAN Driver</b>
|
||||
* @author @htmlonly © @endhtmlonly 2020 Kevin Stefanik <kevin@allocor.tech>
|
||||
* @date February 13, 2020
|
||||
*
|
||||
* This library supports the CAN module in the PAC55xx SoC from Qorvo.
|
||||
*
|
||||
* Note: Acceptance Code Mask Register values of 1 indicate the filter is to
|
||||
* ignore the bit. However, standard CAN driver APIs use a positive logic for the
|
||||
* mask. The implementations in this file inverts masks as appropriate to
|
||||
* the mask to make this more portable/intuitive.
|
||||
*
|
||||
* LGPL License Terms @ref lgpl_license
|
||||
*/
|
||||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <libopencm3/pac55xx/can.h>
|
||||
#include <libopencm3/cm3/common.h>
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief CAN Enable
|
||||
Enable the CAN peripheral and its associated FIFOs/counters/interrupts.
|
||||
@param[in] canport Unsigned int32. CAN block register base address.
|
||||
*/
|
||||
void can_enable(uint32_t canport) {
|
||||
CAN_ISR_SR_CMR_MR_CLEAR(canport, CAN_MR_RM);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief CAN Disable
|
||||
Disable the CAN peripheral and all associated FIFOs/counters/interrupts.
|
||||
@param[in] canport Unsigned int32. CAN block register base address.
|
||||
*/
|
||||
void can_disable(uint32_t canport) {
|
||||
CAN_ISR_SR_CMR_MR_SET(canport, CAN_MR_RM);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief CAN Init
|
||||
Initialize the selected CAN peripheral block.
|
||||
@param[in] canport Unsigned int32. CAN block register base address.
|
||||
@param[in] listen_only bool. Enable listen only mode.
|
||||
@param[in] sjw Unsigned int32. Resynchronization time quanta jump width.
|
||||
@param[in] tseg1 Unsigned int32. Time segment 1 time quanta width.
|
||||
@param[in] tseg2 Unsigned int32. Time segment 2 time quanta width.
|
||||
@param[in] sam3 bool. Use best 2 out of 3 samples.
|
||||
@param[in] brp Unsigned int32. Baud rate prescaler.
|
||||
*/
|
||||
void can_init(uint32_t canport, bool listen_only, uint32_t sjw,
|
||||
uint32_t tseg1, uint32_t tseg2,
|
||||
bool sam3, uint32_t brp) {
|
||||
/* Put CAN module in reset and clear out ISR/SR/CMR/MR */
|
||||
CAN_ISR_SR_CMR_MR(canport) = CAN_MR_RM;
|
||||
/* Setup single filter scheme */
|
||||
CAN_ISR_SR_CMR_MR_SET(canport, CAN_MR_AFM);
|
||||
/* enable listen-only mode */
|
||||
if (listen_only) {
|
||||
CAN_ISR_SR_CMR_MR_SET(canport, CAN_MR_LOM);
|
||||
}
|
||||
|
||||
/* Set Baud Rate Prescaler, sync jump width, tseg1/2 */
|
||||
CAN_BTR1_BTR0_RMC_IMR(canport) = CAN_BTR0_BRP(brp) | CAN_BTR0_SJW(sjw)
|
||||
| CAN_BTR1_TSEG1(tseg1) | CAN_BTR1_TSEG2(tseg2);
|
||||
if (sam3) {
|
||||
/* enable sample bus 3 times */
|
||||
CAN_BTR1_BTR0_RMC_IMR(canport) |= CAN_BTR1_SAM;
|
||||
}
|
||||
|
||||
/* Filter: Accept incoming messages with any identifier */
|
||||
CAN_ACR(canport) = 0;
|
||||
/* Note: when mask bits are 1, the bits are ignored */
|
||||
CAN_AMR(canport) = 0xFFFFFFFFu;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief CAN Filter Clear
|
||||
Clear the message filters to receive all messages.
|
||||
@param[in] canport Unsigned int32. CAN block register base address.
|
||||
*/
|
||||
void can_filter_clear(uint32_t canport) {
|
||||
/* Filter: Accept incoming messages with any identifier */
|
||||
CAN_ACR(canport) = 0;
|
||||
/* Note: when mask bits are 1, the bits are ignored */
|
||||
CAN_AMR(canport) = 0xFFFFFFFFu;
|
||||
/* Setup single filter scheme */
|
||||
CAN_ISR_SR_CMR_MR_SET(canport, CAN_MR_AFM);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief CAN Dual Filter Standard Frame
|
||||
Notes:
|
||||
- Acceptance Code Mask Register values of 1 indicate the filter is to ignore
|
||||
the bit. However standard CAN driver APIs use a positive logic for the mask.
|
||||
So this function inverts the mask to make this more portable/intuitive.
|
||||
- Register definition byte order is opposite what is shown in Rev 1.23 of
|
||||
the PAC55XX Family User Guide. Since both data and ID values cross byte
|
||||
boundaries, the bswap32 function is used to correct for the discrepancy.
|
||||
|
||||
@param[in] canport Unsigned int32. CAN block register base address.
|
||||
@param[in] id1 Unsigned int32. CAN ID 1. Only bits 10:0 are used.
|
||||
@param[in] id1_mask Unsigned int32. CAN ID 1 mask. Only bits 10:0 are used.
|
||||
@param[in] id2 Unsigned int32. CAN ID 2. Only bits 10:0 are used.
|
||||
@param[in] id2_mask Unsigned int32. CAN ID 2 mask. Only bits 10:0 are used.
|
||||
@param[in] db bool. CAN first data byte value.
|
||||
@param[in] db_mask bool. CAN first data byte mask.
|
||||
*/
|
||||
void can_filter_dual(uint32_t canport, uint32_t id1, uint32_t id1_mask,
|
||||
uint32_t id2, uint32_t id2_mask,
|
||||
uint8_t db, uint8_t db_mask) {
|
||||
/* set value */
|
||||
uint32_t word = ((id1 << 21) & CAN_ACR_DUAL_ID1)
|
||||
| ((id2 << 5) & CAN_ACR_DUAL_ID2)
|
||||
| ((db << 12) & CAN_ACR_DUAL_DB_UPPER) | (db & CAN_ACR_DUAL_DB_LOWER);
|
||||
CAN_ACR(canport) = __builtin_bswap32(word);
|
||||
/* set mask */
|
||||
word = ((~id1_mask << 21) & CAN_ACR_DUAL_ID1)
|
||||
| ((~id2_mask << 5) & CAN_ACR_DUAL_ID2)
|
||||
| ((~db_mask << 12) & CAN_ACR_DUAL_DB_UPPER)
|
||||
| ((~db_mask) & CAN_ACR_DUAL_DB_LOWER)
|
||||
| CAN_ACR_DUAL_RTR1 | CAN_ACR_DUAL_RTR2;
|
||||
CAN_AMR(canport) = __builtin_bswap32(word);
|
||||
/* 0: dual filter */
|
||||
CAN_ISR_SR_CMR_MR_CLEAR(canport, CAN_MR_AFM);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief CAN Filter Single Standard Frame
|
||||
Notes:
|
||||
- Acceptance Code Mask Register values of 1 indicate the filter is to ignore
|
||||
the bit. However standard CAN driver APIs use a positive logic for the mask.
|
||||
So this function inverts the mask to make this more portable/intuitive.
|
||||
- Register definition byte order is opposite what is shown in Rev 1.23 of
|
||||
the PAC55XX Family User Guide. Since both data and ID values cross byte
|
||||
boundaries, the bswap32 function is used to correct for the discrepancy.
|
||||
|
||||
@param[in] canport Unsigned int32. CAN block register base address.
|
||||
@param[in] id Unsigned int32. CAN ID. Only bits 10:0 are used.
|
||||
@param[in] id_mask Unsigned int32. CAN ID mask. Only bits 10:0 are used.
|
||||
@param[in] db1 bool. CAN first data byte value.
|
||||
@param[in] db1_mask bool. CAN first data byte mask.
|
||||
@param[in] db2 bool. CAN second data byte value.
|
||||
@param[in] db2_mask bool. CAN second data byte mask.
|
||||
*/
|
||||
void can_filter_single_std(uint32_t canport, uint32_t id, uint32_t id_mask,
|
||||
uint8_t db1, uint8_t db1_mask,
|
||||
uint8_t db2, uint8_t db2_mask) {
|
||||
/* set value */
|
||||
uint32_t word = ((id << 21) & CAN_ACR_SINGLE_STD_ID)
|
||||
| ((db1 << 8) & CAN_ACR_SINGLE_STD_DB1)
|
||||
| ((db2 << 0) & CAN_ACR_SINGLE_STD_DB2);
|
||||
CAN_ACR(canport) = __builtin_bswap32(word);
|
||||
/* set mask */
|
||||
word = ((~id_mask << 21) & CAN_ACR_SINGLE_STD_ID)
|
||||
| CAN_ACR_SINGLE_STD_RTR | CAN_ACR_DUAL_DB_UPPER
|
||||
| ((~db1_mask << 8) & CAN_ACR_SINGLE_STD_DB1)
|
||||
| ((~db2_mask << 0) & CAN_ACR_SINGLE_STD_DB2);
|
||||
CAN_AMR(canport) = __builtin_bswap32(word);
|
||||
/* 1: single filter */
|
||||
CAN_ISR_SR_CMR_MR_SET(canport, CAN_MR_AFM);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief CAN Filter Single Standard Frame w/RTR set
|
||||
Notes:
|
||||
- Acceptance Code Mask Register values of 1 indicate the filter is to ignore
|
||||
the bit. However standard CAN driver APIs use a positive logic for the mask.
|
||||
So this function inverts the mask to make this more portable/intuitive.
|
||||
- Register definition byte order is opposite what is shown in Rev 1.23 of
|
||||
the PAC55XX Family User Guide. Since both data and ID values cross byte
|
||||
boundaries, the bswap32 function is used to correct for the discrepancy.
|
||||
|
||||
@param[in] canport Unsigned int32. CAN block register base address.
|
||||
@param[in] id Unsigned int32. CAN ID. Only bits 10:0 are used.
|
||||
@param[in] id_mask Unsigned int32. CAN ID mask. Only bits 10:0 are used.
|
||||
@param[in] db1 bool. CAN first data byte value.
|
||||
@param[in] db1_mask bool. CAN first data byte mask.
|
||||
@param[in] db2 bool. CAN second data byte value.
|
||||
@param[in] db2_mask bool. CAN second data byte mask.
|
||||
*/
|
||||
void can_filter_single_std_rtr(uint32_t canport, uint32_t id, uint32_t id_mask,
|
||||
uint8_t db1, uint8_t db1_mask,
|
||||
uint8_t db2, uint8_t db2_mask) {
|
||||
/* set value */
|
||||
uint32_t word = ((id << 21) & CAN_ACR_SINGLE_STD_ID)
|
||||
| CAN_ACR_SINGLE_STD_RTR | ((db1 << 8) & CAN_ACR_SINGLE_STD_DB1)
|
||||
| ((db2 << 0) & CAN_ACR_SINGLE_STD_DB2);
|
||||
CAN_ACR(canport) = __builtin_bswap32(word);
|
||||
/* set mask */
|
||||
word = ((~id_mask << 21) & CAN_ACR_SINGLE_STD_ID)
|
||||
| ((~db1_mask << 8) & CAN_ACR_SINGLE_STD_DB1)
|
||||
| ((~db2_mask << 0) & CAN_ACR_SINGLE_STD_DB2);
|
||||
CAN_AMR(canport) = __builtin_bswap32(word);
|
||||
/* 1: single filter */
|
||||
CAN_ISR_SR_CMR_MR_SET(canport, CAN_MR_AFM);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief CAN Filter Single Extended Frame
|
||||
Notes:
|
||||
- Acceptance Code Mask Register values of 1 indicate the filter is to ignore
|
||||
the bit. However standard CAN driver APIs use a positive logic for the mask.
|
||||
So this function inverts the mask to make this more portable/intuitive.
|
||||
- Register definition byte order is opposite what is shown in Rev 1.23 of
|
||||
the PAC55XX Family User Guide. Since both data and ID values cross byte
|
||||
boundaries, the bswap32 function is used to correct for the discrepancy.
|
||||
|
||||
@param[in] canport Unsigned int32. CAN block register base address.
|
||||
@param[in] id Unsigned int32. CAN ID. Only bits 28:0 are used.
|
||||
@param[in] id_mask Unsigned int32. CAN ID mask. Only bits 28:0 are used.
|
||||
*/
|
||||
void can_filter_single_ext(uint32_t canport, uint32_t id, uint32_t id_mask) {
|
||||
/* set value */
|
||||
uint32_t word = ((id << 3) & CAN_ACR_SINGLE_EXT_ID);
|
||||
CAN_ACR(canport) = __builtin_bswap32(word);
|
||||
/* set mask */
|
||||
word = ((~id_mask << 3) & CAN_ACR_SINGLE_EXT_ID) | CAN_ACR_SINGLE_EXT_RTR;
|
||||
CAN_AMR(canport) = __builtin_bswap32(word);
|
||||
/* 1: single filter */
|
||||
CAN_ISR_SR_CMR_MR_SET(canport, CAN_MR_AFM);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief CAN Filter Single Extended Frame w/RTR set
|
||||
Notes:
|
||||
- Acceptance Code Mask Register values of 1 indicate the filter is to ignore
|
||||
the bit. However standard CAN driver APIs use a positive logic for the mask.
|
||||
So this function inverts the mask to make this more portable/intuitive.
|
||||
- Register definition byte order is opposite what is shown in Rev 1.23 of
|
||||
the PAC55XX Family User Guide. Since both data and ID values cross byte
|
||||
boundaries, the bswap32 function is used to correct for the discrepancy.
|
||||
|
||||
@param[in] canport Unsigned int32. CAN block register base address.
|
||||
@param[in] id Unsigned int32. CAN ID. Only bits 28:0 are used.
|
||||
@param[in] id_mask Unsigned int32. CAN ID mask. Only bits 28:0 are used.
|
||||
*/
|
||||
void can_filter_single_ext_rtr(uint32_t canport, uint32_t id, uint32_t id_mask) {
|
||||
/* set value */
|
||||
uint32_t word = ((id << 3) & CAN_ACR_SINGLE_EXT_ID) | CAN_ACR_SINGLE_EXT_RTR;
|
||||
CAN_ACR(canport) = __builtin_bswap32(word);
|
||||
/* set mask */
|
||||
word = ((~id_mask << 3) & CAN_ACR_SINGLE_EXT_ID);
|
||||
CAN_AMR(canport) = __builtin_bswap32(word);
|
||||
/* 1: single filter */
|
||||
CAN_ISR_SR_CMR_MR_SET(canport, CAN_MR_AFM);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief CAN Enable IRQ
|
||||
@param[in] canport Unsigned int32. CAN block register base address.
|
||||
@param[in] irq Unsigned int8. IRQ bit(s).
|
||||
*/
|
||||
void can_enable_irq(uint32_t canport, uint8_t irq) {
|
||||
/* set to 1 (not masked) to enable */
|
||||
CAN_BTR1_BTR0_RMC_IMR(canport) |= (uint32_t)irq;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief CAN Disable IRQ
|
||||
@param[in] canport Unsigned int32. CAN block register base address.
|
||||
@param[in] irq Unsigned int8. IRQ bit(s).
|
||||
*/
|
||||
void can_disable_irq(uint32_t canport, uint8_t irq) {
|
||||
/* set to 0 (masked) to disable */
|
||||
CAN_BTR1_BTR0_RMC_IMR(canport) &= ~(uint32_t)irq;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief CAN Transmit Standard Frame
|
||||
@param[in] canport Unsigned int32. CAN block register base address.
|
||||
@param[in] id Unsigned int32. Message ID bits 10:0 used.
|
||||
@param[in] rtr bool. Remote Request bit value.
|
||||
@param[in] length Unsigned int8. Message payload length.
|
||||
@param[in] data Unsigned int8[]. Message payload data.
|
||||
@returns true if able to transmit, false otherwise.
|
||||
*/
|
||||
bool can_transmit_std(uint32_t canport, uint32_t id, bool rtr, uint8_t length,
|
||||
const uint8_t *data) {
|
||||
/* if TBS is 0, then not ready to transmit */
|
||||
if ((CAN_ISR_SR_CMR_MR(canport) & CAN_SR_TBS) == 0) {
|
||||
return false;
|
||||
}
|
||||
uint32_t word = (length & CAN_BITS_3_0)
|
||||
| (rtr ? BIT6 : 0) /* DLC/RTR/FF ==> 7:0 */
|
||||
| ((id & CAN_BITS_10_3) << 5) /* ID 10:3 ==> 15:8 */
|
||||
| ((id & CAN_BITS_2_0) << 21) /* ID 2:0 ==> 23:21 */
|
||||
| (((length > 0) ? data[0] : 0) << 24);
|
||||
CAN_TXBUF(canport) = word;
|
||||
|
||||
if (length > 1) {
|
||||
word = (data[1] << 0) | (data[2] << 8)
|
||||
| (data[3] << 16) | (data[4] << 24);
|
||||
CAN_TXBUF(canport) = word;
|
||||
}
|
||||
|
||||
if (length > 5) {
|
||||
word = (data[5] << 0) | (data[6] << 8) | (data[7] << 16);
|
||||
CAN_TXBUF(canport) = word;
|
||||
}
|
||||
|
||||
/* Request transmit */
|
||||
CAN_ISR_SR_CMR_MR_SET(canport, CAN_CMR_TR);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief CAN Transmit Extended Frame
|
||||
@param[in] canport Unsigned int32. CAN block register base address.
|
||||
@param[in] id Unsigned int32. Message ID bits 28:0 used.
|
||||
@param[in] rtr bool. Remote Request bit value.
|
||||
@param[in] length Unsigned int8. Message payload length, 0-8.
|
||||
@param[in] data Unsigned int8[]. Message payload data.
|
||||
@returns true if able to transmit, false otherwise.
|
||||
*/
|
||||
bool can_transmit_ext(uint32_t canport, uint32_t id, bool rtr, uint8_t length,
|
||||
const uint8_t *data) {
|
||||
/* if TBS is 0, then not ready to transmit */
|
||||
if ((CAN_ISR_SR_CMR_MR(canport) & CAN_SR_TBS) == 0) {
|
||||
return false;
|
||||
}
|
||||
uint32_t word = (length & CAN_BITS_3_0)
|
||||
| (rtr ? BIT6 : 0) | BIT7 /* DLC/RTR/FF ==> 7:0 */
|
||||
| ((id & CAN_BITS_28_21) >> 13) /* ID 28:21 ==> 15:8 */
|
||||
| ((id & CAN_BITS_20_13) << 3) /* ID 20:13 ==> 23:16 */
|
||||
| ((id & CAN_BITS_12_5) << 19); /* ID 12:5 ==> 31:24 */
|
||||
CAN_TXBUF(canport) = word; /* write first 32-bit word to FIFO */
|
||||
|
||||
word = ((id & CAN_BITS_4_0) << 3); /* ID 4:0 ==> 7:3 */
|
||||
if (length > 0) {
|
||||
word |= (data[0] << 8) | (data[1] << 16) | (data[2] << 24);
|
||||
}
|
||||
/* for extended frame, always write second 32-bit word to FIFO */
|
||||
CAN_TXBUF(canport) = word;
|
||||
if (length > 3) {
|
||||
word = (data[3] << 0) | (data[4] << 8)
|
||||
| (data[5] << 16) | (data[6] << 24);
|
||||
CAN_TXBUF(canport) = word;
|
||||
}
|
||||
if (length > 7) {
|
||||
word = data[7];
|
||||
CAN_TXBUF(canport) = word;
|
||||
}
|
||||
/* Request transmit */
|
||||
CAN_ISR_SR_CMR_MR_SET(canport, CAN_CMR_TR);
|
||||
return true;
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief CAN Abort Transmit
|
||||
Aborts the current transmission.
|
||||
|
||||
@param[in] canport Unsigned int32. CAN block register base address.
|
||||
*/
|
||||
void can_abort_transmit(uint32_t canport) {
|
||||
CAN_ISR_SR_CMR_MR_SET(canport, CAN_CMR_AT);
|
||||
}
|
||||
|
||||
/*---------------------------------------------------------------------------*/
|
||||
/** @brief CAN Receive Message
|
||||
If no data is in the RX buffer, id and length are set to 0.
|
||||
|
||||
@param[in] canport Unsigned int32. CAN block register base address.
|
||||
@param[out] id Unsigned int32 pointer. Message ID.
|
||||
@param[out] ext bool pointer. The message ID is extended.
|
||||
@param[out] rtr bool pointer. Remote Request bit value.
|
||||
@param[out] length Unsigned int8 pointer. Length of message payload.
|
||||
@param[out] data Unsigned int8[]. Message payload data, min length 8.
|
||||
*/
|
||||
void can_receive(uint32_t canport, uint32_t *id, bool *ext, bool *rtr, uint8_t *length,
|
||||
uint8_t *data) {
|
||||
if ((CAN_ISR_SR_CMR_MR(canport) & CAN_ISR_RI) == 0 || CAN_RMC(canport) == 0) {
|
||||
*id = 0;
|
||||
*length = 0;
|
||||
return; /* empty RX FIFO */
|
||||
}
|
||||
uint32_t can_buffer = CAN_RXBUF(canport); /* read 32-bit word */
|
||||
uint8_t rx_length = can_buffer & CAN_BITS_3_0;
|
||||
bool is_extended = can_buffer & BIT7;
|
||||
if (ext) {
|
||||
*ext = is_extended;
|
||||
}
|
||||
if (rtr) {
|
||||
*rtr = can_buffer & BIT6;
|
||||
}
|
||||
if (length) {
|
||||
*length = rx_length;
|
||||
}
|
||||
uint32_t _id;
|
||||
if (is_extended) {
|
||||
/* Parse extended message ID from RXBUF */
|
||||
_id = ((can_buffer & CAN_BITS_15_8) << 13) /* ID 28:21 <== 15:8 */
|
||||
| ((can_buffer & CAN_BITS_23_16) >> 3) /* ID 20:13 <== 23:16 */
|
||||
| ((can_buffer & CAN_BITS_31_24) >> 19); /* ID 12:5 <== 31:24 */
|
||||
can_buffer = CAN_RXBUF(canport);
|
||||
_id |= ((can_buffer & CAN_BITS_7_3) >> 3); /* ID 4:0 <== 7:3 */
|
||||
|
||||
/* Parse extended message data from RXBUF */
|
||||
data[0] = can_buffer >> 8;
|
||||
data[1] = can_buffer >> 16;
|
||||
data[2] = can_buffer >> 24;
|
||||
if (rx_length > 3) {
|
||||
can_buffer = CAN_RXBUF(canport);
|
||||
data[3] = can_buffer;
|
||||
data[4] = can_buffer >> 8;
|
||||
data[5] = can_buffer >> 16;
|
||||
data[6] = can_buffer >> 24;
|
||||
}
|
||||
if (rx_length > 7) {
|
||||
can_buffer = CAN_RXBUF(canport);
|
||||
data[7] = can_buffer;
|
||||
}
|
||||
} else {
|
||||
/* Parse standard message ID from RXBUF */
|
||||
_id = ((can_buffer & CAN_BITS_15_8) >> 5) /* ID 10:3 <== 15:8 */
|
||||
| ((can_buffer & CAN_BITS_23_21) >> 21); /* ID 2:0 <== 23:21 */
|
||||
/* Parse standard message data from RXBUF */
|
||||
data[0] = can_buffer >> 24;
|
||||
if (rx_length > 1) {
|
||||
can_buffer = CAN_RXBUF(canport);
|
||||
data[1] = can_buffer;
|
||||
data[2] = can_buffer >> 8;
|
||||
data[3] = can_buffer >> 16;
|
||||
data[4] = can_buffer >> 24;
|
||||
if (rx_length > 5) {
|
||||
/* buffer contains data5,data6,data7 */
|
||||
can_buffer = CAN_RXBUF(canport);
|
||||
data[5] = can_buffer;
|
||||
data[6] = can_buffer >> 8;
|
||||
data[7] = can_buffer >> 16;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (id) {
|
||||
*id = _id;
|
||||
}
|
||||
|
||||
/*
|
||||
* Write 1 to acknowledge/clear the interrupt
|
||||
* Note: ensure not to let the other interrupt masks be written as 1, so as
|
||||
* to avoid acknowledging them.
|
||||
* Note: CAN_ISR_RI is already high, but we still write '1' to it to clear it.
|
||||
*/
|
||||
CAN_ISR_ACKNOWLEDGE(canport, CAN_ISR_RI);
|
||||
return;
|
||||
}
|
||||
261
libopencm3/lib/pac55xx/ccs.c
Normal file
261
libopencm3/lib/pac55xx/ccs.c
Normal file
@@ -0,0 +1,261 @@
|
||||
/**
|
||||
* @brief <b>PAC55xxxx CCS Driver</b>
|
||||
* @author @htmlonly © @endhtmlonly 2020 Kevin Stefanik <kevin@allocor.tech>
|
||||
* @date March 7, 2020
|
||||
*
|
||||
* This library supports the CCS module in the PAC55xx SoC from Qorvo.
|
||||
*
|
||||
* LGPL License Terms @ref lgpl_license
|
||||
*/
|
||||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <libopencm3/pac55xx/ccs.h>
|
||||
#include <libopencm3/pac55xx/memorymap.h>
|
||||
#include <libopencm3/pac55xx/memctl.h>
|
||||
#include <libopencm3/cm3/assert.h>
|
||||
|
||||
static volatile uint32_t ccs_extclk_frequency = 0;
|
||||
static volatile uint32_t ccs_frclk_frequency = CCS_ROSC_FREQ;
|
||||
static volatile uint32_t ccs_sclk_frequency = CCS_ROSC_FREQ;
|
||||
static volatile uint32_t ccs_pll_clk_frequency = 0;
|
||||
static volatile uint32_t ccs_hclk_frequency = CCS_ROSC_FREQ;
|
||||
static volatile uint32_t ccs_aclk_frequency = CCS_ROSC_FREQ;
|
||||
static volatile uint32_t ccs_pclk_frequency = CCS_ROSC_FREQ;
|
||||
|
||||
void ccs_frclkmux_select(uint32_t sel) {
|
||||
CCSCTL = (CCSCTL & ~CCS_CTL_FRCLKMUXSEL(CCS_CTL_FRCLKMUXSEL_MASK)) | CCS_CTL_FRCLKMUXSEL(sel);
|
||||
}
|
||||
void ccs_rosc_enable(void) {
|
||||
CCSCTL |= CCS_CTL_ROSCEN;
|
||||
}
|
||||
void ccs_rosc_disable(void) {
|
||||
CCSCTL &= ~CCS_CTL_ROSCEN;
|
||||
}
|
||||
void ccs_sclkmux_select_frclk(void) {
|
||||
CCSCTL &= ~CCS_CTL_SCLKMUXSEL;
|
||||
}
|
||||
void ccs_sclkmux_select_pllclk(void) {
|
||||
CCSCTL |= CCS_CTL_SCLKMUXSEL;
|
||||
}
|
||||
void ccs_clkfail_enable(void) {
|
||||
CCSCTL |= CCS_CTL_CLKFAILEN;
|
||||
}
|
||||
void ccs_clkfail_disable(void) {
|
||||
CCSCTL &= ~CCS_CTL_CLKFAILEN;
|
||||
}
|
||||
void ccs_clkfailmux_select_frclk(void) {
|
||||
CCSCTL &= ~CCS_CTL_CLKFAILMUXSEL;
|
||||
}
|
||||
void ccs_clkfailmux_select_pllclk(void) {
|
||||
CCSCTL |= CCS_CTL_CLKFAILMUXSEL;
|
||||
}
|
||||
void ccs_ldo_enable(void) {
|
||||
CCSCTL |= CCS_CTL_LDOEN;
|
||||
}
|
||||
void ccs_ldo_disable(void) {
|
||||
CCSCTL &= ~CCS_CTL_LDOEN;
|
||||
}
|
||||
void ccs_pclk_enable(void) {
|
||||
CCSCTL |= CCS_CTL_PCLKEN;
|
||||
}
|
||||
void ccs_pclk_disable(void) {
|
||||
CCSCTL &= ~CCS_CTL_PCLKEN;
|
||||
}
|
||||
void ccs_aclk_enable(void) {
|
||||
CCSCTL |= CCS_CTL_ACLKEN;
|
||||
}
|
||||
void ccs_aclk_disable(void) {
|
||||
CCSCTL &= ~CCS_CTL_ACLKEN;
|
||||
}
|
||||
void ccs_adcclk_enable(void) {
|
||||
CCSCTL |= CCS_CTL_ADCCLKEN;
|
||||
}
|
||||
void ccs_adcclk_disable(void) {
|
||||
CCSCTL &= ~CCS_CTL_ADCCLKEN;
|
||||
}
|
||||
void ccs_stclk_sleep_enable(void) {
|
||||
CCSCTL |= CCS_CTL_STCLKSLPEN;
|
||||
}
|
||||
void ccs_stclk_sleep_disable(void) {
|
||||
CCSCTL &= ~CCS_CTL_STCLKSLPEN;
|
||||
}
|
||||
void ccs_set_pclkdiv(uint32_t div) {
|
||||
CCSCTL = (CCSCTL & ~CCS_CTL_PCLKDIV(8)) | CCS_CTL_PCLKDIV(div);
|
||||
}
|
||||
void ccs_set_aclkdiv(uint32_t div) {
|
||||
CCSCTL = (CCSCTL & ~CCS_CTL_ACLKDIV(8)) | CCS_CTL_ACLKDIV(div);
|
||||
}
|
||||
void ccs_set_hclkdiv(uint32_t div) {
|
||||
CCSCTL = (CCSCTL & ~CCS_CTL_HCLKDIV(8)) | CCS_CTL_HCLKDIV(div);
|
||||
}
|
||||
void ccs_pll_enable(void) {
|
||||
CCSPLLCTL |= CCS_PLLCTL_PLLEN;
|
||||
}
|
||||
void ccs_pll_disable(void) {
|
||||
CCSPLLCTL &= ~CCS_PLLCTL_PLLEN;
|
||||
}
|
||||
bool ccs_pll_locked(void) {
|
||||
return (CCSPLLCTL & CCS_PLLCTL_PLLLOCK) == CCS_PLLCTL_PLLLOCK;
|
||||
}
|
||||
void ccs_pll_bypass_enable(void) {
|
||||
CCSPLLCTL |= CCS_PLLCTL_PLLBP;
|
||||
}
|
||||
void ccs_pll_bypass_disable(void) {
|
||||
CCSPLLCTL &= ~CCS_PLLCTL_PLLBP;
|
||||
}
|
||||
void ccs_pll_set_outdiv(uint32_t div) {
|
||||
CCSPLLCTL = (CCSPLLCTL & ~CCS_PLLCTL_PLLOUTDIV(CCS_PLLCTL_PLLOUTDIV_MASK)) | CCS_PLLCTL_PLLOUTDIV(div);
|
||||
}
|
||||
void ccs_pll_set_indiv(uint32_t div) {
|
||||
if (div <= 15 && div >= 1) {
|
||||
CCSPLLCTL = (CCSPLLCTL & ~CCS_PLLCTL_PLLINDIV(CCS_PLLCTL_PLLINDIV_MASK)) | CCS_PLLCTL_PLLINDIV(div);
|
||||
} else {
|
||||
cm3_assert_not_reached();
|
||||
}
|
||||
}
|
||||
void ccs_pll_set_fbdiv(uint32_t div) {
|
||||
if (div <= 16383 && div >= 4) {
|
||||
CCSPLLCTL = (CCSPLLCTL & ~CCS_PLLCTL_PLLFBDIV(CCS_PLLCTL_PLLFBDIV_MASK)) | CCS_PLLCTL_PLLFBDIV(div);
|
||||
} else {
|
||||
cm3_assert_not_reached();
|
||||
}
|
||||
}
|
||||
void css_pll_config_enable(uint32_t indiv, uint32_t fbdiv, uint32_t outdiv) {
|
||||
ccs_pll_disable();
|
||||
ccs_pll_set_fbdiv(fbdiv);
|
||||
ccs_pll_set_outdiv(outdiv);
|
||||
ccs_pll_set_indiv(indiv);
|
||||
ccs_pll_enable();
|
||||
while (!ccs_pll_locked()) ; /* Wait for PLL lock ~500us */
|
||||
}
|
||||
uint32_t ccs_get_peripheral_clk_freq(uint32_t periph, uint32_t select) {
|
||||
switch (periph) {
|
||||
case ADC_BASE:
|
||||
return ccs_sclk_frequency;
|
||||
case I2C_BASE: /* fall through */
|
||||
case USARTA_BASE: /* fall through */
|
||||
case USARTB_BASE: /* fall through */
|
||||
case USARTC_BASE: /* fall through */
|
||||
case USARTD_BASE: /* fall through */
|
||||
case CAN_BASE: /* fall through */
|
||||
case GPTIMERA_BASE: /* fall through */
|
||||
case GPTIMERB_BASE:
|
||||
return ccs_pclk_frequency;
|
||||
case TIMERA_BASE: /* fall through */
|
||||
case TIMERB_BASE: /* fall through */
|
||||
case TIMERC_BASE: /* fall through */
|
||||
case TIMERD_BASE:
|
||||
return (select == 0) ? ccs_pclk_frequency : ccs_aclk_frequency;
|
||||
case MEMCTL_BASE:
|
||||
return (select == 0) ? CCS_ROSC_FREQ : ccs_hclk_frequency;
|
||||
case WWDT_BASE:
|
||||
return (select == 0) ? ccs_frclk_frequency : CCS_ROSC_FREQ;
|
||||
case RTC_BASE:
|
||||
return ccs_frclk_frequency;
|
||||
case CRC_BASE: /* fall through */
|
||||
case SYS_TICK_BASE:
|
||||
return ccs_hclk_frequency;
|
||||
default:
|
||||
cm3_assert_not_reached();
|
||||
}
|
||||
}
|
||||
|
||||
void ccs_reset_clocks(void) {
|
||||
CCSCTL = CCS_CTL_LDOEN | CCS_CTL_ROSCEN |
|
||||
CCS_CTL_PCLKEN | CCS_CTL_ACLKEN |
|
||||
CCS_CTL_ADCCLKEN | CCS_CTL_STCLKSLPEN;
|
||||
CCSPLLCTL = 0;
|
||||
}
|
||||
|
||||
void ccs_configure_clocks(const struct ccs_clk_config *config) {
|
||||
MEMCTL_FLASHLOCK = MEMCTL_FLASHLOCK_ALLOW_MEMCTL_WRITE;
|
||||
|
||||
ccs_reset_clocks(); /* set safe defaults */
|
||||
ccs_frclkmux_select(CCS_CTL_FRCLKMUXSEL_ROSC);
|
||||
ccs_sclkmux_select_frclk();
|
||||
memctl_flash_select_roscclk();
|
||||
|
||||
if (config->mem_enable_cache) {
|
||||
memctl_flash_cache_enable();
|
||||
} else {
|
||||
memctl_flash_cache_disable();
|
||||
}
|
||||
|
||||
ccs_frclkmux_select(CCS_CTL_FRCLKMUXSEL_CLKREF); /* switch frclk to 4MHz CLKREF */
|
||||
|
||||
switch (config->frclk_source) {
|
||||
case CCS_CTL_FRCLKMUXSEL_ROSC:
|
||||
ccs_frclkmux_select(CCS_CTL_FRCLKMUXSEL_ROSC);
|
||||
ccs_frclk_frequency = CCS_ROSC_FREQ;
|
||||
break;
|
||||
case CCS_CTL_FRCLKMUXSEL_CLKREF:
|
||||
ccs_frclkmux_select(CCS_CTL_FRCLKMUXSEL_CLKREF);
|
||||
ccs_frclk_frequency = CCS_CLKREF_FREQ;
|
||||
break;
|
||||
case CCS_CTL_FRCLKMUXSEL_EXTCLK:
|
||||
if (config->extclk_frequency > CCS_EXTCLK_MAX_FREQ
|
||||
|| config->extclk_frequency == 0) {
|
||||
cm3_assert_not_reached();
|
||||
}
|
||||
ccs_frclkmux_select(CCS_CTL_FRCLKMUXSEL_EXTCLK);
|
||||
ccs_frclk_frequency = ccs_extclk_frequency = config->extclk_frequency;
|
||||
break;
|
||||
default:
|
||||
cm3_assert_not_reached();
|
||||
}
|
||||
|
||||
if (config->sclk_source == CCS_CTL_SCLKMUXSEL_FRCLK) {
|
||||
ccs_set_hclkdiv(config->hclkdiv);
|
||||
ccs_set_aclkdiv(config->aclkdiv);
|
||||
memctl_flash_set_wstate(config->mem_wstate);
|
||||
ccs_sclkmux_select_frclk();
|
||||
memctl_flash_set_mclkdiv(config->mem_mclkdiv);
|
||||
if (config->mem_mclksel == false) {
|
||||
memctl_flash_select_roscclk();
|
||||
} else {
|
||||
memctl_flash_select_mclk();
|
||||
}
|
||||
ccs_sclk_frequency = ccs_frclk_frequency;
|
||||
} else if (config->sclk_source == CCS_CTL_SCLKMUXSEL_PLLCLK) {
|
||||
css_pll_config_enable(config->pll_indiv, config->pll_fbdiv, config->pll_outdiv);
|
||||
ccs_set_hclkdiv(config->hclkdiv);
|
||||
ccs_set_aclkdiv(config->aclkdiv);
|
||||
memctl_flash_set_wstate(config->mem_wstate);
|
||||
ccs_sclkmux_select_pllclk();
|
||||
memctl_flash_set_mclkdiv(config->mem_mclkdiv);
|
||||
if (config->mem_mclksel == false) {
|
||||
memctl_flash_select_roscclk();
|
||||
} else {
|
||||
memctl_flash_select_mclk();
|
||||
}
|
||||
ccs_pll_clk_frequency = ((ccs_frclk_frequency * config->pll_fbdiv) / config->pll_indiv) >> config->pll_outdiv;
|
||||
ccs_sclk_frequency = ccs_pll_clk_frequency;
|
||||
} else {
|
||||
cm3_assert_not_reached();
|
||||
}
|
||||
ccs_set_pclkdiv(config->pclkdiv);
|
||||
ccs_pclk_enable();
|
||||
ccs_aclk_enable();
|
||||
ccs_adcclk_enable();
|
||||
ccs_stclk_sleep_disable();
|
||||
|
||||
ccs_hclk_frequency = ccs_sclk_frequency / config->hclkdiv;
|
||||
ccs_aclk_frequency = ccs_sclk_frequency / config->aclkdiv;
|
||||
ccs_pclk_frequency = ccs_hclk_frequency / config->pclkdiv;
|
||||
|
||||
MEMCTL_FLASHLOCK = MEMCTL_FLASHLOCK_CLEAR;
|
||||
}
|
||||
163
libopencm3/lib/pac55xx/gpio.c
Normal file
163
libopencm3/lib/pac55xx/gpio.c
Normal file
@@ -0,0 +1,163 @@
|
||||
/**
|
||||
* @ingroup PAC55xx_gpio
|
||||
* @brief <b>PAC55xxxx General-Purpose Input/Output (GPIO)</b>
|
||||
* @author @htmlonly © @endhtmlonly 2019 Brian Viele <vielster@allocor.tech>
|
||||
* @date December 1, 2019
|
||||
*
|
||||
* This library supports the GPIO module in the PAC55xx SoC from Qorvo.
|
||||
*
|
||||
* LGPL License Terms @ref lgpl_license
|
||||
*/
|
||||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <libopencm3/pac55xx/gpio.h>
|
||||
|
||||
static uint32_t get_ccs_port_base(uint32_t gpioport) {
|
||||
switch (gpioport) {
|
||||
case GPIOA:
|
||||
return CCS_PORTA;
|
||||
case GPIOB:
|
||||
return CCS_PORTB;
|
||||
case GPIOC:
|
||||
return CCS_PORTC;
|
||||
case GPIOD:
|
||||
return CCS_PORTD;
|
||||
case GPIOE:
|
||||
return CCS_PORTE;
|
||||
case GPIOF:
|
||||
return CCS_PORTF;
|
||||
case GPIOG:
|
||||
return CCS_PORTG;
|
||||
default:
|
||||
return 0U;
|
||||
}
|
||||
}
|
||||
|
||||
void gpio_mode_setup(uint32_t gpioport, gpio_mode_t mode,
|
||||
ccs_pull_updown_t pull_up_down, uint16_t gpios) {
|
||||
/* Read the current value of the register. */
|
||||
uint32_t reg = GPIO_MODER(gpioport);
|
||||
uint32_t port = get_ccs_port_base(gpioport);
|
||||
|
||||
/* Loop through only set bits, utilize built-ins for optimized assembly. */
|
||||
int ffs = __builtin_ffs(gpios);
|
||||
while (ffs) {
|
||||
const int pin = ffs - 1;
|
||||
const int bit = (1 << pin);
|
||||
|
||||
/* Update the cached mode value by clearing then setting values. */
|
||||
reg &= ~GPIO_MODER_MASK_PIN(pin);
|
||||
reg |= GPIO_MODER_MODE(pin, mode);
|
||||
|
||||
/* Set the pinmux configurations for the pull-up / pull-down. */
|
||||
if (pull_up_down == CCS_IO_PULL_UP) {
|
||||
CCS_PDENR(port) &= ~bit;
|
||||
CCS_PUENR(port) |= bit;
|
||||
} else if (pull_up_down == CCS_IO_PULL_DOWN) {
|
||||
CCS_PUENR(port) &= ~bit;
|
||||
CCS_PDENR(port) |= bit;
|
||||
} else {
|
||||
CCS_PDENR(port) &= ~bit;
|
||||
CCS_PUENR(port) &= ~bit;
|
||||
}
|
||||
gpios ^= bit; /* Clear the bit we just serviced. */
|
||||
ffs = __builtin_ffs(gpios);
|
||||
}
|
||||
GPIO_MODER(gpioport) = reg;
|
||||
}
|
||||
|
||||
void gpio_set_outmask(uint32_t gpioport, bool enable, uint16_t gpios) {
|
||||
uint32_t reg = GPIO_OUTMASKR(gpioport);
|
||||
if (enable) {
|
||||
reg |= gpios;
|
||||
} else {
|
||||
reg &= ~gpios;
|
||||
}
|
||||
GPIO_OUTMASKR(gpioport) = reg;
|
||||
}
|
||||
|
||||
void gpio_set(uint32_t gpioport, uint16_t gpios) {
|
||||
GPIO_DOSETR(gpioport) = gpios;
|
||||
}
|
||||
|
||||
void gpio_clear(uint32_t gpioport, uint16_t gpios) {
|
||||
GPIO_DOCLEARR(gpioport) = gpios;
|
||||
}
|
||||
|
||||
uint16_t gpio_get(uint32_t gpioport, uint16_t gpios) {
|
||||
return GPIO_INR(gpioport) & gpios;
|
||||
}
|
||||
|
||||
void gpio_set_af(uint32_t gpioport, ccs_muxsel_func_t muxsel, uint16_t gpios) {
|
||||
uint32_t port = get_ccs_port_base(gpioport);
|
||||
|
||||
/* Update each of the pin configs. */
|
||||
uint32_t reg = CCS_MUXSELR(port);
|
||||
int ffs = __builtin_ffs(gpios);
|
||||
while (ffs) {
|
||||
const int pin = ffs - 1;
|
||||
|
||||
reg &= ~CCS_MUXSELR_MASK_PIN(pin);
|
||||
reg |= CCS_MUXSELR_VAL(pin, muxsel);
|
||||
|
||||
/* Set the pinmux configurations for the pull-up / pull-down. */
|
||||
gpios ^= (1 << pin); /* Clear the bit we just serviced. */
|
||||
ffs = __builtin_ffs(gpios);
|
||||
}
|
||||
CCS_MUXSELR(port) = reg;
|
||||
}
|
||||
|
||||
void gpio_set_output_options(uint32_t gpioport, ccs_drive_strength_t strength,
|
||||
uint16_t gpios) {
|
||||
uint32_t port = get_ccs_port_base(gpioport);
|
||||
|
||||
/* Update each of the pin configs. */
|
||||
uint32_t reg = CCS_DSR(port);
|
||||
int ffs = __builtin_ffs(gpios);
|
||||
while (ffs) {
|
||||
const int pin = ffs - 1;
|
||||
|
||||
reg &= ~CCS_DSR_MASK_PIN(pin);
|
||||
reg |= CCS_DSR_DS_VAL(pin, strength);
|
||||
|
||||
/* Set the pinmux configurations for the pull-up / pull-down. */
|
||||
gpios ^= (1 << pin); /* Clear the bit we just serviced. */
|
||||
ffs = __builtin_ffs(gpios);
|
||||
}
|
||||
CCS_DSR(port) = reg;
|
||||
}
|
||||
|
||||
void gpio_set_schmidt_trigger(uint32_t gpioport, bool enable, uint16_t gpios) {
|
||||
uint32_t port = get_ccs_port_base(gpioport);
|
||||
|
||||
/* Update each of the pin configs. */
|
||||
uint32_t reg = CCS_DSR(port);
|
||||
int ffs = __builtin_ffs(gpios);
|
||||
while (ffs) {
|
||||
const int pin = ffs - 1;
|
||||
if (enable) {
|
||||
reg |= CCS_DSR_SCHMIDT_PIN(pin);
|
||||
} else {
|
||||
reg &= ~CCS_DSR_SCHMIDT_PIN(pin);
|
||||
}
|
||||
|
||||
/* Set the pinmux configurations for the pull-up / pull-down. */
|
||||
gpios ^= (1 << pin); /* Clear the bit we just serviced. */
|
||||
ffs = __builtin_ffs(gpios);
|
||||
}
|
||||
CCS_DSR(port) = reg;
|
||||
}
|
||||
78
libopencm3/lib/pac55xx/memctl.c
Normal file
78
libopencm3/lib/pac55xx/memctl.c
Normal file
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* @brief <b>PAC55xxxx Memory Controller Driver</b>
|
||||
* @author @htmlonly © @endhtmlonly 2020 Kevin Stefanik <kevin@allocor.tech>
|
||||
* @date April 1, 2020
|
||||
*
|
||||
* This library supports the Memory Controller in the PAC55xx SoC from Qorvo.
|
||||
*
|
||||
* LGPL License Terms @ref lgpl_license
|
||||
*/
|
||||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <libopencm3/pac55xx/memctl.h>
|
||||
|
||||
void memctl_flash_set_wstate(uint32_t wstate) {
|
||||
MEMCTL_MEMCTLR = (MEMCTL_MEMCTLR & ~MEMCTL_MEMCTLR_WSTATE(MEMCTL_MEMCTLR_WSTATE_MASK)) | MEMCTL_MEMCTLR_WSTATE(wstate);
|
||||
}
|
||||
void memctl_flash_set_mclkdiv(uint32_t div) {
|
||||
MEMCTL_MEMCTLR = (MEMCTL_MEMCTLR & ~MEMCTL_MEMCTLR_MCLKDIV(16)) | MEMCTL_MEMCTLR_MCLKDIV(div);
|
||||
}
|
||||
void memctl_flash_reset_write_buffer(void) {
|
||||
MEMCTL_MEMCTLR = (MEMCTL_MEMCTLR & ~MEMCTL_MEMCTLR_WRITEWORDCNT(MEMCTL_MEMCTLR_WRITEWORDCNT_MASK));
|
||||
}
|
||||
void memctl_flash_standby_mode_enable(void) {
|
||||
MEMCTL_MEMCTLR |= MEMCTL_MEMCTLR_STBY;
|
||||
}
|
||||
void memctl_flash_standby_mode_disable(void) {
|
||||
MEMCTL_MEMCTLR &= ~MEMCTL_MEMCTLR_STBY;
|
||||
}
|
||||
void memctl_flash_cache_enable(void) {
|
||||
MEMCTL_MEMCTLR &= ~MEMCTL_MEMCTLR_CACHEDIS;
|
||||
}
|
||||
void memctl_flash_cache_disable(void) {
|
||||
MEMCTL_MEMCTLR |= MEMCTL_MEMCTLR_CACHEDIS;
|
||||
}
|
||||
void memctl_flash_select_roscclk(void) {
|
||||
MEMCTL_MEMCTLR &= ~MEMCTL_MEMCTLR_MCLKSEL;
|
||||
}
|
||||
void memctl_flash_select_mclk(void) {
|
||||
MEMCTL_MEMCTLR |= MEMCTL_MEMCTLR_MCLKSEL;
|
||||
}
|
||||
void memctl_sram_ecc_enable(void) {
|
||||
MEMCTL_MEMCTLR &= ~MEMCTL_MEMCTLR_ECCDIS;
|
||||
}
|
||||
void memctl_sram_ecc_disable(void) {
|
||||
MEMCTL_MEMCTLR |= MEMCTL_MEMCTLR_ECCDIS;
|
||||
}
|
||||
void memctl_sram_ecc_single_bit_interrupt_enable(void) {
|
||||
MEMCTL_MEMCTLR |= MEMCTL_MEMCTLR_SEIE;
|
||||
}
|
||||
void memctl_sram_ecc_single_bit_interrupt_disable(void) {
|
||||
MEMCTL_MEMCTLR &= ~MEMCTL_MEMCTLR_SEIE;
|
||||
}
|
||||
void memctl_sram_ecc_dual_bit_interrupt_enable(void) {
|
||||
MEMCTL_MEMCTLR |= MEMCTL_MEMCTLR_DEIE;
|
||||
}
|
||||
void memctl_sram_ecc_dual_bit_interrupt_disable(void) {
|
||||
MEMCTL_MEMCTLR &= ~MEMCTL_MEMCTLR_DEIE;
|
||||
}
|
||||
void memctl_invaddr_interrupt_enable(void) {
|
||||
MEMCTL_MEMCTLR |= MEMCTL_MEMCTLR_INVADDRIE;
|
||||
}
|
||||
void memctl_invaddr_interrupt_disable(void) {
|
||||
MEMCTL_MEMCTLR &= ~MEMCTL_MEMCTLR_INVADDRIE;
|
||||
}
|
||||
200
libopencm3/lib/pac55xx/usart.c
Normal file
200
libopencm3/lib/pac55xx/usart.c
Normal file
@@ -0,0 +1,200 @@
|
||||
/**
|
||||
* @defgroup usart_api USART peripheral API
|
||||
* @ingroup peripheral_apis
|
||||
* @brief <b>PAC55xxxx USART Driver</b>
|
||||
* @author @htmlonly © @endhtmlonly 2020 Kevin Stefanik <kevin@allocor.tech>
|
||||
* @date February 25, 2020
|
||||
*
|
||||
* This library supports the USART module in the PAC55xx SoC from Qorvo.
|
||||
*
|
||||
* LGPL License Terms @ref lgpl_license
|
||||
*/
|
||||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <libopencm3/pac55xx/usart.h>
|
||||
#include <libopencm3/cm3/common.h>
|
||||
|
||||
/**@{*/
|
||||
|
||||
/** @brief USART Set Baudrate
|
||||
The baud rate is computed assuming a peripheral clock of 150MHz.
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
@param[in] baud unsigned 32 bit. Baud rate specified in Hz.
|
||||
@return Actual baud rate.
|
||||
*/
|
||||
uint32_t usart_set_baudrate(uint32_t usart, uint32_t baud) {
|
||||
/* TODO Assumes 150MHz PCLK. Update this to ccs_get_peripheral_freq() like on other platforms */
|
||||
const uint32_t pclk = 150000000;
|
||||
uint32_t denom = (baud << 4); /* denominator is baud * 16. */
|
||||
uint32_t dlr = 0xFFFFu & ((pclk + denom / 2) / denom);
|
||||
USART_DLR(usart) = dlr;
|
||||
return pclk / (dlr << 4); /* Baud Rate = PCLK / (16 * UARTADLR) */
|
||||
}
|
||||
|
||||
/** @brief USART Configure Line Control Register
|
||||
This register sets the data bits, stop bits, and parity
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
@param[in] data_bits unsigned 8 bit. One of USART_DATABITS_5/6/7/8.
|
||||
@param[in] stop_bits unsigned 8 bit. One of USART_STOPBITS_1/1P5/2.
|
||||
@param[in] parity unsigned 8 bit. One of USART_PARITY_DISABLE/ODD/EVEN/FORCE1/FORCE0
|
||||
*/
|
||||
void usart_configure_lcr(uint32_t usart, uint8_t data_bits, uint8_t stop_bits,
|
||||
uint8_t parity) {
|
||||
USART_LCR(usart) = USART_LCR_WLS(data_bits)
|
||||
| ((stop_bits==USART_STOPBITS_2) ? USART_LCR_SBS : 0)
|
||||
| USART_LCR_PSELPEN(parity);
|
||||
}
|
||||
|
||||
/** @brief Enable Break Control
|
||||
Enables break control bit that forces TX pin to logic low.
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
*/
|
||||
void usart_break_enable(uint32_t usart) {
|
||||
USART_LCR(usart) |= USART_LCR_BCON;
|
||||
}
|
||||
|
||||
/** @brief Disable Break Control
|
||||
Disables break control bit that forces TX pin to logic low.
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
*/
|
||||
void usart_break_disable(uint32_t usart) {
|
||||
USART_LCR(usart) &= ~USART_LCR_BCON;
|
||||
}
|
||||
|
||||
/** @brief Enable Enhanced Mode
|
||||
Enable enhanced mode to generate interrupts when FIFO thresholds in FCR are reached.
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
*/
|
||||
void usart_enhanced_enable(uint32_t usart) {
|
||||
USART_EFR(usart) = USART_EFR_ENMODE;
|
||||
}
|
||||
|
||||
/** @brief Disable Enhanced Mode
|
||||
Disable enhanced mode to generate interrupts when FIFO thresholds in FCR are reached.
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
*/
|
||||
void usart_enhanced_disable(uint32_t usart) {
|
||||
USART_EFR(usart) &= ~USART_EFR_ENMODE;
|
||||
}
|
||||
|
||||
/** @brief Enable FIFOs
|
||||
Enable both TX and RX FIFOs. This must be set before setting the trigger levels.
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
*/
|
||||
void usart_fifo_enable(uint32_t usart) {
|
||||
USART_FCR(usart) |= USART_FCR_FIFOEN;
|
||||
}
|
||||
|
||||
/** @brief Disable FIFOs
|
||||
Disable both TX and RX FIFOs.
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
*/
|
||||
void usart_fifo_disable(uint32_t usart) {
|
||||
USART_FCR(usart) &= ~USART_FCR_FIFOEN;
|
||||
}
|
||||
|
||||
/** Set the TX and RX FIFO depth. This function also enables the FIFOs if not already.
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
@param[in] tx_depth unsigned 8 bit. One of USART_FIFO_TRIG_1/2/4/14CHAR.
|
||||
@param[in] rx_depth unsigned 8 bit. One of USART_FIFO_TRIG_1/2/4/14CHAR.
|
||||
*/
|
||||
void usart_set_fifo_depth(uint32_t usart, uint8_t tx_depth, uint8_t rx_depth) {
|
||||
USART_FCR(usart) |= USART_FCR_FIFOEN;
|
||||
USART_FCR(usart) = USART_FCR_TXTL(tx_depth) | USART_FCR_RXTL(rx_depth) | USART_FCR_FIFOEN;
|
||||
}
|
||||
|
||||
/** @brief Write byte to TX FIFO
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
@param[in] data unsigned 8 bit. Data to write to the TX FIFO.
|
||||
*/
|
||||
void usart_send(uint32_t usart, uint8_t data) {
|
||||
USART_THR(usart) = (uint32_t)data;
|
||||
}
|
||||
|
||||
/** @brief Read byte from the RX FIFO
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
@return Data read from the RX FIFO.
|
||||
*/
|
||||
uint8_t usart_recv(uint32_t usart) {
|
||||
return (uint8_t)USART_RBR(usart);
|
||||
}
|
||||
|
||||
/** @brief Enable RX Interrupts
|
||||
Enable both the Receive Data Available and Character Timeout interrupts.
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
*/
|
||||
void usart_enable_rx_interrupt(uint32_t usart) {
|
||||
USART_IER(usart) |= USART_IER_RBRIE;
|
||||
}
|
||||
|
||||
/** @brief Disable RX Interrupts
|
||||
Disable both the Receive Data Available and Character Timeout interrupts.
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
*/
|
||||
void usart_disable_rx_interrupt(uint32_t usart) {
|
||||
USART_IER(usart) &= ~USART_IER_RBRIE;
|
||||
}
|
||||
|
||||
/** @brief Enable TX Interrupt
|
||||
Enable the TX Holding Register Empty interrupt.
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
*/
|
||||
void usart_enable_tx_interrupt(uint32_t usart) {
|
||||
USART_IER(usart) |= USART_IER_THRIE;
|
||||
}
|
||||
|
||||
/** @brief Disable TX Interrupt
|
||||
Disable the TX Holding Register Empty interrupt.
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
*/
|
||||
void usart_disable_tx_interrupt(uint32_t usart) {
|
||||
USART_IER(usart) &= ~USART_IER_THRIE;
|
||||
}
|
||||
|
||||
/** @brief Enable RX Line Status Interrupt
|
||||
Enable the RX Line Status interrupt.
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
*/
|
||||
void usart_enable_rls_interrupt(uint32_t usart) {
|
||||
USART_IER(usart) |= USART_IER_RLSIE;
|
||||
}
|
||||
|
||||
/** @brief Disable RX Line Status Interrupt
|
||||
Disable the RX Line Status interrupt.
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
*/
|
||||
void usart_disable_rls_interrupt(uint32_t usart) {
|
||||
USART_IER(usart) &= ~USART_IER_RLSIE;
|
||||
}
|
||||
|
||||
/** @brief Clear the TX FIFO
|
||||
Clears the TX FIFO. The bit is self-clearing.
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
*/
|
||||
void usart_clear_tx_fifo(uint32_t usart) {
|
||||
USART_FCR(usart) |= USART_FCR_TXFIFORST;
|
||||
}
|
||||
|
||||
/** @brief Clear the RX FIFO
|
||||
Clears the RX FIFO. The bit is self-clearing.
|
||||
@param[in] usart unsigned 32 bit. USART block register address base @ref usart_reg_base
|
||||
*/
|
||||
void usart_clear_rx_fifo(uint32_t usart) {
|
||||
USART_FCR(usart) |= USART_FCR_RXFIFORST;
|
||||
}
|
||||
|
||||
/**@}*/
|
||||
24
libopencm3/lib/pac55xx/vector_chipset.c
Normal file
24
libopencm3/lib/pac55xx/vector_chipset.c
Normal file
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* This file is part of the libopencm3 project.
|
||||
*
|
||||
* Copyright (C) 2019 Brian Viele <vielster@allocor.tech>
|
||||
*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
/* Standard Cortex-M4F initialization of FPU. */
|
||||
static void pre_main(void) {
|
||||
/* Enable FPU */
|
||||
SCB_CPACR |= SCB_CPACR_FULL * (SCB_CPACR_CP10 | SCB_CPACR_CP11);
|
||||
}
|
||||
40
libopencm3/lib/sam/3a/Makefile
Normal file
40
libopencm3/lib/sam/3a/Makefile
Normal file
@@ -0,0 +1,40 @@
|
||||
##
|
||||
## This file is part of the libopencm3 project.
|
||||
##
|
||||
## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
##
|
||||
## 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/>.
|
||||
##
|
||||
|
||||
LIBNAME = libopencm3_sam3a
|
||||
SRCLIBDIR ?= ../..
|
||||
|
||||
CC = $(PREFIX)gcc
|
||||
AR = $(PREFIX)ar
|
||||
TGT_CFLAGS = -Os -Wall -Wextra -I../../../include -fno-common \
|
||||
-mcpu=cortex-m3 -mthumb $(FP_FLAGS) -Wstrict-prototypes \
|
||||
-ffunction-sections -fdata-sections -MD -DSAM3A
|
||||
TGT_CFLAGS += $(DEBUG_FLAGS)
|
||||
TGT_CFLAGS += $(STANDARD_FLAGS)
|
||||
# ARFLAGS = rcsv
|
||||
ARFLAGS = rcs
|
||||
|
||||
OBJS += gpio_common_all.o gpio_common_3a3u3x.o
|
||||
OBJS += pmc.o
|
||||
OBJS += usart_common_all.o usart_common_3.o
|
||||
|
||||
VPATH += ../../usb:../../cm3:../common
|
||||
|
||||
include ../../Makefile.include
|
||||
|
||||
40
libopencm3/lib/sam/3n/Makefile
Normal file
40
libopencm3/lib/sam/3n/Makefile
Normal file
@@ -0,0 +1,40 @@
|
||||
##
|
||||
## This file is part of the libopencm3 project.
|
||||
##
|
||||
## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
##
|
||||
## 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/>.
|
||||
##
|
||||
|
||||
LIBNAME = libopencm3_sam3n
|
||||
SRCLIBDIR ?= ../..
|
||||
|
||||
CC = $(PREFIX)gcc
|
||||
AR = $(PREFIX)ar
|
||||
TGT_CFLAGS = -Os -Wall -Wextra -I../../../include -fno-common \
|
||||
-mcpu=cortex-m3 -mthumb $(FP_FLAGS) -Wstrict-prototypes \
|
||||
-ffunction-sections -fdata-sections -MD -DSAM3N
|
||||
TGT_CFLAGS += $(DEBUG_FLAGS)
|
||||
TGT_CFLAGS += $(STANDARD_FLAGS)
|
||||
# ARFLAGS = rcsv
|
||||
ARFLAGS = rcs
|
||||
|
||||
OBJS += gpio_common_all.o gpio_common_3n3s.o
|
||||
OBJS += pmc.o
|
||||
OBJS += usart_common_all.o usart_common_3.o
|
||||
|
||||
VPATH += ../../cm3:../common
|
||||
|
||||
include ../../Makefile.include
|
||||
|
||||
41
libopencm3/lib/sam/3s/Makefile
Normal file
41
libopencm3/lib/sam/3s/Makefile
Normal file
@@ -0,0 +1,41 @@
|
||||
##
|
||||
## This file is part of the libopencm3 project.
|
||||
##
|
||||
## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
## Copyright (C) 2014 Felix Held <felix-libopencm3@felixheld.de>
|
||||
##
|
||||
## 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/>.
|
||||
##
|
||||
|
||||
LIBNAME = libopencm3_sam3s
|
||||
SRCLIBDIR ?= ../..
|
||||
|
||||
CC = $(PREFIX)gcc
|
||||
AR = $(PREFIX)ar
|
||||
TGT_CFLAGS = -Os -Wall -Wextra -I../../../include -fno-common \
|
||||
-mcpu=cortex-m3 -mthumb $(FP_FLAGS) -Wstrict-prototypes \
|
||||
-ffunction-sections -fdata-sections -MD -DSAM3S
|
||||
TGT_CFLAGS += $(DEBUG_FLAGS)
|
||||
TGT_CFLAGS += $(STANDARD_FLAGS)
|
||||
# ARFLAGS = rcsv
|
||||
ARFLAGS = rcs
|
||||
|
||||
OBJS += gpio_common_all.o gpio_common_3n3s.o
|
||||
OBJS += pmc.o
|
||||
OBJS += usart_common_all.o usart_common_3.o
|
||||
|
||||
VPATH += ../../usb:../../cm3:../common
|
||||
|
||||
include ../../Makefile.include
|
||||
|
||||
41
libopencm3/lib/sam/3u/Makefile
Normal file
41
libopencm3/lib/sam/3u/Makefile
Normal file
@@ -0,0 +1,41 @@
|
||||
##
|
||||
## This file is part of the libopencm3 project.
|
||||
##
|
||||
## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
## Copyright (C) 2014 Felix Held <felix-libopencm3@felixheld.de>
|
||||
##
|
||||
## 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/>.
|
||||
##
|
||||
|
||||
LIBNAME = libopencm3_sam3u
|
||||
SRCLIBDIR ?= ../..
|
||||
|
||||
CC = $(PREFIX)gcc
|
||||
AR = $(PREFIX)ar
|
||||
TGT_CFLAGS = -Os -Wall -Wextra -I../../../include -fno-common \
|
||||
-mcpu=cortex-m3 -mthumb $(FP_FLAGS) -Wstrict-prototypes \
|
||||
-ffunction-sections -fdata-sections -MD -DSAM3U
|
||||
TGT_CFLAGS += $(DEBUG_FLAGS)
|
||||
TGT_CFLAGS += $(STANDARD_FLAGS)
|
||||
# ARFLAGS = rcsv
|
||||
ARFLAGS = rcs
|
||||
|
||||
OBJS += gpio_common_all.o gpio_common_3a3u3x.o
|
||||
OBJS += pmc.o
|
||||
OBJS += usart_common_all.o usart_common_3.o
|
||||
|
||||
VPATH += ../../usb:../../cm3:../common
|
||||
|
||||
include ../../Makefile.include
|
||||
|
||||
40
libopencm3/lib/sam/3x/Makefile
Normal file
40
libopencm3/lib/sam/3x/Makefile
Normal file
@@ -0,0 +1,40 @@
|
||||
##
|
||||
## This file is part of the libopencm3 project.
|
||||
##
|
||||
## Copyright (C) 2009 Uwe Hermann <uwe@hermann-uwe.de>
|
||||
##
|
||||
## 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/>.
|
||||
##
|
||||
|
||||
LIBNAME = libopencm3_sam3x
|
||||
SRCLIBDIR ?= ../..
|
||||
|
||||
CC = $(PREFIX)gcc
|
||||
AR = $(PREFIX)ar
|
||||
TGT_CFLAGS = -Os -Wall -Wextra -I../../../include -fno-common \
|
||||
-mcpu=cortex-m3 -mthumb $(FP_FLAGS) -Wstrict-prototypes \
|
||||
-ffunction-sections -fdata-sections -MD -DSAM3X
|
||||
TGT_CFLAGS += $(DEBUG_FLAGS)
|
||||
TGT_CFLAGS += $(STANDARD_FLAGS)
|
||||
# ARFLAGS = rcsv
|
||||
ARFLAGS = rcs
|
||||
|
||||
OBJS += gpio_common_all.o gpio_common_3a3u3x.o
|
||||
OBJS += pmc.o
|
||||
OBJS += usart_common_all.o usart_common_3.o
|
||||
|
||||
VPATH += ../../usb:../../cm3:../common
|
||||
|
||||
include ../../Makefile.include
|
||||
|
||||
40
libopencm3/lib/sam/4l/Makefile
Normal file
40
libopencm3/lib/sam/4l/Makefile
Normal file
@@ -0,0 +1,40 @@
|
||||
##
|
||||
## 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 <http://www.gnu.org/licenses/>.
|
||||
##
|
||||
|
||||
LIBNAME = libopencm3_sam4l
|
||||
SRCLIBDIR ?= ../..
|
||||
|
||||
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
|
||||
OBJS += gpio.o
|
||||
OBJS += pm.o
|
||||
OBJS += scif.o
|
||||
OBJS += usart_common_all.o usart.o
|
||||
|
||||
VPATH += ../../usb:../../cm3:../common
|
||||
|
||||
include ../../Makefile.include
|
||||
|
||||
121
libopencm3/lib/sam/4l/adcife.c
Normal file
121
libopencm3/lib/sam/4l/adcife.c
Normal file
@@ -0,0 +1,121 @@
|
||||
/** @addtogroup scif
|
||||
*
|
||||
* @brief <b>Access functions for the SAM4 Analog to Digital Converter Interface (ADCIFE)</b>
|
||||
* @ingroup SAM4
|
||||
* LGPL License Terms @ref lgpl_license
|
||||
* @author @htmlonly © @endhtmlonly 2016
|
||||
* Maxim Sloyko <maxims@google.com>
|
||||
*
|
||||
*/
|
||||
|
||||
#include <libopencm3/sam/adcife.h>
|
||||
|
||||
/** @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;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user