1
0
Fork 0
mirror of https://github.com/betaflight/betaflight.git synced 2025-07-15 04:15:44 +03:00

SPI CS preinit for configurability

This commit is contained in:
jflyper 2018-05-18 17:22:58 +09:00
parent ca09a8e2fc
commit f9a43099db
22 changed files with 219 additions and 113 deletions

View file

@ -86,9 +86,7 @@ void bmp280BusDeinit(busDevice_t *busdev)
{
#ifdef USE_BARO_SPI_BMP280
if (busdev->bustype == BUSTYPE_SPI) {
IOConfigGPIO(busdev->busdev_u.spi.csnPin, IOCFG_IPU);
IORelease(busdev->busdev_u.spi.csnPin);
IOInit(busdev->busdev_u.spi.csnPin, OWNER_SPI_PREINIT, 0);
spiPreinitCsByIO(busdev->busdev_u.spi.csnPin);
}
#else
UNUSED(busdev);

View file

@ -82,9 +82,7 @@ void ms5611BusDeinit(busDevice_t *busdev)
{
#ifdef USE_BARO_SPI_MS5611
if (busdev->bustype == BUSTYPE_SPI) {
IOConfigGPIO(busdev->busdev_u.spi.csnPin, IOCFG_IPU);
IORelease(busdev->busdev_u.spi.csnPin);
IOInit(busdev->busdev_u.spi.csnPin, OWNER_SPI_PREINIT, 0);
spiPreinitCsByIO(busdev->busdev_u.spi.csnPin);
}
#else
UNUSED(busdev);

View file

@ -92,8 +92,13 @@ typedef enum SPIDevice {
#define SPI_CFG_TO_DEV(x) ((x) - 1)
#define SPI_DEV_TO_CFG(x) ((x) + 1)
void spiPreInitCs(ioTag_t iotag);
void spiPreInitCsOutPU(ioTag_t iotag);
// Size of SPI CS pre-initialization tag arrays
#define SPI_PREINIT_IPU_COUNT 8
#define SPI_PREINIT_OPU_COUNT 2
void spiPreinitCsByTag(ioTag_t iotag);
void spiPreinitCsByIO(IO_t io);
void spiPreInit(void);
bool spiInit(SPIDevice device);
void spiSetDivisor(SPI_TypeDef *instance, uint16_t divisor);

View file

@ -28,33 +28,80 @@
#include "drivers/bus_spi.h"
#include "drivers/io.h"
#include "pg/bus_spi.h"
// Bring a pin for possible CS line to pull-up state in preparation for
// sequential initialization by relevant drivers.
// There are two versions:
// spiPreInitCs set the pin to input with pullup (IOCFG_IPU) for safety at this point.
// spiPreInitCsOutPU which actually drive the pin for digital hi.
// There are two versions locally:
// spiPreInitCsIPU set the pin to input with pullup (IOCFG_IPU) for safety.
// spiPreInitCsOPU actually drive the pin for digital hi.
//
// The later is required for SPI slave devices on some targets, interfaced through level shifters, such as Kakute F4.
// Note that with this handling, a pin declared as CS pin for MAX7456 needs special care when re-purposing the pin for other, especially, input uses.
// This will/should be fixed when we go fully reconfigurable.
//
// Two ioTag_t array PGs, spiPreinitIPUConfig and spiPreinitOPUConfig are used to
// determine pin to be IPU or OPU.
// The IPU array is initialized with a hard coded initialization array,
// while the OPU array is initialized from target dependent config.c.
// With generic targets, both arrays are setup with resource commands.
void spiPreInitCs(ioTag_t iotag)
static void spiPreInitCsIPU(ioTag_t iotag, int index)
{
IO_t io = IOGetByTag(iotag);
if (io) {
IOInit(io, OWNER_SPI_PREINIT, 0);
IOInit(io, OWNER_SPI_PREINIT_IPU, index);
IOConfigGPIO(io, IOCFG_IPU);
IOHi(io);
}
}
void spiPreInitCsOutPU(ioTag_t iotag)
static void spiPreInitCsOPU(ioTag_t iotag, int index)
{
IO_t io = IOGetByTag(iotag);
if (io) {
IOInit(io, OWNER_SPI_PREINIT, 0);
IOInit(io, OWNER_SPI_PREINIT_OPU, index);
IOConfigGPIO(io, IOCFG_OUT_PP);
IOHi(io);
}
}
void spiPreInit(void)
{
for (int i = 0 ; i < SPI_PREINIT_IPU_COUNT ; i++) {
if (spiPreinitIPUConfig(i)->csnTag) {
spiPreInitCsIPU(spiPreinitIPUConfig(i)->csnTag, i);
}
}
for (int i = 0 ; i < SPI_PREINIT_OPU_COUNT ; i++) {
if (spiPreinitOPUConfig(i)->csnTag) {
spiPreInitCsOPU(spiPreinitOPUConfig(i)->csnTag, i);
}
}
}
// Back to pre-init state
void spiPreinitCsByIO(IO_t io)
{
for (int i = 0 ; i < SPI_PREINIT_IPU_COUNT ; i++) {
if (IOGetByTag(spiPreinitIPUConfig(i)->csnTag) == io) {
spiPreInitCsIPU(spiPreinitIPUConfig(i)->csnTag, i);
return;
}
}
for (int i = 0 ; i < SPI_PREINIT_OPU_COUNT ; i++) {
if (IOGetByTag(spiPreinitOPUConfig(i)->csnTag) == io) {
spiPreInitCsOPU(spiPreinitOPUConfig(i)->csnTag, i);
return;
}
}
}
void spiPreinitCsByTag(ioTag_t iotag)
{
spiPreinitCsByIO(IOGetByTag(iotag));
}
#endif

View file

@ -410,9 +410,7 @@ void ak8963BusDeInit(const busDevice_t *busdev)
#ifdef USE_MAG_SPI_AK8963
case BUSTYPE_SPI:
IOConfigGPIO(busdev->busdev_u.spi.csnPin, IOCFG_IPU);
IORelease(busdev->busdev_u.spi.csnPin);
IOInit(busdev->busdev_u.spi.csnPin, OWNER_SPI_PREINIT, 0);
spiPreinitCsByIO(busdev->busdev_u.spi.csnPin);
break;
#endif

View file

@ -52,7 +52,7 @@ bool flashInit(const flashConfig_t *flashConfig)
return false;
}
if (IOGetOwner(busdev->busdev_u.spi.csnPin) != OWNER_SPI_PREINIT) {
if (!IOIsFreeOrPreinit(busdev->busdev_u.spi.csnPin)) {
return false;
}
@ -99,7 +99,7 @@ bool flashInit(const flashConfig_t *flashConfig)
}
#endif
spiPreInitCs(flashConfig->csTag);
spiPreinitCsByTag(flashConfig->csTag);
return false;
}

View file

@ -275,6 +275,17 @@ resourceOwner_e IOGetOwner(IO_t io)
return ioRec->owner;
}
bool IOIsFreeOrPreinit(IO_t io)
{
resourceOwner_e owner = IOGetOwner(io);
if (owner == OWNER_FREE || owner == OWNER_SPI_PREINIT_IPU || owner == OWNER_SPI_PREINIT_OPU) {
return true;
}
return false;
}
#if defined(STM32F1)
void IOConfigGPIO(IO_t io, ioConfig_t cfg)
@ -414,3 +425,4 @@ IO_t IOGetByTag(ioTag_t tag)
offset += ioDefUsedOffset[portIdx];
return ioRecs + offset;
}

