rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
pin_repository.cpp
Go to the documentation of this file.
1/**
2 * @file pin_repository.cpp
3 * @brief I/O pin registry code
4 *
5 * This job of this class is to make sure that we are not using same hardware pin for two
6 * different purposes.
7 *
8 * @date Jan 15, 2013
9 * @author Andrey Belomutskiy, (c) 2012-2020
10 */
11
12#include "pch.h"
13
15
16static size_t getBrainPinTotalNum() {
17 return BRAIN_PIN_TOTAL_PINS;
18}
19
20const char* & getBrainUsedPin(size_t index) {
21 return pinRepository.getBrainUsedPin(index);
22}
23
24/* Common for firmware and unit tests */
26 if ((brainPin == Gpio::Unassigned) || (brainPin == Gpio::Invalid))
27 return false;
28
29 if (brainPin > BRAIN_PIN_LAST)
30 /* something terribly wrong */
31 return false;
32
33 return true;
34}
35
36int brainPin_to_index(Gpio brainPin) {
37 if (brainPin < Gpio::A0)
38 return -1;
39
40 size_t i = brainPin - Gpio::A0;
41
42 if (i >= getBrainPinTotalNum())
43 return -1;
44
45 return i;
46}
47
48/**
49 * See also brain_pin_markUnused()
50 * @return true if this pin was already used, false otherwise
51 */
52
53bool brain_pin_markUsed(Gpio brainPin, const char *msg) {
54#ifndef EFI_BOOTLOADER
55// efiPrintf("pin_markUsed: %s on %s", msg, hwPortname(brainPin));
56#endif
57
58 int index = brainPin_to_index(brainPin);
59 if (index < 0)
60 return true;
61
62 if (pinRepository.getBrainUsedPin(index) != nullptr) {
63 // hwPortname and share a buffer behind the scenes, even while they probably never use it for different
64 // values here let's have an explicit second buffer to make this more reliable
65 char physicalPinName[32];
66 strncpy(physicalPinName, hwPhysicalPinName(brainPin), sizeof(physicalPinName) - 1);
67 criticalError("Pin \"%s\" (%s) required by \"%s\" but is used by \"%s\"",
68 hwPortname(brainPin),
69 physicalPinName,
70 msg,
71 getBrainUsedPin(index));
72 return true;
73 }
74
75 getBrainUsedPin(index) = msg;
76 return false;
77}
78
79/**
80 * See also brain_pin_markUsed()
81 */
82
84#ifndef EFI_BOOTLOADER
85// efiPrintf("pin_markUnused: %s", hwPortname(brainPin));
86#endif
87 int index = brainPin_to_index(brainPin);
88 if (index < 0)
89 return;
90
91 getBrainUsedPin(index) = nullptr;
92}
93
94#if EFI_PROD_CODE
95#include "memstreams.h"
96static MemoryStream portNameStream;
97static char portNameBuffer[20];
98#endif /* EFI_PROD_CODE */
99
101#if EFI_PROD_CODE
102 msObjectInit(&portNameStream, (uint8_t*) portNameBuffer, sizeof(portNameBuffer), 0);
103#endif /* EFI_PROD_CODE */
104
105 memset(PIN_USED, 0, sizeof(PIN_USED));
106}
107
108#if EFI_PROD_CODE
109
110#include "eficonsole.h"
112#include "smart_gpio.h"
113#include "hardware.h"
114
115void pinDiag2string(char *buffer, size_t size, brain_pin_diag_e pin_diag) {
116 /* use autogeneraged helpers here? */
117 if (pin_diag == PIN_OK) {
118 chsnprintf(buffer, size, "Ok");
119 } else if (pin_diag != PIN_UNKNOWN) {
120 chsnprintf(buffer, size, "%s%s%s%s%s%s",
121 pin_diag & PIN_DRIVER_OFF ? "driver_off " : "",
122 pin_diag & PIN_OPEN ? "open_load " : "",
123 pin_diag & PIN_SHORT_TO_GND ? "short_to_gnd " : "",
124 pin_diag & PIN_SHORT_TO_BAT ? "short_to_bat " : "",
125 pin_diag & PIN_OVERLOAD ? "overload " : "",
126 pin_diag & PIN_DRIVER_OVERTEMP ? "overtemp": "");
127 } else {
128 chsnprintf(buffer, size, "INVALID");
129 }
130}
131
132static brain_pin_e index_to_brainPin(unsigned int i)
133{
134 if (i < getBrainPinTotalNum())
135 return Gpio::A0 + i;
136
137 return Gpio::Invalid;
138}
139
140static void reportPins() {
141 int totalPinsUsed = 0;
142
143 for (unsigned int i = 0; i < getBrainPinOnchipNum(); i++) {
144 const char *pin_user = getBrainUsedPin(i);
145
146 /* show used pins */
147 if (pin_user) {
148 static char pin_state[64];
149 brain_pin_e brainPin = index_to_brainPin(i);
150 int pin = getBrainPinIndex(brainPin);
151 ioportid_t port = getBrainPinPort(brainPin);
152 debugBrainPin(pin_state, sizeof(pin_state), brainPin);
153
154 const char *boardPinName = getBoardSpecificPinName(brainPin);
155 efiPrintf("pin %s%d (%s): %s %s", portname(port), pin, boardPinName, pin_user, pin_state);
156 totalPinsUsed++;
157 }
158 }
159
160 #if (BOARD_EXT_GPIOCHIPS > 0)
161 for (unsigned int i = getBrainPinOnchipNum() ; i < getBrainPinTotalNum(); i++) {
162 static char pin_error[64];
163 brain_pin_e brainPin = index_to_brainPin(i);
164
165 const char *pin_name = gpiochips_getPinName(brainPin);
166 const char *pin_user = getBrainUsedPin(i);
167 brain_pin_diag_e pin_diag = gpiochips_getDiag(brainPin);
168
169 pinDiag2string(pin_error, sizeof(pin_error), pin_diag);
170
171 /* here show all pins, unused too */
172 if (pin_name) {
173 // this probably uses a lot of output buffer!
174 efiPrintf("ext %s: %s diagnostic: %s",
175 pin_name, pin_user ? pin_user : "free", pin_error);
176 } else {
177 const char *chip_name = gpiochips_getChipName(brainPin);
178 /* if chip exist */
179 if (chip_name) {
180 efiPrintf("ext %s.%d: %s diagnostic: %s",
181 chip_name, gpiochips_getPinOffset(brainPin), pin_user ? pin_user : "free", pin_error);
182 }
183 }
184 if (pin_user) {
185 totalPinsUsed++;
186 }
187 }
188 #endif
189
190 efiPrintf("Total pins used: %d", totalPinsUsed);
191
193}
194
195__attribute__((weak)) const char * getBoardSpecificPinName(brain_pin_e /*brainPin*/) {
196 return nullptr;
197}
198
199const char *hwOnChipPhysicalPinName(ioportid_t hwPort, int hwPin) {
200 portNameStream.eos = 0; // reset
201 if (!hwPort) {
202 return "NONE";
203 }
204 chprintf((BaseSequentialStream *) &portNameStream, "%s%d", portname(hwPort), hwPin);
205 portNameStream.buffer[portNameStream.eos] = 0; // need to terminate explicitly
206 return portNameBuffer;
207}
208
209const char *hwPhysicalPinName(Gpio brainPin) {
210 if (brainPin == Gpio::Invalid) {
211 return "INVALID";
212 }
213 if (brainPin == Gpio::Unassigned) {
214 return "NONE";
215 }
216
217 if (brain_pin_is_onchip(brainPin)) {
218 ioportid_t hwPort = getHwPort("hostname", brainPin);
219 int hwPin = getHwPin("hostname", brainPin);
220 return hwOnChipPhysicalPinName(hwPort, hwPin);
221 }
222 #if (BOARD_EXT_GPIOCHIPS > 0)
223 else {
224 portNameStream.eos = 0; // reset
225 const char *pin_name = gpiochips_getPinName(brainPin);
226
227 if (pin_name) {
228 chprintf((BaseSequentialStream *) &portNameStream, "ext:%s",
229 pin_name);
230 } else {
231 chprintf((BaseSequentialStream *) &portNameStream, "ext:%s.%d",
232 gpiochips_getChipName(brainPin), gpiochips_getPinOffset(brainPin));
233 }
234 portNameStream.buffer[portNameStream.eos] = 0; // need to terminate explicitly
235 return portNameBuffer;
236 }
237 #endif
238 return "unexpected";
239}
240
241const char *hwPortname(brain_pin_e brainPin) {
242 const char * boardSpecificPinName = getBoardSpecificPinName(brainPin);
243 if (boardSpecificPinName != nullptr) {
244 return boardSpecificPinName;
245 }
246 return hwPhysicalPinName(brainPin);
247}
248
250 /**
251 * this method cannot use console because this method is invoked before console is initialized
252 */
253
254 addConsoleAction(CMD_PINS, reportPins);
255
256#if (BOARD_TLE8888_COUNT > 0)
258 addConsoleAction("tle8888init", tle8888_req_init);
259#endif
260}
261
263{
264 if ((brainPin < Gpio::A0) || (brainPin > BRAIN_PIN_ONCHIP_LAST))
265 return false;
266
267 return true;
268}
269
271{
272 if (brainPin > BRAIN_PIN_ONCHIP_LAST)
273 return true;
274
275 return false;
276}
277
278/**
279 * Marks on-chip gpio port-pin as used. Works only for on-chip gpios
280 * To be replaced with brain_pin_markUsed later
281 */
282
283bool gpio_pin_markUsed(ioportid_t port, ioportmask_t pin, const char *msg) {
284 int index = getPortPinIndex(port, pin);
285#ifndef EFI_BOOTLOADER
286// efiPrintf("pin_markUsed: %s on %s", msg, hwOnChipPhysicalPinName(port, pin));
287#endif
288
289 if (getBrainUsedPin(index) != NULL) {
290 /**
291 * todo: the problem is that this warning happens before the console is even
292 * connected, so the warning is never displayed on the console and that's quite a problem!
293 */
294// warning(ObdCode::OBD_PCM_Processor_Fault, "%s%d req by %s used by %s", portname(port), pin, msg, getBrainUsedPin(index));
295 firmwareError(ObdCode::CUSTOM_ERR_PIN_ALREADY_USED_1, "%s%d req by %s used by %s", portname(port), (int)pin, msg, getBrainUsedPin(index));
296 return true;
297 }
298 getBrainUsedPin(index) = msg;
299 return false;
300}
301
302/**
303 * Marks on-chip gpio port-pin as UNused. Works only for on-chip gpios
304 * To be replaced with brain_pin_markUnused later
305 */
306
308 int index = getPortPinIndex(port, pin);
309
310 getBrainUsedPin(index) = nullptr;
311}
312
313const char *getPinFunction(brain_input_pin_e brainPin) {
314 int index;
315
316 index = brainPin_to_index(brainPin);
317 if (index < 0)
318 return NULL;
319
320 return getBrainUsedPin(index);
321}
322#else
323const char *hwPhysicalPinName(Gpio brainPin) {
324 return "N/A";
325}
326const char *hwPortname(Gpio brainPin) {
327 (void)brainPin;
328 return "N/A";
329}
330#endif /* EFI_PROD_CODE */
PinRepository pinRepository
typedef __attribute__
Ignition Mode.
const char *& getBrainUsedPin(size_t idx)
const char * PIN_USED[BRAIN_PIN_TOTAL_PINS]
void addConsoleAction(const char *token, Void callback)
Register console action without parameters.
@ Unassigned
@ Invalid
const char * gpiochips_getChipName(brain_pin_e pin)
Get external chip name.
Definition core.cpp:148
void gpiochips_debug(void)
Definition core.cpp:413
const char * gpiochips_getPinName(brain_pin_e pin)
Get external chip port name.
Definition core.cpp:162
brain_pin_diag_e gpiochips_getDiag(brain_pin_e pin)
Get diagnostic for given gpio.
Definition core.cpp:381
int gpiochips_getPinOffset(brain_pin_e pin)
Definition core.cpp:132
ioportid_t getHwPort(const char *msg, brain_pin_e brainPin)
ioportmask_t getHwPin(const char *msg, brain_pin_e brainPin)
const char * portname(ioportid_t GPIOx)
Console package entry point header.
void firmwareError(ObdCode code, const char *fmt,...)
const char * getBoardSpecificPinName(brain_pin_e brainPin)
uint32_t ioportmask_t
Digital I/O port sized unsigned type.
Definition hal_pal_lld.h:78
GPIO_TypeDef * ioportid_t
Port Identifier.
@ CUSTOM_ERR_PIN_ALREADY_USED_1
int brainPin_to_index(Gpio brainPin)
const char *& getBrainUsedPin(size_t index)
static char portNameBuffer[20]
const char * hwPhysicalPinName(Gpio brainPin)
void gpio_pin_markUnused(ioportid_t port, ioportmask_t pin)
void initPinRepository(void)
void pinDiag2string(char *buffer, size_t size, brain_pin_diag_e pin_diag)
static void reportPins()
const char * hwOnChipPhysicalPinName(ioportid_t hwPort, int hwPin)
const char * hwPortname(brain_pin_e brainPin)
static brain_pin_e index_to_brainPin(unsigned int i)
bool brain_pin_markUsed(Gpio brainPin, const char *msg)
static MemoryStream portNameStream
bool brain_pin_is_onchip(brain_pin_e brainPin)
void brain_pin_markUnused(brain_pin_e brainPin)
const char * getPinFunction(brain_input_pin_e brainPin)
bool isBrainPinValid(brain_pin_e brainPin)
PinRepository pinRepository CCM_OPTIONAL
bool brain_pin_is_ext(brain_pin_e brainPin)
static size_t getBrainPinTotalNum()
bool gpio_pin_markUsed(ioportid_t port, ioportmask_t pin, const char *msg)
size_t getBrainPinOnchipNum()
int getBrainPinIndex(Gpio brainPin)
int getPortPinIndex(ioportid_t port, ioportmask_t pin)
void debugBrainPin(char *buffer, size_t size, brain_pin_e brainPin)
ioportid_t getBrainPinPort(brain_pin_e brainPin)
brain_pin_diag_e
brain_pin_e pin
Definition stm32_adc.cpp:15
void tle8888_dump_regs()
Definition tle8888.cpp:1279
void tle8888_req_init()
Definition tle8888.cpp:1272
composite packet size
static BigBufferHandle buffer