xref: /aosp_15_r20/external/pigweed/pw_digital_io_mcuxpresso/interrupt_controller.cc (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1 // Copyright 2023 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_digital_io_mcuxpresso/interrupt_controller.h"
16 
17 #include <array>
18 #include <cstdint>
19 
20 #include "fsl_pint.h"
21 #include "pw_digital_io/digital_io.h"
22 #include "pw_function/function.h"
23 #include "pw_result/result.h"
24 #include "pw_status/status.h"
25 
26 namespace pw::digital_io {
27 namespace {
28 
29 using ::pw::digital_io::InterruptTrigger;
30 using ::pw::digital_io::State;
31 
32 // PINT API doesn't allow context on callback API, so store globally.
33 std::array<pw::digital_io::InterruptHandler,
34            FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS>
35     interrupt_handlers;
36 std::array<PINT_Type*, FSL_FEATURE_PINT_NUMBER_OF_CONNECTED_OUTPUTS> bases;
37 
PintCallback(pint_pin_int_t pin,uint32_t)38 void PintCallback(pint_pin_int_t pin, uint32_t) {
39   PW_CHECK(pin < interrupt_handlers.size());
40   State state = PINT_PinInterruptGetStatus(bases[pin], pin) == 1
41                     ? State::kActive
42                     : State::kInactive;
43   interrupt_handlers[pin](state);
44   SDK_ISR_EXIT_BARRIER;
45 }
46 
47 }  // namespace
48 
McuxpressoInterruptController(PINT_Type * base)49 McuxpressoInterruptController::McuxpressoInterruptController(PINT_Type* base)
50     : base_(base) {
51   PINT_Init(base_);
52 }
53 
~McuxpressoInterruptController()54 McuxpressoInterruptController::~McuxpressoInterruptController() {
55   PINT_Deinit(base_);
56 }
57 
Config(pint_pin_int_t pin,InterruptTrigger trigger,pw::digital_io::InterruptHandler && handler)58 pw::Status McuxpressoInterruptController::Config(
59     pint_pin_int_t pin,
60     InterruptTrigger trigger,
61     pw::digital_io::InterruptHandler&& handler) {
62   if (pin >= interrupt_handlers.size()) {
63     return pw::Status::InvalidArgument();
64   }
65   interrupt_handlers[pin] = std::move(handler);
66   bases[pin] = base_;
67   switch (trigger) {
68     case InterruptTrigger::kActivatingEdge:
69       PINT_PinInterruptConfig(
70           base_, pin, kPINT_PinIntEnableRiseEdge, PintCallback);
71       break;
72     case InterruptTrigger::kDeactivatingEdge:
73       PINT_PinInterruptConfig(
74           base_, pin, kPINT_PinIntEnableFallEdge, PintCallback);
75       break;
76     case InterruptTrigger::kBothEdges:
77       PINT_PinInterruptConfig(
78           base_, pin, kPINT_PinIntEnableBothEdges, PintCallback);
79       break;
80     default:
81       return pw::Status::InvalidArgument();
82   }
83   return pw::OkStatus();
84 }
85 
EnableHandler(pint_pin_int_t pin,bool enable)86 pw::Status McuxpressoInterruptController::EnableHandler(pint_pin_int_t pin,
87                                                         bool enable) {
88   if (enable) {
89     PINT_EnableCallbackByIndex(base_, pin);
90   } else {
91     PINT_DisableCallbackByIndex(base_, pin);
92   }
93   return pw::OkStatus();
94 }
95 
GetState(pint_pin_int_t pin)96 pw::Result<pw::digital_io::State> McuxpressoInterruptController::GetState(
97     pint_pin_int_t pin) {
98   switch (PINT_PinInterruptGetStatus(base_, pin)) {
99     case 0:
100       return State::kInactive;
101     case 1:
102       return State::kActive;
103     default:
104       return pw::Status::Unknown();
105   }
106 }
107 
108 }  // namespace pw::digital_io
109