View file

@ -110,6 +110,7 @@ void IOToggle(IO_t io);
void IOInit(IO_t io, resourceOwner_e owner, uint8_t index);
void IORelease(IO_t io); // unimplemented
resourceOwner_e IOGetOwner(IO_t io);
bool IOIsFreeOrPreinit(IO_t io);
IO_t IOGetByTag(ioTag_t tag);
void IOConfigGPIO(IO_t io, ioConfig_t cfg);

View file

@ -425,7 +425,7 @@ void max7456Init(const max7456Config_t *max7456Config, const vcdProfile_t *pVcdP
busdev->busdev_u.spi.csnPin = IOGetByTag(max7456Config->csTag);
if (IOGetOwner(busdev->busdev_u.spi.csnPin) != OWNER_SPI_PREINIT) {
if (!IOIsFreeOrPreinit(busdev->busdev_u.spi.csnPin)) {
return;
}

View file

@ -66,7 +66,6 @@ const char * const ownerNames[OWNER_TOTAL_COUNT] = {
"TRANSPONDER",
"VTX",
"COMPASS_CS",
"SPI_PREINIT",
"RX_BIND_PLUG",
"ESCSERIAL",
"CAMERA_CONTROL",
@ -75,4 +74,6 @@ const char * const ownerNames[OWNER_TOTAL_COUNT] = {
"RX_SPI",
"PINIO",
"USB_MSC_PIN",
"SPI_PREINIT_IPU",
"SPI_PREINIT_OPU",
};

View file

@ -66,7 +66,6 @@ typedef enum {
OWNER_TRANSPONDER,
OWNER_VTX,
OWNER_COMPASS_CS,
OWNER_SPI_PREINIT,
OWNER_RX_BIND_PLUG,
OWNER_ESCSERIAL,
OWNER_CAMERA_CONTROL,
@ -75,6 +74,8 @@ typedef enum {
OWNER_RX_SPI,
OWNER_PINIO,
OWNER_USB_MSC_PIN,
OWNER_SPI_PREINIT_IPU,
OWNER_SPI_PREINIT_OPU,
OWNER_TOTAL_COUNT
} resourceOwner_e;

View file

@ -197,73 +197,6 @@ static IO_t busSwitchResetPin = IO_NONE;
}
#endif
#ifdef USE_SPI
// Pre-initialize all CS pins to input with pull-up.
// It's sad that we can't do this with an initialized array,
// since we will be taking care of configurable CS pins shortly.
void spiPreInit(void)
{
#ifdef GYRO_1_CS_PIN
spiPreInitCs(IO_TAG(GYRO_1_CS_PIN));
#endif
#ifdef GYRO_2_CS_PIN
spiPreInitCs(IO_TAG(GYRO_2_CS_PIN));
#endif
#ifdef MPU6000_CS_PIN
spiPreInitCs(IO_TAG(MPU6000_CS_PIN));
#endif
#ifdef MPU6500_CS_PIN
spiPreInitCs(IO_TAG(MPU6500_CS_PIN));
#endif
#ifdef MPU9250_CS_PIN
spiPreInitCs(IO_TAG(MPU9250_CS_PIN));
#endif
#ifdef ICM20649_CS_PIN
spiPreInitCs(IO_TAG(ICM20649_CS_PIN));
#endif
#ifdef ICM20689_CS_PIN
spiPreInitCs(IO_TAG(ICM20689_CS_PIN));
#endif
#ifdef BMI160_CS_PIN
spiPreInitCs(IO_TAG(BMI160_CS_PIN));
#endif
#ifdef L3GD20_CS_PIN
spiPreInitCs(IO_TAG(L3GD20_CS_PIN));
#endif
#ifdef MAX7456_SPI_CS_PIN
spiPreInitCsOutPU(IO_TAG(MAX7456_SPI_CS_PIN)); // XXX 3.2 workaround for Kakute F4. See comment for spiPreInitCSOutPU.
#endif
#ifdef USE_SDCARD
spiPreInitCs(sdcardConfig()->chipSelectTag);
#endif
#ifdef BMP280_CS_PIN
spiPreInitCs(IO_TAG(BMP280_CS_PIN));
#endif
#ifdef MS5611_CS_PIN
spiPreInitCs(IO_TAG(MS5611_CS_PIN));
#endif
#ifdef LPS_CS_PIN
spiPreInitCs(IO_TAG(LPS_CS_PIN));
#endif
#ifdef HMC5883_CS_PIN
spiPreInitCs(IO_TAG(HMC5883_CS_PIN));
#endif
#ifdef AK8963_CS_PIN
spiPreInitCs(IO_TAG(AK8963_CS_PIN));
#endif
#if defined(RTC6705_CS_PIN) && !defined(USE_VTX_RTC6705_SOFTSPI) // RTC6705 soft SPI initialisation handled elsewhere.
spiPreInitCs(IO_TAG(RTC6705_CS_PIN));
#endif
#ifdef FLASH_CS_PIN
spiPreInitCs(IO_TAG(FLASH_CS_PIN));
#endif
#if defined(USE_RX_SPI)
spiPreInitCs(IO_TAG(RX_NSS_PIN));
#endif
}
#endif
void init(void)
{
#ifdef USE_ITCM_RAM

View file

@ -3580,6 +3580,10 @@ const cliResourceValue_t resourceTable[] = {
#ifdef USE_MAX7456
DEFS( OWNER_OSD_CS, PG_MAX7456_CONFIG, max7456Config_t, csTag ),
#endif
#ifdef USE_SPI
DEFA( OWNER_SPI_PREINIT_IPU, PG_SPI_PREINIT_IPU_CONFIG, spiCs_t, csnTag, SPI_PREINIT_IPU_COUNT ),
DEFA( OWNER_SPI_PREINIT_OPU, PG_SPI_PREINIT_OPU_CONFIG, spiCs_t, csnTag, SPI_PREINIT_OPU_COUNT ),
#endif
};
#undef DEFS

View file

@ -123,20 +123,6 @@ static IO_t busSwitchResetPin = IO_NONE;
}
#endif
#ifdef USE_SPI
// Pre-initialize all CS pins to input with pull-up.
// It's sad that we can't do this with an initialized array,
// since we will be taking care of configurable CS pins shortly.
void spiPreInit(void)
{
#ifdef USE_MAX7456
spiPreInitCs(IO_TAG(MAX7456_SPI_CS_PIN));
#endif
}
#endif
void init(void)
{
#ifdef USE_HAL_DRIVER

View file

@ -62,4 +62,87 @@ void pgResetFn_spiPinConfig(spiPinConfig_t *spiPinConfig)
spiPinConfig[defconf->device].ioTagMosi = defconf->mosi;
}
}
PG_REGISTER_ARRAY_WITH_RESET_FN(spiCs_t, SPI_PREINIT_IPU_COUNT, spiPreinitIPUConfig, PG_SPI_PREINIT_IPU_CONFIG, 0);
PG_REGISTER_ARRAY(spiCs_t, SPI_PREINIT_OPU_COUNT, spiPreinitOPUConfig, PG_SPI_PREINIT_OPU_CONFIG, 0);
// Initialization values for input pull-up are listed here.
// Explicit output with pull-up should handled in target dependent config.c.
// Generic target will be specifying both values by resource commands.
ioTag_t preinitIPUList[SPI_PREINIT_IPU_COUNT] = {
#ifdef GYRO_1_CS_PIN
IO_TAG(GYRO_1_CS_PIN),
#endif
#ifdef GYRO_2_CS_PIN
IO_TAG(GYRO_2_CS_PIN),
#endif
#ifdef MPU6000_CS_PIN
IO_TAG(MPU6000_CS_PIN),
#endif
#ifdef MPU6500_CS_PIN
IO_TAG(MPU6500_CS_PIN),
#endif
#ifdef MPU9250_CS_PIN
IO_TAG(MPU9250_CS_PIN),
#endif
#ifdef ICM20649_CS_PIN
IO_TAG(ICM20649_CS_PIN),
#endif
#ifdef ICM20689_CS_PIN
IO_TAG(ICM20689_CS_PIN),
#endif
#ifdef BMI160_CS_PIN
IO_TAG(BMI160_CS_PIN),
#endif
#ifdef L3GD20_CS_PIN
IO_TAG(L3GD20_CS_PIN),
#endif
#ifdef SDCARD_SPI_CS_PIN
IO_TAG(SDCARD_SPI_CS_PIN),
#endif
#ifdef BMP280_CS_PIN
IO_TAG(BMP280_CS_PIN),
#endif
#ifdef MS5611_CS_PIN
IO_TAG(MS5611_CS_PIN),
#endif
#ifdef LPS_CS_PIN
IO_TAG(LPS_CS_PIN),
#endif
#ifdef HMC5883_CS_PIN
IO_TAG(HMC5883_CS_PIN),
#endif
#ifdef AK8963_CS_PIN
IO_TAG(AK8963_CS_PIN),
#endif
#if defined(RTC6705_CS_PIN) && !defined(USE_VTX_RTC6705_SOFTSPI) // RTC6705 soft SPI initialisation handled elsewhere.
IO_TAG(RTC6705_CS_PIN),
#endif
#ifdef FLASH_CS_PIN
IO_TAG(FLASH_CS_PIN),
#endif
#if defined(USE_RX_SPI) && !defined(USE_RX_SOFTSPI)
IO_TAG(RX_NSS_PIN),
#endif
#if defined(MAX7456_SPI_CS_PIN)
IO_TAG(MAX7456_SPI_CS_PIN),
#endif
IO_TAG(NONE)
};
void pgResetFn_spiPreinitIPUConfig(spiCs_t *config)
{
int puPins = 0;
for (int i = 0 ; i < SPI_PREINIT_IPU_COUNT ; i++) {
for (int j = 0 ; j < i ; j++) {
if (config[j].csnTag == preinitIPUList[i]) {
goto next;
}
}
config[puPins++].csnTag = preinitIPUList[i];
next:;
}
}
#endif

View file

@ -32,3 +32,12 @@ typedef struct spiPinConfig_s {
} spiPinConfig_t;
PG_DECLARE_ARRAY(spiPinConfig_t, SPIDEV_COUNT, spiPinConfig);
// Place holder for CS pins for pre-initialization
typedef struct spiCs_s {
ioTag_t csnTag;
} spiCs_t;
PG_DECLARE_ARRAY(spiCs_t, SPI_PREINIT_IPU_COUNT, spiPreinitIPUConfig);
PG_DECLARE_ARRAY(spiCs_t, SPI_PREINIT_OPU_COUNT, spiPreinitOPUConfig);

View file

@ -129,7 +129,9 @@
#define PG_SDIO_CONFIG 532
#define PG_DISPLAY_PORT_CRSF_CONFIG 533 // no longer required -- never released
#define PG_TIMER_IO_CONFIG 534 // used to store the index for timer use in timerHardware array in target.c
#define PG_BETAFLIGHT_END 534
#define PG_SPI_PREINIT_IPU_CONFIG 535
#define PG_SPI_PREINIT_OPU_CONFIG 536
#define PG_BETAFLIGHT_END 536
// OSD configuration (subject to change)

View file

@ -25,13 +25,11 @@
#ifdef USE_TARGET_CONFIG
#include "io/serial.h"
#include "rx/rx.h"
#include "telemetry/telemetry.h"
#include "config_helper.h"
#include "io/serial.h"
#include "pg/bus_spi.h"
#include "rx/rx.h"
#include "telemetry/telemetry.h"
#define TELEMETRY_UART SERIAL_PORT_USART1
@ -44,5 +42,23 @@ void targetConfiguration(void)
targetSerialPortFunctionConfig(targetSerialPortFunction, ARRAYLEN(targetSerialPortFunction));
telemetryConfigMutable()->halfDuplex = 0;
telemetryConfigMutable()->telemetry_inverted = true;
// Register MAX7456 CS pin as OPU
// Invalidate IPU entry first
for (int i = 0 ; i < SPI_PREINIT_IPU_COUNT ; i++) {
if (spiPreinitIPUConfig(i)->csnTag == IO_TAG(MAX7456_SPI_CS_PIN)) {
spiPreinitIPUConfigMutable(i)->csnTag = IO_TAG(NONE);
break;
}
}
// Add as OPU entry
for (int i = 0 ; i < SPI_PREINIT_OPU_COUNT ; i++) {
if (spiPreinitOPUConfig(i)->csnTag == IO_TAG(NONE)) {
spiPreinitOPUConfigMutable(i)->csnTag = IO_TAG(MAX7456_SPI_CS_PIN);
break;
}
}
}
#endif

View file

@ -30,6 +30,10 @@ resource SPI_SCK 3 C10
resource SPI_MISO 3 C11
resource SPI_MOSI 3 C12
# SPI CS pins to pre-initialize
resource SPI_PREINIT_IPU 1 C04 // MPU6500
resource SPI_PREINIT_IPU 2 A15 // SDCARD
# Timers
# First four timers
# timer is zero origin

View file

@ -20,6 +20,7 @@
// pg/max7456
#ifdef USE_MAX7456
#ifndef MAX7456_CLOCK_CONFIG_DEFAULT
#define MAX7456_CLOCK_CONFIG_DEFAULT MAX7456_CLOCK_CONFIG_OC
#endif
@ -27,6 +28,7 @@
#ifndef MAX7456_SPI_CS_PIN
#define MAX7456_SPI_CS_PIN NONE
#endif
#endif
// pg/bus_i2c

View file

@ -150,6 +150,9 @@ bool busWriteRegister(const busDevice_t*, uint8_t, uint8_t) {return true;}
void spiSetDivisor() {
}
void spiPreinitCsByIO() {
}
void IOConfigGPIO() {
}

View file

@ -152,6 +152,9 @@ bool busWriteRegister(const busDevice_t*, uint8_t, uint8_t) {return true;}
void spiSetDivisor() {
}
void spiPreinitCsByIO() {
}
void IOConfigGPIO() {
}