1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2024-11-29 07:24:13 +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
* @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
* @see The GNU Public License (GPL) Version 3
* @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)
{
uint32_t init_ssel = 0;
PIOS_Assert(spi_id);
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) {
/* 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);
/* Since we're driving the SSEL pin in software, ensure that the slave is deselected */
GPIO_SetBits(spi_dev->cfg->ssel.gpio, spi_dev->cfg->ssel.init.GPIO_Pin);
GPIO_Init(spi_dev->cfg->ssel.gpio, &(spi_dev->cfg->ssel.init));
/* Init as many slave selects as the config advertises. */
init_ssel = spi_dev->cfg->slave_count;
} else {
/* 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);
}
break;
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()? */
GPIO_Init(spi_dev->cfg->ssel.gpio, &(spi_dev->cfg->ssel.init));
break;
default:
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->mosi.gpio, &(spi_dev->cfg->mosi.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 */
switch ((uint32_t) spi_dev->cfg->regs) {
@ -252,6 +262,26 @@ int32_t PIOS_SPI_ClaimBus(uint32_t spi_id)
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
* \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
* \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;
bool valid = PIOS_SPI_validate(spi_dev);
PIOS_Assert(valid)
PIOS_Assert(slave_id <= spi_dev->cfg->slave_count)
/* XXX multi-slave support? */
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 {
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;

View File

@ -50,7 +50,7 @@ static bool PIOS_SPI_validate(struct pios_spi_dev * com_dev)
return(true);
}
#if defined(PIOS_INCLUDE_FREERTOS) && 0
#if defined(PIOS_INCLUDE_FREERTOS)
static struct pios_spi_dev * PIOS_SPI_alloc(void)
{
return (malloc(sizeof(struct pios_spi_dev)));

View File

@ -44,11 +44,7 @@ typedef enum {
/* Public Functions */
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);
#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_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);

View File

@ -34,8 +34,6 @@
#include <pios.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 {
SPI_TypeDef *regs;
uint32_t remap; /* GPIO_Remap_* or GPIO_AF_* */
@ -48,18 +46,6 @@ struct pios_spi_cfg {
uint32_t slave_count;
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 {
const struct pios_spi_cfg * cfg;