rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
sent_hw_icu.cpp
Go to the documentation of this file.
1/*
2 * sent_hw_icu.cpp
3 *
4 * SENT protocol glue to ChibiOS ICU driver
5 *
6 * @date Oct 01, 2022
7 * @author Andrey Gusakov <dron0gus@gmail.com>, (c) 2022
8 */
9
10#if EFI_PROD_CODE
11
12#include "pch.h"
13
14#if EFI_SENT_SUPPORT
15
16#include "sent.h"
17#include "sent_hw_icu.h"
18
19#include "io_pins.h"
20#include "pin_repository.h"
21
22/* This SENT HW driver is based on ChibiOS ICU driver */
23#if (HAL_USE_ICU == TRUE)
24
25/* TODO: do we care about scaling abstract timer ticks to some time base? */
26/* TODO: get at runtime */
27/* Max timer clock for most timers on STM32 is CPU clock / 2 */
28#define SENT_TIMER_CLOCK_DIV 2
29#define SENT_ICU_FREQ (STM32_SYSCLK / SENT_TIMER_CLOCK_DIV) // == CPU freq / 2
30
31static uint16_t lastPulse[SENT_INPUT_COUNT];
32static bool overcapture[SENT_INPUT_COUNT];
33
34static void icuperiodcb(ICUDriver *icup, size_t index)
35{
36 uint16_t clocks;
37 uint8_t flags = 0;
38 const ICUConfig *icucfg = icup->config;
39
40 if ((icucfg->channel == ICU_CHANNEL_1) || (icucfg->channel == ICU_CHANNEL_2)) {
41 /* channel 1 and channel 2 supports period measurements */
42 clocks = icuGetPeriodX(icup);
43 } else {
44 /* this is freerunnig timer and we need to calculate period using just captured timer value and previous one */
45 /* TODO: support 32 bit timers too? */
46 uint16_t val = icuGetWidthX(icup);
47
48 /* can overflow */
49 clocks = val - lastPulse[index];
50
51 lastPulse[index] = val;
52 }
53
54 if (overcapture[index]) {
55 flags |= SENT_FLAG_HW_OVERFLOW;
56 overcapture[index] = false;
57 }
58
59 SENT_ISR_Handler(index, clocks, flags);
60}
61
62static void icuovercapture(ICUDriver *icup, size_t index)
63{
64 UNUSED(icup);
65 overcapture[index] = true;
66}
67
68/* ICU callbacks */
69static void icuperiodcb_in1(ICUDriver *icup)
70{
71 icuperiodcb(icup, 0);
72}
73
74static void icuovercapture_in1(ICUDriver *icup)
75{
76 icuovercapture(icup, 0);
77}
78
79/* ICU configs */
80static ICUConfig icucfg[SENT_INPUT_COUNT] =
81{
82 {
83 .mode = ICU_INPUT_ACTIVE_LOW,
84 .frequency = SENT_ICU_FREQ,
85 .width_cb = NULL,
86 .period_cb = icuperiodcb_in1,
87 .overflow_cb = NULL,
88 .channel = ICU_CHANNEL_1, /* will be overwriten on startSent() */
89 .dier = 0U,
90 .arr = 0xFFFFFFFFU,
91 .overcapture_cb = icuovercapture_in1,
92 }
93};
94
95void startSent() {
96 for (int i = 0; i < SENT_INPUT_COUNT; i++) {
98
99 if (!isBrainPinValid(sentPin)) {
100 continue;
101 }
102
103 ICUConfig *cfg = &icucfg[i];
104 ICUDriver *icu;
105 iomode_t pinAF;
106 uint32_t baseClock;
107
108 if (getIcuParams(sentPin, &pinAF, &icu, &cfg->channel, &baseClock) != true) {
109 /* this pin has no ICU functionality or ICU driver is not enabled for TIM on this pin */
110 criticalError("No ICU on selected SENT pin");
111 continue;
112 }
113
114 efiSetPadMode("SENT", sentPin, PAL_MODE_ALTERNATE(pinAF));
115
116 icuStart(icu, cfg);
117 icuStartCapture(icu);
118 icuEnableNotifications(icu);
119 }
120}
121
122void stopSent() {
123 for (int i = 0; i < SENT_INPUT_COUNT; i++) {
125
126 if (!isBrainPinValid(sentPin)) {
127 continue;
128 }
129
130 ICUDriver *icu;
131
132 if (getIcuParams(sentPin, NULL, &icu, NULL, NULL) != true) {
133 /* this pin has no ICU functionality or ICU driver is not enabled for TIM on this pin */
134 /* throw error? */
135 continue;
136 }
137
138 icuDisableNotifications(icu);
139 icuStopCapture(icu);
140 icuStop(icu);
141
142 efiSetPadUnused(sentPin);
143 }
144}
145
146#endif /* EFI_SENT_SUPPORT */
147
148#endif /* HAL_USE_ICU */
149
150#endif /* EFI_PROD_CODE */
void efiSetPadMode(const char *msg, brain_pin_e brainPin, iomode_t mode)
engine_configuration_s & activeConfiguration
static constexpr engine_configuration_s * engineConfiguration
uint32_t iomode_t
Digital I/O modes.
Definition hal_pal_lld.h:83
void efiSetPadUnused(brain_pin_e brainPin)
Definition io_pins.cpp:20
this file is about general input/output utility methods, not much EFI-specifics
UNUSED(samplingTimeSeconds)
bool getIcuParams(brain_pin_e hwPin, iomode_t *af_ptr, ICUDriver **icu_ptr, icuchannel_t *channel_ptr, uint32_t *clock_ptr)
bool isBrainPinValid(brain_pin_e brainPin)
I/O pin registry header.
void SENT_ISR_Handler(uint8_t channel, uint16_t clocks, uint8_t flags)
Definition sent.cpp:73
void stopSent()
static void icuperiodcb(ICUDriver *icup, size_t index)
static void icuovercapture(ICUDriver *icup, size_t index)
static void icuovercapture_in1(ICUDriver *icup)
static ICUConfig icucfg[SENT_INPUT_COUNT]
static uint16_t lastPulse[SENT_INPUT_COUNT]
void startSent()
static void icuperiodcb_in1(ICUDriver *icup)
static bool overcapture[SENT_INPUT_COUNT]