libopencm3
A free/libre/open-source firmware library for various ARM Cortex-M3 microcontrollers.
common/periph.h
Go to the documentation of this file.
1/*
2 * This file is part of the libopencm3 project.
3 *
4 * Copyright (C) 2017-2018 Unicore MX project<dev(at)lists(dot)unicore-mx(dot)org>
5 * Copyright (C) 2021 Eduard Drusa <ventyl86(at)netkosice(dot)sk>
6 *
7 * This library is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library. If not, see <http://www.gnu.org/licenses/>.
19 */
20
21#pragma once
22
24#include <libopencm3/cm3/nvic.h>
26
27/* Common Peripheral Interface.
28 * The implementation only applies to peripherals on APB
29 * bus, which for this part excludes only GPIO.
30 */
31
32/* Peripheral IDs
33 *
34 * For peripherals on the APB bus there is a direct relationship between its ID
35 * and its base address. A peripheral with base address 0x40000000 is therefore
36 * assigned ID=0, and a peripheral with base address 0x40001000 is assigned
37 * ID=1. The peripheral with base address 0x4001F000 is assigned ID=31
38 */
39
40#define PERIPH_CLOCK_ID (0x00)
41#define PERIPH_POWER_ID (0x00)
42#define PERIPH_MPU_ID (0x00)
43#define PERIPH_RADIO_ID (0x01)
44#define PERIPH_UART_ID (0x02)
45#define PERIPH_SPI0_ID (0x03)
46#define PERIPH_TWI0_ID (0x03)
47#define PERIPH_I2C0_ID (0x03)
48#define PERIPH_SPI1_ID (0x04)
49#define PERIPH_SPIS1_ID (0x04)
50#define PERIPH_TWI1_ID (0x04)
51#define PERIPH_I2C1_ID (0x04)
52#define PERIPH_GPIOTE_ID (0x06)
53#define PERIPH_ADC_ID (0x07)
54#define PERIPH_TIMER0_ID (0x08)
55#define PERIPH_TIMER1_ID (0x09)
56#define PERIPH_TIMER2_ID (0x0a)
57#define PERIPH_RTC0_ID (0x0b)
58#define PERIPH_TEMP_ID (0x0c)
59#define PERIPH_RNG_ID (0x0d)
60#define PERIPH_ECB_ID (0x0e)
61#define PERIPH_AAR_ID (0x0f)
62#define PERIPH_CCM_ID (0x0f)
63#define PERIPH_WDT_ID (0x10)
64#define PERIPH_RTC1_ID (0x11)
65#define PERIPH_QDEC_ID (0x12)
66#define PERIPH_LPCOMP_ID (0x13)
67#define PERIPH_SWI0_ID (0x14)
68#define PERIPH_SWI1_ID (0x15)
69#define PERIPH_SWI2_ID (0x16)
70#define PERIPH_SWI3_ID (0x17)
71#define PERIPH_SWI4_ID (0x18)
72#define PERIPH_SWI5_ID (0x19)
73#define PERIPH_NVMC_ID (0x1e)
74#define PERIPH_PPI_ID (0x1f)
75
76#define PERIPH_BASE_FROM_ID(periph_id) (ABP_BASE + 0x1000 * (periph_id))
77#define PERIPH_ID_FROM_BASE(base) (((base) - APB_BASE) >> 12)
78#define PERIPH_BASE_FROM_REG(reg) (((uint32_t) &(reg)) & 0xfffff000)
79
80/*
81 * Tasks are used to trigger actions in a peripheral, for example, to start a
82 * particular behavior. A peripheral can implement multiple tasks with each
83 * task having a separate register in that peripheral's task register group.
84 *
85 * A task is triggered when firmware writes a '1' to the task register or when
86 * the peripheral itself, or another peripheral, toggles the corresponding task
87 * signal.
88 */
89
90/** Starting address of all the tasks in the peripheral. */
91#define PERIPH_TASK_OFFSET (0x000)
92
93/*
94 * Events are used to notify peripherals and the CPU about events that have
95 * happened, for example, a state change in a peripheral. A peripheral may
96 * generate multiple events with each event having a separate register in that
97 * peripheral’s event register group. An event is generated when the
98 * peripheral itself toggles the corresponding event signal, whereupon the
99 * event register is updated to reflect that the event has been generated.
100 */
101
102/** Starting address of all the events in the peripheral. */
103#define PERIPH_EVENT_OFFSET (0x100)
104
105#define PERIPH_TRIGGER_TASK(task) (task) = (1)
106
107/* All peripherals on the APB bus support interrupts. A peripheral only
108 * occupies one interrupt, and the interrupt number follows the peripheral ID,
109 * for example, the peripheral with ID=4 is connected to interrupt number 4 in
110 * the Nested Vector Interrupt Controller (NVIC).
111 */
112
113#define PERIPH_ENABLE_IRQ(base) nvic_enable_irq(periph_id_from_base(base))
114#define PERIPH_DISABLE_IRQ(base) nvic_disable_irq(periph_id_from_base(base))
115
116/* Common regisgers. Not all peripherals have these registers, but when they
117 * are present, they are at this offset.
118 */
119#define PERIPH_SHORTS_OFFSET (0x200)
120#define PERIPH_INTEN_OFFSET (0x300)
121#define PERIPH_INTENSET_OFFSET (0x304)
122#define PERIPH_INTENCLR_OFFSET (0x308)
123
124#define _PERIPH_SHORTS(base) MMIO32((base) + PERIPH_SHORTS_OFFSET)
125#define _PERIPH_INTEN(base) MMIO32((base) + PERIPH_INTEN_OFFSET)
126#define _PERIPH_INTENSET(base) MMIO32((base) + PERIPH_INTENSET_OFFSET)
127#define _PERIPH_INTENCLR(base) MMIO32((base) + PERIPH_INTENCLR_OFFSET)
128
129/* TODO: convert these to functions */
130#define periph_enable_shorts(base, shorts) periph_shorts(base) |= (shorts)
131#define periph_disable_shorts(base, shorts) periph_shorts(base) &= (~(shorts))
132#define periph_clear_shorts(base) periph_shorts(base) = (0)
133
134#define periph_enable_interrupts(base, mask) periph_intenset(base) |= (mask)
135#define periph_disable_interrupts(base, mask) periph_intenclr(base) = (mask)
136#define periph_clear_interrupts(base) periph_intenclr(base) = (0xffffffff)
137
138/** Mark the signal as not connected to any pin. */
139#define GPIO_UNCONNECTED 0xFFFFFFFFU
140
141/** This is an approximation of log2. As used here, works correctly
142 * only for single bit set, which should be the case when used to.
143 * convert above GPIOxy macros to pin numbers as needed for PSEL
144 * registers of peripherals.
145 */
146#define __GPIO2PIN(x) (31 - __builtin_clz((uint32_t) (x)))
147
148