mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2025-02-27 16:54:15 +01:00
Update the F1 SPI library to support multiple NSS lines
This commit is contained in:
parent
5fd458426a
commit
aaf1c5dfdd
@ -7,7 +7,7 @@
|
|||||||
* @{
|
* @{
|
||||||
*
|
*
|
||||||
* @file pios_spi.c
|
* @file pios_spi.c
|
||||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2012.
|
||||||
* @brief Hardware Abstraction Layer for SPI ports of STM32
|
* @brief Hardware Abstraction Layer for SPI ports of STM32
|
||||||
* @see The GNU Public License (GPL) Version 3
|
* @see The GNU Public License (GPL) Version 3
|
||||||
* @notes
|
* @notes
|
||||||
@ -70,6 +70,8 @@ static struct pios_spi_dev * PIOS_SPI_alloc(void)
|
|||||||
*/
|
*/
|
||||||
int32_t PIOS_SPI_Init(uint32_t * spi_id, const struct pios_spi_cfg * cfg)
|
int32_t PIOS_SPI_Init(uint32_t * spi_id, const struct pios_spi_cfg * cfg)
|
||||||
{
|
{
|
||||||
|
uint32_t init_ssel = 0;
|
||||||
|
|
||||||
PIOS_Assert(spi_id);
|
PIOS_Assert(spi_id);
|
||||||
PIOS_Assert(cfg);
|
PIOS_Assert(cfg);
|
||||||
|
|
||||||
@ -100,18 +102,20 @@ int32_t PIOS_SPI_Init(uint32_t * spi_id, const struct pios_spi_cfg * cfg)
|
|||||||
if (spi_dev->cfg->init.SPI_Mode == SPI_Mode_Master) {
|
if (spi_dev->cfg->init.SPI_Mode == SPI_Mode_Master) {
|
||||||
/* We're a master in soft NSS mode, make sure we see NSS high at all times. */
|
/* We're a master in soft NSS mode, make sure we see NSS high at all times. */
|
||||||
SPI_NSSInternalSoftwareConfig(spi_dev->cfg->regs, SPI_NSSInternalSoft_Set);
|
SPI_NSSInternalSoftwareConfig(spi_dev->cfg->regs, SPI_NSSInternalSoft_Set);
|
||||||
/* Since we're driving the SSEL pin in software, ensure that the slave is deselected */
|
/* Init as many slave selects as the config advertises. */
|
||||||
GPIO_SetBits(spi_dev->cfg->ssel.gpio, spi_dev->cfg->ssel.init.GPIO_Pin);
|
init_ssel = spi_dev->cfg->slave_count;
|
||||||
GPIO_Init(spi_dev->cfg->ssel.gpio, &(spi_dev->cfg->ssel.init));
|
|
||||||
} else {
|
} else {
|
||||||
/* We're a slave in soft NSS mode, make sure we see NSS low at all times. */
|
/* We're a slave in soft NSS mode, make sure we see NSS low at all times. */
|
||||||
SPI_NSSInternalSoftwareConfig(spi_dev->cfg->regs, SPI_NSSInternalSoft_Reset);
|
SPI_NSSInternalSoftwareConfig(spi_dev->cfg->regs, SPI_NSSInternalSoft_Reset);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SPI_NSS_Hard:
|
case SPI_NSS_Hard:
|
||||||
|
/* only legal for single-slave config */
|
||||||
|
PIOS_Assert(spi_dev->cfg->slave_count == 1);
|
||||||
|
init_ssel = 1;
|
||||||
/* FIXME: Should this also call SPI_SSOutputCmd()? */
|
/* FIXME: Should this also call SPI_SSOutputCmd()? */
|
||||||
GPIO_Init(spi_dev->cfg->ssel.gpio, &(spi_dev->cfg->ssel.init));
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
PIOS_Assert(0);
|
PIOS_Assert(0);
|
||||||
}
|
}
|
||||||
@ -120,6 +124,12 @@ int32_t PIOS_SPI_Init(uint32_t * spi_id, const struct pios_spi_cfg * cfg)
|
|||||||
GPIO_Init(spi_dev->cfg->sclk.gpio, &(spi_dev->cfg->sclk.init));
|
GPIO_Init(spi_dev->cfg->sclk.gpio, &(spi_dev->cfg->sclk.init));
|
||||||
GPIO_Init(spi_dev->cfg->mosi.gpio, &(spi_dev->cfg->mosi.init));
|
GPIO_Init(spi_dev->cfg->mosi.gpio, &(spi_dev->cfg->mosi.init));
|
||||||
GPIO_Init(spi_dev->cfg->miso.gpio, &(spi_dev->cfg->miso.init));
|
GPIO_Init(spi_dev->cfg->miso.gpio, &(spi_dev->cfg->miso.init));
|
||||||
|
for (uint32_t i = 0; i < init_ssel; i++) {
|
||||||
|
/* Since we're driving the SSEL pin in software, ensure that the slave is deselected */
|
||||||
|
/* XXX multi-slave support - maybe have another SPI_NSS_ mode? */
|
||||||
|
GPIO_SetBits(spi_dev->cfg->ssel[i].gpio, spi_dev->cfg->ssel[i].init.GPIO_Pin);
|
||||||
|
GPIO_Init(spi_dev->cfg->ssel[i].gpio, (GPIO_InitTypeDef*)&(spi_dev->cfg->ssel[i].init));
|
||||||
|
}
|
||||||
|
|
||||||
/* Enable the associated peripheral clock */
|
/* Enable the associated peripheral clock */
|
||||||
switch ((uint32_t) spi_dev->cfg->regs) {
|
switch ((uint32_t) spi_dev->cfg->regs) {
|
||||||
@ -252,6 +262,26 @@ int32_t PIOS_SPI_ClaimBus(uint32_t spi_id)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Claim the SPI bus semaphore from an ISR. Has no timeout.
|
||||||
|
* \param[in] spi SPI number (0 or 1)
|
||||||
|
* \return 0 if no error
|
||||||
|
* \return -1 if timeout before claiming semaphore
|
||||||
|
*/
|
||||||
|
int32_t PIOS_SPI_ClaimBusISR(uint32_t spi_id)
|
||||||
|
{
|
||||||
|
#if defined(PIOS_INCLUDE_FREERTOS)
|
||||||
|
struct pios_spi_dev * spi_dev = (struct pios_spi_dev *)spi_id;
|
||||||
|
|
||||||
|
bool valid = PIOS_SPI_validate(spi_dev);
|
||||||
|
PIOS_Assert(valid)
|
||||||
|
|
||||||
|
if (xQueueGenericReceive(( xQueueHandle ) spi_dev->busy, NULL, 0x0000 , pdFALSE ) != pdTRUE)
|
||||||
|
return -1;
|
||||||
|
#endif
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Release the SPI bus semaphore. Calling the SPI functions does not require this
|
* Release the SPI bus semaphore. Calling the SPI functions does not require this
|
||||||
* \param[in] spi SPI number (0 or 1)
|
* \param[in] spi SPI number (0 or 1)
|
||||||
@ -282,17 +312,19 @@ int32_t PIOS_SPI_ReleaseBus(uint32_t spi_id)
|
|||||||
* \param[in] pin_value 0 or 1
|
* \param[in] pin_value 0 or 1
|
||||||
* \return 0 if no error
|
* \return 0 if no error
|
||||||
*/
|
*/
|
||||||
int32_t PIOS_SPI_RC_PinSet(uint32_t spi_id, uint8_t pin_value)
|
int32_t PIOS_SPI_RC_PinSet(uint32_t spi_id, uint32_t slave_id, uint8_t pin_value)
|
||||||
{
|
{
|
||||||
struct pios_spi_dev * spi_dev = (struct pios_spi_dev *)spi_id;
|
struct pios_spi_dev * spi_dev = (struct pios_spi_dev *)spi_id;
|
||||||
|
|
||||||
bool valid = PIOS_SPI_validate(spi_dev);
|
bool valid = PIOS_SPI_validate(spi_dev);
|
||||||
PIOS_Assert(valid)
|
PIOS_Assert(valid)
|
||||||
|
PIOS_Assert(slave_id <= spi_dev->cfg->slave_count)
|
||||||
|
|
||||||
|
/* XXX multi-slave support? */
|
||||||
if (pin_value) {
|
if (pin_value) {
|
||||||
GPIO_SetBits(spi_dev->cfg->ssel.gpio, spi_dev->cfg->ssel.init.GPIO_Pin);
|
GPIO_SetBits(spi_dev->cfg->ssel[slave_id].gpio, spi_dev->cfg->ssel[slave_id].init.GPIO_Pin);
|
||||||
} else {
|
} else {
|
||||||
GPIO_ResetBits(spi_dev->cfg->ssel.gpio, spi_dev->cfg->ssel.init.GPIO_Pin);
|
GPIO_ResetBits(spi_dev->cfg->ssel[slave_id].gpio, spi_dev->cfg->ssel[slave_id].init.GPIO_Pin);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -50,7 +50,7 @@ static bool PIOS_SPI_validate(struct pios_spi_dev * com_dev)
|
|||||||
return(true);
|
return(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(PIOS_INCLUDE_FREERTOS) && 0
|
#if defined(PIOS_INCLUDE_FREERTOS)
|
||||||
static struct pios_spi_dev * PIOS_SPI_alloc(void)
|
static struct pios_spi_dev * PIOS_SPI_alloc(void)
|
||||||
{
|
{
|
||||||
return (malloc(sizeof(struct pios_spi_dev)));
|
return (malloc(sizeof(struct pios_spi_dev)));
|
||||||
|
@ -44,11 +44,7 @@ typedef enum {
|
|||||||
|
|
||||||
/* Public Functions */
|
/* Public Functions */
|
||||||
extern int32_t PIOS_SPI_SetClockSpeed(uint32_t spi_id, SPIPrescalerTypeDef spi_prescaler);
|
extern int32_t PIOS_SPI_SetClockSpeed(uint32_t spi_id, SPIPrescalerTypeDef spi_prescaler);
|
||||||
#if defined(STM32F2XX) || defined(STM32F4XX) /* XXX harmonise these */
|
|
||||||
extern int32_t PIOS_SPI_RC_PinSet(uint32_t spi_id, uint32_t slave_id, uint8_t pin_value);
|
extern int32_t PIOS_SPI_RC_PinSet(uint32_t spi_id, uint32_t slave_id, uint8_t pin_value);
|
||||||
#else
|
|
||||||
extern int32_t PIOS_SPI_RC_PinSet(uint32_t spi_id, uint8_t pin_value);
|
|
||||||
#endif
|
|
||||||
extern int32_t PIOS_SPI_TransferByte(uint32_t spi_id, uint8_t b);
|
extern int32_t PIOS_SPI_TransferByte(uint32_t spi_id, uint8_t b);
|
||||||
extern int32_t PIOS_SPI_TransferBlock(uint32_t spi_id, const uint8_t *send_buffer, uint8_t *receive_buffer, uint16_t len, void *callback);
|
extern int32_t PIOS_SPI_TransferBlock(uint32_t spi_id, const uint8_t *send_buffer, uint8_t *receive_buffer, uint16_t len, void *callback);
|
||||||
extern int32_t PIOS_SPI_Busy(uint32_t spi_id);
|
extern int32_t PIOS_SPI_Busy(uint32_t spi_id);
|
||||||
|
@ -34,8 +34,6 @@
|
|||||||
#include <pios.h>
|
#include <pios.h>
|
||||||
#include <pios_stm32.h>
|
#include <pios_stm32.h>
|
||||||
|
|
||||||
/* XXX these two should be reconciled - separate for now to avoid breaking other targets */
|
|
||||||
#if defined(STM32F2XX) || defined(STM32F4XX)
|
|
||||||
struct pios_spi_cfg {
|
struct pios_spi_cfg {
|
||||||
SPI_TypeDef *regs;
|
SPI_TypeDef *regs;
|
||||||
uint32_t remap; /* GPIO_Remap_* or GPIO_AF_* */
|
uint32_t remap; /* GPIO_Remap_* or GPIO_AF_* */
|
||||||
@ -48,18 +46,6 @@ struct pios_spi_cfg {
|
|||||||
uint32_t slave_count;
|
uint32_t slave_count;
|
||||||
struct stm32_gpio ssel[];
|
struct stm32_gpio ssel[];
|
||||||
};
|
};
|
||||||
#else
|
|
||||||
struct pios_spi_cfg {
|
|
||||||
SPI_TypeDef *regs;
|
|
||||||
SPI_InitTypeDef init;
|
|
||||||
bool use_crc;
|
|
||||||
struct stm32_dma dma;
|
|
||||||
struct stm32_gpio ssel;
|
|
||||||
struct stm32_gpio sclk;
|
|
||||||
struct stm32_gpio miso;
|
|
||||||
struct stm32_gpio mosi;
|
|
||||||
};
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct pios_spi_dev {
|
struct pios_spi_dev {
|
||||||
const struct pios_spi_cfg * cfg;
|
const struct pios_spi_cfg * cfg;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user