rusEFI
The most advanced open source ECU
Loading...
Searching...
No Matches
drv8860.cpp
Go to the documentation of this file.
1/*
2 * drv8860.c
3 *
4 * DRV8860 Smart 8/16-Channel Low-Side Switch
5 *
6 * All channels are controlled via the serial interface (SPI).
7 * <200 kHz SPI
8 *
9 * @date Apr 6, 2020
10 *
11 * @author andreika, (c) 2020
12 * @author Andrey Belomutskiy, (c) 2012-2020
13 */
14
15#include "pch.h"
16
17#include "gpio/gpio_ext.h"
18#include "gpio/drv8860.h"
19
20#if EFI_PROD_CODE && (BOARD_DRV8860_COUNT > 0)
21
22/*==========================================================================*/
23/* Driver local definitions. */
24/*==========================================================================*/
25
26#define DRIVER_NAME "drv8860"
27
28static bool drv_task_ready = false;
29
36
37/*==========================================================================*/
38/* Driver exported variables. */
39/*==========================================================================*/
40
41/*==========================================================================*/
42/* Driver local variables and types. */
43/*==========================================================================*/
44
45/* OS */
46SEMAPHORE_DECL(drv8860_wake, 10 /* or BOARD_DRV8860_COUNT ? */);
47static THD_WORKING_AREA(drv8860_thread_1_wa, 256);
48
49/* Driver */
50struct Drv8860 : public GpioChip {
51 int init() override;
52
53 int writePad(size_t pin, int value) override;
54 brain_pin_diag_e getDiag(size_t pin) override;
55
56 // Internal helpers
57 int chip_init();
58
59 void spi_send(uint16_t tx);
60
61 void update_outputs();
62 int wake_driver();
63
64 const drv8860_config *cfg;
65 /* cached output state - state last send to chip */
66 uint16_t o_state_cached;
67 /* state to be sended to chip */
68 uint16_t o_state;
69
70 drv8860_drv_state drv_state;
71};
72
73static Drv8860 chips[BOARD_DRV8860_COUNT];
74
75static const char* drv8860_pin_names[DRV8860_OUTPUTS] = {
76 "drv8860.OUT1", "drv8860.OUT2", "drv8860.OUT3", "drv8860.OUT4",
77 "drv8860.OUT5", "drv8860.OUT6", "drv8860.OUT7", "drv8860.OUT8",
78 "drv8860.OUT9", "drv8860.OUT10", "drv8860.OUT11", "drv8860.OUT12",
79 "drv8860.OUT13", "drv8860.OUT14", "drv8860.OUT15", "drv8860.OUT16",
80};
81
82/*==========================================================================*/
83/* Driver local functions. */
84/*==========================================================================*/
85
86/**
87 * @brief DRV8860 send routine.
88 * @details Sends 8/16 bits. CS asserted before and released after transaction.
89 */
90
91void Drv8860::spi_send(uint16_t tx) {
92 SPIDriver *spi = cfg->spi_bus;
93
94 /* Acquire ownership of the bus. */
95 spiAcquireBus(spi);
96 /* Setup transfer parameters. */
97 spiStart(spi, &cfg->spi_config);
98 /* Slave Select assertion. */
99 spiSelect(spi);
100 /* Atomic transfer operations. */
101 spiPolledExchange(spi, tx);
102 /* Slave Select de-assertion. */
103 spiUnselect(spi);
104 /* Ownership release. */
105 spiReleaseBus(spi);
106}
107
108/**
109 * @brief DRV8860 send output data.
110 */
111
112void Drv8860::update_outputs() {
113 /* TODO: lock? */
114
115 /* atomic */
116 /* set value only for non-direct driven pins */
117 spi_send(o_state & 0xffff);
118
119 /* atomic */
120 o_state_cached = o_state;
121
122 /* TODO: unlock? */
123}
124
125/**
126 * @brief DRV8860 chip init.
127 * @details Marks all used pins.
128 * @todo: Checks direct io signals integrity, read initial diagnostic state.
129 */
130
131int Drv8860::chip_init() {
132 /* upload pin states */
133 update_outputs();
134
135 return 0;
136}
137
138/**
139 * @brief DRV8860 chip driver wakeup.
140 * @details Wake up driver. Will cause output register update.
141 */
142
143int Drv8860::wake_driver() {
144 /* Entering a reentrant critical zone.*/
145 chibios_rt::CriticalSectionLocker csl;
146
147 chSemSignalI(&drv8860_wake);
148
149 return 0;
150}
151
152/*==========================================================================*/
153/* Driver thread. */
154/*==========================================================================*/
155
156static THD_FUNCTION(drv8860_driver_thread, p) {
157 int i;
158 msg_t msg;
159
160 (void)p;
161
162 chRegSetThreadName(DRIVER_NAME);
163
164 while (1) {
165 msg = chSemWaitTimeout(&drv8860_wake, TIME_MS2I(DRV8860_POLL_INTERVAL_MS));
166
167 /* should we care about msg == MSG_TIMEOUT? */
168 (void)msg;
169
170 for (i = 0; i < BOARD_DRV8860_COUNT; i++) {
171 auto chip = &chips[i];
172 if ((chip->cfg == NULL) ||
173 (chip->drv_state == DRV8860_DISABLED) ||
174 (chip->drv_state == DRV8860_FAILED))
175 continue;
176
177 chip->update_outputs();
178 }
179 }
180}
181
182/*==========================================================================*/
183/* Driver interrupt handlers. */
184/*==========================================================================*/
185
186/* TODO: add IRQ support */
187
188/*==========================================================================*/
189/* Driver exported functions. */
190/*==========================================================================*/
191
192int Drv8860::writePad(size_t pin, int value) {
193 if (pin >= DRV8860_OUTPUTS)
194 return -1;
195
196 /* TODO: lock */
197 if (value)
198 o_state |= (1 << pin);
199 else
200 o_state &= ~(1 << pin);
201 /* TODO: unlock */
202 wake_driver();
203
204 return 0;
205}
206
207brain_pin_diag_e Drv8860::getDiag(size_t /*pin*/) {
208 // todo: implement diag
209 return PIN_OK;
210}
211
212int Drv8860::init() {
213 int ret;
214
215 ret = chip_init();
216 if (ret)
217 return ret;
218
219 drv_state = DRV8860_READY;
220
221 if (!drv_task_ready) {
222 chThdCreateStatic(drv8860_thread_1_wa, sizeof(drv8860_thread_1_wa),
223 PRIO_GPIOCHIP, drv8860_driver_thread, NULL);
224 drv_task_ready = true;
225 }
226
227 return 0;
228}
229
230/**
231 * @brief DRV8860 driver add.
232 * @details Checks for valid config
233 */
234
235int drv8860_add(brain_pin_e base, unsigned int index, const drv8860_config *cfg) {
236 int ret;
237
238 /* no config or no such chip */
239 if ((!cfg) || (!cfg->spi_bus) || (index >= BOARD_DRV8860_COUNT))
240 return -1;
241
242 /* check for valid cs.
243 * TODO: remove this check? CS can be driven by SPI */
244 //if (cfg->spi_config.ssport == NULL)
245 // return -1;
246
247 auto& chip = chips[index];
248
249 /* already initted? */
250 if (!chip.cfg)
251 return -1;
252
253 chip.cfg = cfg;
254 chip.o_state = 0;
255 chip.o_state_cached = 0;
256 chip.drv_state = DRV8860_WAIT_INIT;
257
258 /* register, return gpio chip base */
259 ret = gpiochip_register(base, DRIVER_NAME, chip, DRV8860_OUTPUTS);
260 if (ret < 0)
261 return ret;
262
263 /* set default pin names, board init code can rewrite */
265
266 return ret;
267}
268
269#else /* BOARD_DRV8860_COUNT > 0 */
270
271int drv8860_add(brain_pin_e base, unsigned int index, const drv8860_config *cfg) {
272 (void)base; (void)index; (void)cfg;
273
274 return -1;
275}
276
277#endif /* BOARD_DRV8860_COUNT */
int gpiochip_register(brain_pin_e base, const char *name, GpioChip &gpioChip, size_t size)
Register gpiochip.
Definition core.cpp:186
int gpiochips_setPinNames(brain_pin_e base, const char **names)
Set pins names for registered gpiochip.
Definition core.cpp:266
static bool drv_task_ready
Definition drv8860.cpp:28
static const char * drv8860_pin_names[DRV8860_OUTPUTS]
Definition drv8860.cpp:75
SEMAPHORE_DECL(drv8860_wake, 10)
static Drv8860 chips[BOARD_DRV8860_COUNT]
Definition drv8860.cpp:73
drv8860_drv_state
Definition drv8860.cpp:30
@ DRV8860_FAILED
Definition drv8860.cpp:34
@ DRV8860_WAIT_INIT
Definition drv8860.cpp:32
@ DRV8860_READY
Definition drv8860.cpp:33
@ DRV8860_DISABLED
Definition drv8860.cpp:31
static THD_FUNCTION(drv8860_driver_thread, p)
Definition drv8860.cpp:156
int drv8860_add(brain_pin_e base, unsigned int index, const drv8860_config *cfg)
DRV8860 driver add.
Definition drv8860.cpp:235
static THD_WORKING_AREA(drv8860_thread_1_wa, 256)
brain_pin_diag_e
brain_pin_e pin
Definition stm32_adc.cpp:15
virtual brain_pin_diag_e getDiag(size_t)
Definition gpio_ext.h:31
virtual int writePad(size_t, int)
Definition gpio_ext.h:28
virtual int init()=0
SPIDriver * spi_bus
Definition drv8860.h:24