1
0
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:
James Cotton 2012-01-23 23:27:02 -06:00
parent 5fd458426a
commit aaf1c5dfdd
5 changed files with 597 additions and 583 deletions

View File

@ -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;

View File

@ -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)));

View File

@ -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);

View File

@ -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;