Hellen says drivers

This commit is contained in:
rusefi 2020-09-07 12:00:16 -04:00
parent fea6b48309
commit 02573713f3
3 changed files with 342 additions and 1 deletions

View File

@ -13,7 +13,8 @@ HW_LAYER_DRIVERS = \
$(DRIVERS_DIR)/gpio/tle6240.c \
$(DRIVERS_DIR)/gpio/tle8888.c \
$(DRIVERS_DIR)/gpio/mc33972.c \
$(DRIVERS_DIR)/gpio/mc33810.c
$(DRIVERS_DIR)/gpio/mc33810.c \
$(DRIVERS_DIR)/gpio/drv8860.c \
HW_LAYER_DRIVERS_CPP = \
$(DRIVERS_DIR)/can/can_hw.cpp \

View File

@ -0,0 +1,297 @@
/*
* drv8860.c
*
* DRV8860 Smart 8/16-Channel Low-Side Switch
*
* All channels are controlled via the serial interface (SPI).
* <200 kHz SPI
*
* @date Apr 6, 2020
*
* @author andreika, (c) 2020
* @author Andrey Belomutskiy, (c) 2012-2020
*/
#include "global.h"
#include "gpio/gpio_ext.h"
#include "gpio/drv8860.h"
#include "pin_repository.h"
#include "os_util.h"
#if (BOARD_DRV8860_COUNT > 0)
/*==========================================================================*/
/* Driver local definitions. */
/*==========================================================================*/
#define DRIVER_NAME "drv8860"
static bool drv_task_ready = false;
typedef enum {
DRV8860_DISABLED = 0,
DRV8860_WAIT_INIT,
DRV8860_READY,
DRV8860_FAILED
} drv8860_drv_state;
/*==========================================================================*/
/* Driver exported variables. */
/*==========================================================================*/
/*==========================================================================*/
/* Driver local variables and types. */
/*==========================================================================*/
/* OS */
SEMAPHORE_DECL(drv8860_wake, 10 /* or BOARD_DRV8860_COUNT ? */);
static THD_WORKING_AREA(drv8860_thread_1_wa, 256);
/* Driver */
struct drv8860_priv {
const struct drv8860_config *cfg;
/* cached output state - state last send to chip */
uint16_t o_state_cached;
/* state to be sended to chip */
uint16_t o_state;
drv8860_drv_state drv_state;
};
static struct drv8860_priv chips[BOARD_DRV8860_COUNT];
static const char* drv8860_pin_names[DRV8860_OUTPUTS] = {
"drv8860.OUT1", "drv8860.OUT2", "drv8860.OUT3", "drv8860.OUT4",
"drv8860.OUT5", "drv8860.OUT6", "drv8860.OUT7", "drv8860.OUT8",
"drv8860.OUT9", "drv8860.OUT10", "drv8860.OUT11", "drv8860.OUT12",
"drv8860.OUT13", "drv8860.OUT14", "drv8860.OUT15", "drv8860.OUT16",
};
/*==========================================================================*/
/* Driver local functions. */
/*==========================================================================*/
static SPIDriver *get_bus(struct drv8860_priv *chip) {
/* return non-const SPIDriver* from const struct cfg */
return chip->cfg->spi_bus;
}
/**
* @brief DRV8860 send routine.
* @details Sends 8/16 bits. CS asserted before and released after transaction.
*/
static void drv8860_spi_send(struct drv8860_priv *chip, uint16_t tx) {
SPIDriver *spi = get_bus(chip);
/* Acquire ownership of the bus. */
spiAcquireBus(spi);
/* Setup transfer parameters. */
spiStart(spi, &chip->cfg->spi_config);
/* Slave Select assertion. */
spiSelect(spi);
/* Atomic transfer operations. */
spiPolledExchange(spi, tx);
/* Slave Select de-assertion. */
spiUnselect(spi);
/* Ownership release. */
spiReleaseBus(spi);
}
/**
* @brief DRV8860 send output data.
*/
static void drv8860_update_outputs(struct drv8860_priv *chip) {
/* TODO: lock? */
/* atomic */
/* set value only for non-direct driven pins */
drv8860_spi_send(chip, chip->o_state & 0xffff);
/* atomic */
chip->o_state_cached = chip->o_state;
/* TODO: unlock? */
}
/**
* @brief DRV8860 chip init.
* @details Marks all used pins.
* @todo: Checks direct io signals integrity, read initial diagnostic state.
*/
static int drv8860_chip_init(struct drv8860_priv *chip) {
/* upload pin states */
drv8860_update_outputs(chip);
return 0;
}
/**
* @brief DRV8860 chip driver wakeup.
* @details Wake up driver. Will cause output register update.
*/
static int drv8860_wake_driver(struct drv8860_priv *chip) {
(void)chip;
/* Entering a reentrant critical zone.*/
syssts_t sts = chSysGetStatusAndLockX();
chSemSignalI(&drv8860_wake);
/* Leaving the critical zone.*/
chSysRestoreStatusX(sts);
return 0;
}
/*==========================================================================*/
/* Driver thread. */
/*==========================================================================*/
static THD_FUNCTION(drv8860_driver_thread, p) {
int i;
msg_t msg;
(void)p;
chRegSetThreadName(DRIVER_NAME);
while (1) {
msg = chSemWaitTimeout(&drv8860_wake, TIME_MS2I(DRV8860_POLL_INTERVAL_MS));
/* should we care about msg == MSG_TIMEOUT? */
(void)msg;
for (i = 0; i < BOARD_DRV8860_COUNT; i++) {
struct drv8860_priv *chip;
chip = &chips[i];
if ((chip->cfg == NULL) ||
(chip->drv_state == DRV8860_DISABLED) ||
(chip->drv_state == DRV8860_FAILED))
continue;
drv8860_update_outputs(chip);
}
}
}
/*==========================================================================*/
/* Driver interrupt handlers. */
/*==========================================================================*/
/* TODO: add IRQ support */
/*==========================================================================*/
/* Driver exported functions. */
/*==========================================================================*/
int drv8860_writePad(void *data, unsigned int pin, int value) {
struct drv8860_priv *chip;
if ((pin >= DRV8860_OUTPUTS) || (data == NULL))
return -1;
chip = (struct drv8860_priv *)data;
/* TODO: lock */
if (value)
chip->o_state |= (1 << pin);
else
chip->o_state &= ~(1 << pin);
/* TODO: unlock */
drv8860_wake_driver(chip);
return 0;
}
brain_pin_diag_e drv8860_getDiag(void *data, unsigned int pin) {
// todo: implement diag
return PIN_OK;
}
int drv8860_init(void * data) {
int ret;
struct drv8860_priv *chip;
chip = (struct drv8860_priv *)data;
ret = drv8860_chip_init(chip);
if (ret)
return ret;
chip->drv_state = DRV8860_READY;
if (!drv_task_ready) {
chThdCreateStatic(drv8860_thread_1_wa, sizeof(drv8860_thread_1_wa),
NORMALPRIO + 1, drv8860_driver_thread, NULL);
drv_task_ready = true;
}
return 0;
}
int drv8860_deinit(void *data) {
(void)data;
/* TODO: set all pins to inactive state, stop task? */
return 0;
}
struct gpiochip_ops drv8860_ops = {
.writePad = drv8860_writePad,
.readPad = NULL, /* chip outputs only */
.getDiag = drv8860_getDiag,
.init = drv8860_init,
.deinit = drv8860_deinit,
};
/**
* @brief DRV8860 driver add.
* @details Checks for valid config
*/
int drv8860_add(unsigned int index, const struct drv8860_config *cfg) {
int i;
int ret;
struct drv8860_priv *chip;
/* no config or no such chip */
if ((!cfg) || (!cfg->spi_bus) || (index >= BOARD_DRV8860_COUNT))
return -1;
/* check for valid cs.
* TODO: remove this check? CS can be driven by SPI */
//if (cfg->spi_config.ssport == NULL)
// return -1;
chip = &chips[index];
/* already initted? */
if (chip->cfg != NULL)
return -1;
chip->cfg = cfg;
chip->o_state = 0;
chip->o_state_cached = 0;
chip->drv_state = DRV8860_WAIT_INIT;
/* register, return gpio chip base */
ret = gpiochip_register(DRIVER_NAME, &drv8860_ops, DRV8860_OUTPUTS, chip);
/* set default pin names, board init code can rewrite */
gpiochips_setPinNames(ret, drv8860_pin_names);
return ret;
}
#else /* BOARD_DRV8860_COUNT > 0 */
int drv8860_add(unsigned int index, const struct drv8860_config *cfg) {
(void)index; (void)cfg;
return -1;
}
#endif /* BOARD_DRV8860_COUNT */

View File

@ -0,0 +1,43 @@
/*
* drv8860.h
*
* DRV8860 Smart 8/16-Channel Low-Side Switch
*
* @date Apr 6, 2020
*
* @author andreika, (c) 2020
* @author Andrey Belomutskiy, (c) 2012-2020
*/
#ifndef HW_LAYER_DRV8860_H_
#define HW_LAYER_DRV8860_H_
#include "efifeatures.h"
#include <hal.h>
#define DRV8860_OUTPUTS 16
/* TODO: add irq support */
#define DRV8860_POLL_INTERVAL_MS 500
struct drv8860_config {
SPIDriver *spi_bus;
SPIConfig spi_config;
struct {
ioportid_t port;
uint_fast8_t pad;
} reset;
};
#ifdef __cplusplus
extern "C"
{
#endif /* __cplusplus */
int drv8860_add(unsigned int index, const struct drv8860_config *cfg);
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* HW_LAYER_DRV8860_H_ */