blob: 8f5247aff4945a6f008a4dee2036475e1e4c2df9 [file] [log] [blame]
Anthony DiGirolamofb41f922021-03-02 14:32:01 -08001// Copyright 2021 The Pigweed Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4// use this file except in compliance with the License. You may obtain a copy of
5// the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12// License for the specific language governing permissions and limitations under
13// the License.
14
15#include "pw_board_led/led.h"
16
17#include <cinttypes>
18
19#include "pw_preprocessor/compiler.h"
20
21namespace pw::board_led {
22namespace {
23
24// Base address for everything peripheral-related on the STM32F4xx.
25constexpr uint32_t kPeripheralBaseAddr = 0x40000000u;
26// Base address for everything AHB1-related on the STM32F4xx.
27constexpr uint32_t kAhb1PeripheralBase = kPeripheralBaseAddr + 0x00020000U;
28// Base address for everything APB2-related on the STM32F4xx.
29constexpr uint32_t kApb2PeripheralBase = kPeripheralBaseAddr + 0x00010000U;
30
31// Reset/clock configuration block (RCC).
32// `reserved` fields are unimplemented features, and are present to ensure
33// proper alignment of registers that are in use.
34PW_PACKED(struct) RccBlock {
35 uint32_t reserved1[12];
36 uint32_t ahb1_config;
37 uint32_t reserved2[4];
38 uint32_t apb2_config;
39};
40
41// GPIO register block definition.
42PW_PACKED(struct) GpioBlock {
43 uint32_t modes;
44 uint32_t out_type;
45 uint32_t out_speed;
46 uint32_t pull_up_down;
47 uint32_t input_data;
48 uint32_t output_data;
49 uint32_t gpio_bit_set;
50 uint32_t port_config_lock;
51 uint32_t alt_low;
52 uint32_t alt_high;
53};
54
55// Constants related to GPIO mode register masks.
56constexpr uint32_t kGpioPortModeMask = 0x3u;
57constexpr uint32_t kGpio13PortModePos = 26;
58constexpr uint32_t kGpioPortModeOutput = 1;
59
60// Constants related to GPIO output mode register masks.
61constexpr uint32_t kGpioOutputModeMask = 0x1u;
62constexpr uint32_t kGpio13OutputModePos = 13;
63constexpr uint32_t kGpioOutputModePushPull = 0;
64
65constexpr uint32_t kGpio13BitSetHigh = 0x1u << 13;
66constexpr uint32_t kGpio13BitSetLow = kGpio13BitSetHigh << 16;
67
68// Mask for ahb1_config (AHB1ENR) to enable the "G" GPIO pins.
69constexpr uint32_t kGpioGEnable = 0x1u << 6;
70
71// Declare a reference to the memory mapped RCC block.
72volatile RccBlock& platform_rcc =
73 *reinterpret_cast<volatile RccBlock*>(kAhb1PeripheralBase + 0x3800U);
74
75// Declare a reference to the 'G' GPIO memory mapped block.
76volatile GpioBlock& gpio_g =
77 *reinterpret_cast<volatile GpioBlock*>(kAhb1PeripheralBase + 0x1800U);
78
79} // namespace
80
81void Init() {
82 // Enable 'G' GIPO clocks.
83 platform_rcc.ahb1_config |= kGpioGEnable;
84
85 // Enable Pin 13 in output mode.
86 gpio_g.modes = (gpio_g.modes & ~(kGpioPortModeMask << kGpio13PortModePos)) |
87 (kGpioPortModeOutput << kGpio13PortModePos);
88
89 // Enable Pin 13 in output mode "push pull"
90 gpio_g.out_type =
91 (gpio_g.out_type & ~(kGpioOutputModeMask << kGpio13OutputModePos)) |
92 (kGpioOutputModePushPull << kGpio13OutputModePos);
93}
94
95void TurnOff() { gpio_g.gpio_bit_set = kGpio13BitSetLow; }
96
97void TurnOn() { gpio_g.gpio_bit_set = kGpio13BitSetHigh; }
98
99void Toggle() {
100 // Check if the LED is on. If so, turn it off.
101 if (gpio_g.output_data & kGpio13BitSetHigh) {
102 TurnOff();
103 } else {
104 TurnOn();
105 }
106}
107
108} // namespace pw::board_led