1
0
mirror of https://bitbucket.org/librepilot/librepilot.git synced 2024-12-02 10:24:11 +01:00

PIOS_OVERO driver which handles the communications to the overo and ensures the

data stays in frame.
This commit is contained in:
James Cotton 2012-07-17 15:34:54 -05:00
parent 92a0311b32
commit a6ba379af9
7 changed files with 128 additions and 376 deletions

View File

@ -58,8 +58,6 @@ static int32_t packData(uint8_t * data, int32_t length);
static int32_t transmitData(); static int32_t transmitData();
static void transmitDataDone(bool crc_ok, uint8_t crc_val); static void transmitDataDone(bool crc_ok, uint8_t crc_val);
static void registerObject(UAVObjHandle obj); static void registerObject(UAVObjHandle obj);
// External variables
extern int32_t pios_spi_overo_id;
struct dma_transaction { struct dma_transaction {
uint8_t tx_buffer[OVEROSYNC_PACKET_SIZE] __attribute__ ((aligned(4))); uint8_t tx_buffer[OVEROSYNC_PACKET_SIZE] __attribute__ ((aligned(4)));
@ -83,55 +81,6 @@ struct overosync {
struct overosync *overosync; struct overosync *overosync;
static void PIOS_OVERO_IRQHandler();
static const struct pios_exti_cfg pios_exti_overo_cfg __exti_config = {
.vector = PIOS_OVERO_IRQHandler,
.line = EXTI_Line15,
.pin = {
.gpio = GPIOA,
.init = {
.GPIO_Pin = GPIO_Pin_15,
.GPIO_Speed = GPIO_Speed_100MHz,
.GPIO_Mode = GPIO_Mode_IN,
.GPIO_OType = GPIO_OType_OD,
.GPIO_PuPd = GPIO_PuPd_NOPULL,
},
},
.irq = {
.init = {
.NVIC_IRQChannel = EXTI15_10_IRQn,
.NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID,
.NVIC_IRQChannelSubPriority = 0,
.NVIC_IRQChannelCmd = ENABLE,
},
},
.exti = {
.init = {
.EXTI_Line = EXTI_Line15, // matches above GPIO pin
.EXTI_Mode = EXTI_Mode_Interrupt,
.EXTI_Trigger = EXTI_Trigger_Rising,
.EXTI_LineCmd = ENABLE,
},
},
};
/**
* On the rising edge of NSS schedule a new transaction. This cannot be
* done by the DMA complete because there is 150 us between that and the
* Overo deasserting the CS line. We don't want to spin that long in an
* isr
*/
void PIOS_OVERO_IRQHandler()
{
// transmitData must not block to get semaphore for when we get out of
// frame and transaction is still running here. -1 indicates the transaction
// semaphore is blocked and we are still in a transaction, thus a framesync
// error occurred. This shouldn't happen. Race condition?
if(transmitData() == -1)
overosync->framesync_error++;
}
/** /**
* Initialise the telemetry module * Initialise the telemetry module
* \return -1 if initialisation failed * \return -1 if initialisation failed
@ -139,8 +88,6 @@ void PIOS_OVERO_IRQHandler()
*/ */
int32_t OveroSyncInitialize(void) int32_t OveroSyncInitialize(void)
{ {
if(pios_spi_overo_id == 0)
return -1;
#ifdef MODULE_OVERO_BUILTIN #ifdef MODULE_OVERO_BUILTIN
overoEnabled = true; overoEnabled = true;
@ -161,7 +108,6 @@ int32_t OveroSyncInitialize(void)
OveroSyncStatsInitialize(); OveroSyncStatsInitialize();
PIOS_EXTI_Init(&pios_exti_overo_cfg);
// Create object queues // Create object queues
queue = xQueueCreate(MAX_QUEUE_SIZE, sizeof(UAVObjEvent)); queue = xQueueCreate(MAX_QUEUE_SIZE, sizeof(UAVObjEvent));
@ -183,9 +129,6 @@ int32_t OveroSyncStart(void)
return -1; return -1;
} }
if(pios_spi_overo_id == 0)
return -1;
overosync = (struct overosync *) pvPortMalloc(sizeof(*overosync)); overosync = (struct overosync *) pvPortMalloc(sizeof(*overosync));
if(overosync == NULL) if(overosync == NULL)
return -1; return -1;
@ -302,8 +245,8 @@ static void transmitDataDone(bool crc_ok, uint8_t crc_val)
overosync->transaction_done = true; overosync->transaction_done = true;
// Parse the data from overo // Parse the data from overo
for (uint32_t i = 0; rx_buffer[0] != 0 && i < sizeof(rx_buffer) ; i++) //for (uint32_t i = 0; rx_buffer[0] != 0 && i < sizeof(rx_buffer) ; i++)
UAVTalkProcessInputStream(uavTalkCon, rx_buffer[i]); // UAVTalkProcessInputStream(uavTalkCon, rx_buffer[i]);
} }
/** /**
@ -393,7 +336,7 @@ static int32_t transmitData()
xSemaphoreGiveFromISR(overosync->buffer_lock, &xHigherPriorityTaskWoken); xSemaphoreGiveFromISR(overosync->buffer_lock, &xHigherPriorityTaskWoken);
portEND_SWITCHING_ISR(xHigherPriorityTaskWoken); portEND_SWITCHING_ISR(xHigherPriorityTaskWoken);
return PIOS_SPI_TransferBlock(pios_spi_overo_id, (uint8_t *) tx_buffer, (uint8_t *) rx_buffer, sizeof(overosync->transactions[overosync->active_transaction_id].tx_buffer), &transmitDataDone) == 0 ? 0 : -3; return PIOS_Overo_SetNewBuffer((uint8_t *) tx_buffer, (uint8_t *) rx_buffer, sizeof(overosync->transactions[overosync->active_transaction_id].tx_buffer), &transmitDataDone) == 0 ? 0 : -3;
} }
/** /**

View File

@ -42,6 +42,42 @@
#include <pios_overo.h> #include <pios_overo.h>
#define PACKET_SIZE 1024
static void PIOS_OVERO_NSS_IRQHandler();
static const struct pios_exti_cfg pios_exti_overo_cfg __exti_config = {
.vector = PIOS_OVERO_NSS_IRQHandler,
.line = EXTI_Line15,
.pin = {
.gpio = GPIOA,
.init = {
.GPIO_Pin = GPIO_Pin_15,
.GPIO_Speed = GPIO_Speed_100MHz,
.GPIO_Mode = GPIO_Mode_IN,
.GPIO_OType = GPIO_OType_OD,
.GPIO_PuPd = GPIO_PuPd_NOPULL,
},
},
.irq = {
.init = {
.NVIC_IRQChannel = EXTI15_10_IRQn,
.NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_MID,
.NVIC_IRQChannelSubPriority = 0,
.NVIC_IRQChannelCmd = ENABLE,
},
},
.exti = {
.init = {
.EXTI_Line = EXTI_Line15, // matches above GPIO pin
.EXTI_Mode = EXTI_Mode_Interrupt,
.EXTI_Trigger = EXTI_Trigger_Rising,
.EXTI_LineCmd = ENABLE,
},
},
};
static bool PIOS_OVERO_validate(struct pios_overo_dev * com_dev) static bool PIOS_OVERO_validate(struct pios_overo_dev * com_dev)
{ {
/* Should check device magic here */ /* Should check device magic here */
@ -57,37 +93,32 @@ static struct pios_overo_dev * PIOS_OVERO_alloc(void)
#error Unsupported #error Unsupported
#endif #endif
//! Global variable
struct pios_overo_dev * overo_dev;
/** /**
* Initialises Overo pins * Initialises Overo pins
* \param[in] mode currently only mode 0 supported * \param[in] mode currently only mode 0 supported
* \return < 0 if initialisation failed * \return < 0 if initialisation failed
*/ */
int32_t PIOS_Overo_Init(uint32_t * overo_id, const struct pios_overo_cfg * cfg) int32_t PIOS_Overo_Init(const struct pios_overo_cfg * cfg)
{ {
uint32_t init_ssel = 0; uint32_t init_ssel = 0;
PIOS_Assert(overo_id);
PIOS_Assert(cfg); PIOS_Assert(cfg);
struct pios_overo_dev * overo_dev;
overo_dev = (struct pios_overo_dev *) PIOS_OVERO_alloc(); overo_dev = (struct pios_overo_dev *) PIOS_OVERO_alloc();
if (!overo_dev) goto out_fail; if (!overo_dev) goto out_fail;
/* Bind the configuration to the device instance */ /* Bind the configuration to the device instance */
overo_dev->cfg = cfg; overo_dev->cfg = cfg;
#if defined(PIOS_INCLUDE_FREERTOS)
vSemaphoreCreateBinary(overo_dev->busy);
xSemaphoreGive(overo_dev->busy);
#endif
/* Disable callback function */ /* Disable callback function */
overo_dev->callback = NULL; overo_dev->callback = NULL;
/* Set rx/tx dummy bytes to a known value */ /* Set a null buffer initially */
overo_dev->rx_dummy_byte = 0xFF; overo_dev->new_tx_buffer = 0;
overo_dev->tx_dummy_byte = 0xFF; overo_dev->new_rx_buffer = 0;
/* only legal for single-slave config */ /* only legal for single-slave config */
PIOS_Assert(overo_dev->cfg->slave_count == 1); PIOS_Assert(overo_dev->cfg->slave_count == 1);
@ -143,12 +174,12 @@ int32_t PIOS_Overo_Init(uint32_t * overo_id, const struct pios_overo_cfg * cfg)
/* Enable SPI interrupts to DMA */ /* Enable SPI interrupts to DMA */
SPI_I2S_DMACmd(overo_dev->cfg->regs, SPI_I2S_DMAReq_Tx | SPI_I2S_DMAReq_Rx, ENABLE); SPI_I2S_DMACmd(overo_dev->cfg->regs, SPI_I2S_DMAReq_Tx | SPI_I2S_DMAReq_Rx, ENABLE);
/* Must store this before enabling interrupt */
*spi_id = (uint32_t)overo_dev;
/* Configure DMA interrupt */ /* Configure DMA interrupt */
NVIC_Init((NVIC_InitTypeDef*)&(overo_dev->cfg->dma.irq.init)); NVIC_Init((NVIC_InitTypeDef*)&(overo_dev->cfg->dma.irq.init));
/* Configure the interrupt for rising edge of NSS */
PIOS_EXTI_Init(&pios_exti_overo_cfg);
return(0); return(0);
out_fail: out_fail:
@ -156,296 +187,98 @@ out_fail:
} }
/** /**
* Claim the SPI bus semaphore. Calling the SPI functions does not require this * Transfers a block of bytes via DMA.
* \param[in] spi SPI number (0 or 1) * \param[in] overo_id SPI device handle
* \return 0 if no error * \param[in] send_buffer pointer to buffer which should be sent.<BR>
* \return -1 if timeout before claiming semaphore * If NULL, 0xff (all-one) will be sent.
* \param[in] receive_buffer pointer to buffer which should get the received values.<BR>
* If NULL, received bytes will be discarded.
* \param[in] len number of bytes which should be transfered
* \param[in] callback pointer to callback function which will be executed
* from DMA channel interrupt once the transfer is finished.
* If NULL, no callback function will be used, and PIOS_SPI_TransferBlock() will
* block until the transfer is finished.
* \return >= 0 if no error during transfer
* \return -1 if disabled SPI port selected
* \return -3 if function has been called during an ongoing DMA transfer
*/ */
int32_t PIOS_OVERO_ClaimBus(uint32_t spi_id) int32_t PIOS_Overo_SetNewBuffer(const uint8_t *send_buffer, uint8_t *receive_buffer, uint16_t len, void *callback)
{ {
#if defined(PIOS_INCLUDE_FREERTOS)
struct pios_overo_dev * overo_dev = (struct pios_overo_dev *)overo_id;
bool valid = PIOS_OVERO_validate(overo_dev); bool valid = PIOS_OVERO_validate(overo_dev);
PIOS_Assert(valid) PIOS_Assert(valid)
if (xSemaphoreTake(overo_dev->busy, 0xffff) != pdTRUE) bool overrun = overo_dev->new_tx_buffer || overo_dev->new_rx_buffer;
return -1; /* Cache next buffer */
#endif overo_dev->new_tx_buffer = (uint32_t) send_buffer;
return 0; overo_dev->new_rx_buffer = (uint32_t) receive_buffer;
}
/**
* 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_OVERO_ClaimBusISR(uint32_t overo_io)
{
#if defined(PIOS_INCLUDE_FREERTOS)
struct pios_overo_dev * overo_dev = (struct pios_spi_dev *)spi_id;
bool valid = PIOS_OVERO_validate(overo_dev);
PIOS_Assert(valid)
if (xQueueGenericReceive(( xQueueHandle ) overo_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)
* \return 0 if no error
*/
int32_t PIOS_OVERO_ReleaseBus(uint32_t overo_id)
{
#if defined(PIOS_INCLUDE_FREERTOS)
struct pios_overo_dev * overo_dev = (struct pios_overo_dev *)overo_id;
bool valid = PIOS_OVERO_validate(overo_dev);
PIOS_Assert(valid)
xSemaphoreGive(overo_dev->busy);
#endif
return 0;
}
/**
* Transfers a block of bytes via DMA.
* \param[in] spi SPI number (0 or 1)
* \param[in] send_buffer pointer to buffer which should be sent.<BR>
* If NULL, 0xff (all-one) will be sent.
* \param[in] receive_buffer pointer to buffer which should get the received values.<BR>
* If NULL, received bytes will be discarded.
* \param[in] len number of bytes which should be transfered
* \param[in] callback pointer to callback function which will be executed
* from DMA channel interrupt once the transfer is finished.
* If NULL, no callback function will be used, and PIOS_SPI_TransferBlock() will
* block until the transfer is finished.
* \return >= 0 if no error during transfer
* \return -1 if disabled SPI port selected
* \return -3 if function has been called during an ongoing DMA transfer
*/
static int32_t SPI_DMA_TransferBlock(uint32_t spi_id, const uint8_t *send_buffer, uint8_t *receive_buffer, uint16_t len, void *callback)
{
struct pios_overo_dev * overo_dev = (struct pios_spi_dev *)spi_id;
bool valid = PIOS_SPI_validate(overo_dev);
PIOS_Assert(valid)
DMA_InitTypeDef dma_init;
/* Exit if ongoing transfer */
if (DMA_GetCurrDataCounter(overo_dev->cfg->dma.rx.channel)) {
return -3;
}
/* Disable the DMA channels */
DMA_Cmd(overo_dev->cfg->dma.rx.channel, DISABLE);
DMA_Cmd(overo_dev->cfg->dma.tx.channel, DISABLE);
while(DMA_GetCmdStatus(overo_dev->cfg->dma.rx.channel) == ENABLE);
while(DMA_GetCmdStatus(overo_dev->cfg->dma.tx.channel) == ENABLE);
/* Disable the SPI peripheral */
/* Initialize the SPI block */
SPI_DeInit(overo_dev->cfg->regs);
SPI_Init(overo_dev->cfg->regs, (SPI_InitTypeDef*)&(overo_dev->cfg->init));
SPI_Cmd(overo_dev->cfg->regs, DISABLE);
/* Configure CRC calculation */
if (overo_dev->cfg->use_crc) {
SPI_CalculateCRC(overo_dev->cfg->regs, ENABLE);
} else {
SPI_CalculateCRC(overo_dev->cfg->regs, DISABLE);
}
/* Enable SPI interrupts to DMA */
SPI_I2S_DMACmd(overo_dev->cfg->regs, SPI_I2S_DMAReq_Tx | SPI_I2S_DMAReq_Rx, ENABLE);
/* Set callback function */ /* Set callback function */
overo_dev->callback = callback; overo_dev->callback = callback;
/* /* No error */
* Configure Rx channel return overrun ? -1 : 0;
*/ }
/* Start with the default configuration for this peripheral */ /**
dma_init = overo_dev->cfg->dma.rx.init; * On the rising edge of NSS schedule a new transaction. This cannot be
DMA_DeInit(overo_dev->cfg->dma.rx.channel); * done by the DMA complete because there is 150 us between that and the
if (receive_buffer != NULL) { * Overo deasserting the CS line. We don't want to spin that long in an
/* Enable memory addr. increment - bytes written into receive buffer */ * isr.
dma_init.DMA_Memory0BaseAddr = (uint32_t) receive_buffer; *
dma_init.DMA_MemoryInc = DMA_MemoryInc_Enable; * 1. Disable the DMA channel
} else { * 2. Check that the DMA counter is at the end of the buffer (increase an
/* Disable memory addr. increment - bytes written into dummy buffer */ * error counter if not)
overo_dev->rx_dummy_byte = 0xFF; * 3. Reset the DMA counter to the end of the beginning of the buffer
dma_init.DMA_Memory0BaseAddr = (uint32_t) &overo_dev->rx_dummy_byte; * 4. Swap the buffer
dma_init.DMA_MemoryInc = DMA_MemoryInc_Disable; * 5. Enable the DMA channel
} */
if (overo_dev->cfg->use_crc) { void PIOS_OVERO_NSS_IRQHandler()
/* Make sure the CRC error flag is cleared before we start */ {
SPI_I2S_ClearFlag(overo_dev->cfg->regs, SPI_FLAG_CRCERR); static uint32_t error_counter = 0;
}
dma_init.DMA_BufferSize = len; bool valid = PIOS_OVERO_validate(overo_dev);
DMA_Init(overo_dev->cfg->dma.rx.channel, &(dma_init)); PIOS_Assert(valid)
/* /* Disable the SPI peripheral */
* Configure Tx channel SPI_Cmd(overo_dev->cfg->regs, DISABLE);
*/
/* Start with the default configuration for this peripheral */ /* Disable the DMA commands */
dma_init = overo_dev->cfg->dma.tx.init; DMA_Cmd(overo_dev->cfg->dma.tx.channel, DISABLE);
DMA_DeInit(overo_dev->cfg->dma.tx.channel); DMA_Cmd(overo_dev->cfg->dma.rx.channel, DISABLE);
if (send_buffer != NULL) {
/* Enable memory addr. increment - bytes written into receive buffer */
dma_init.DMA_Memory0BaseAddr = (uint32_t) send_buffer;
dma_init.DMA_MemoryInc = DMA_MemoryInc_Enable;
} else {
/* Disable memory addr. increment - bytes written into dummy buffer */
overo_dev->tx_dummy_byte = 0xFF;
dma_init.DMA_Memory0BaseAddr = (uint32_t) &overo_dev->tx_dummy_byte;
dma_init.DMA_MemoryInc = DMA_MemoryInc_Disable;
}
if (overo_dev->cfg->use_crc) { /* Check that the previous DMA transfer completed */
/* The last byte of the payload will be replaced with the CRC8 */ if(DMA_GetCurrDataCounter(overo_dev->cfg->dma.tx.channel) ||
dma_init.DMA_BufferSize = len - 1; DMA_GetCurrDataCounter(overo_dev->cfg->dma.rx.channel))
} else { error_counter++;
dma_init.DMA_BufferSize = len;
}
DMA_Init(overo_dev->cfg->dma.tx.channel, &(dma_init)); // Activate the new buffer
DMA_MemoryTargetConfig(overo_dev->cfg->dma.tx.channel, overo_dev->new_tx_buffer, DMA_Memory_0);
DMA_MemoryTargetConfig(overo_dev->cfg->dma.rx.channel, overo_dev->new_rx_buffer, DMA_Memory_0);
/* Enable DMA interrupt if callback function active */ // Enable DMA, Slave first
DMA_ITConfig(overo_dev->cfg->dma.rx.channel, DMA_IT_TC, (callback != NULL) ? ENABLE : DISABLE); DMA_SetCurrDataCounter(overo_dev->cfg->dma.tx.channel, PACKET_SIZE);
DMA_SetCurrDataCounter(overo_dev->cfg->dma.rx.channel, PACKET_SIZE);
/* Flush out the CRC registers */
SPI_CalculateCRC(overo_dev->cfg->regs, DISABLE); /* Reenable the SPI peripheral */
(void)SPI_GetCRC(overo_dev->cfg->regs, SPI_CRC_Rx);
SPI_I2S_ClearFlag(overo_dev->cfg->regs, SPI_FLAG_CRCERR);
/* Make sure to flush out the receive buffer */
(void)SPI_I2S_ReceiveData(overo_dev->cfg->regs);
if (overo_dev->cfg->use_crc) {
/* Need a 0->1 transition to reset the CRC logic */
SPI_CalculateCRC(overo_dev->cfg->regs, ENABLE);
}
/* Start DMA transfers */
DMA_Cmd(overo_dev->cfg->dma.rx.channel, ENABLE);
DMA_Cmd(overo_dev->cfg->dma.tx.channel, ENABLE);
/* Reenable the SPI device */
SPI_Cmd(overo_dev->cfg->regs, ENABLE); SPI_Cmd(overo_dev->cfg->regs, ENABLE);
if (callback) { /* Enable SPI interrupts to DMA */
/* User has requested a callback, don't wait for the transfer to complete. */ SPI_I2S_DMACmd(overo_dev->cfg->regs, SPI_I2S_DMAReq_Tx, ENABLE);
return 0; SPI_I2S_DMACmd(overo_dev->cfg->regs, SPI_I2S_DMAReq_Rx, ENABLE);
}
/* Wait until all bytes have been transmitted/received */ /* Enable the DMA endpoints for valid buffers */
while (DMA_GetCurrDataCounter(overo_dev->cfg->dma.rx.channel)); if(overo_dev->new_rx_buffer)
DMA_Cmd(overo_dev->cfg->dma.rx.channel, ENABLE);
if(overo_dev->new_tx_buffer)
DMA_Cmd(overo_dev->cfg->dma.tx.channel, ENABLE);
/* Wait for the final bytes of the transfer to complete, including CRC byte(s). */ /* Indicate these buffers have been used */
while (!(SPI_I2S_GetFlagStatus(overo_dev->cfg->regs, SPI_I2S_FLAG_TXE))); overo_dev->new_tx_buffer = 0;
overo_dev->new_rx_buffer = 0;
/* Wait for the final bytes of the transfer to complete, including CRC byte(s). */ if (overo_dev->callback != NULL)
while (SPI_I2S_GetFlagStatus(overo_dev->cfg->regs, SPI_I2S_FLAG_BSY)); overo_dev->callback(true, true);
/* Check the CRC on the transfer if enabled. */
if (overo_dev->cfg->use_crc) {
/* Check the SPI CRC error flag */
if (SPI_I2S_GetFlagStatus(overo_dev->cfg->regs, SPI_FLAG_CRCERR)) {
return -4;
}
}
/* No error */
return 0;
}
/**
* Transfers a block of bytes via PIO or DMA.
* \param[in] spi_id SPI device handle
* \param[in] send_buffer pointer to buffer which should be sent.<BR>
* If NULL, 0xff (all-one) will be sent.
* \param[in] receive_buffer pointer to buffer which should get the received values.<BR>
* If NULL, received bytes will be discarded.
* \param[in] len number of bytes which should be transfered
* \param[in] callback pointer to callback function which will be executed
* from DMA channel interrupt once the transfer is finished.
* If NULL, no callback function will be used, and PIOS_SPI_TransferBlock() will
* block until the transfer is finished.
* \return >= 0 if no error during transfer
* \return -1 if disabled SPI port selected
* \return -3 if function has been called during an ongoing DMA transfer
*/
int32_t PIOS_SPI_TransferBlock(uint32_t spi_id, const uint8_t *send_buffer, uint8_t *receive_buffer, uint16_t len, void *callback)
{
return SPI_PIO_TransferBlock(spi_id, send_buffer, receive_buffer, len);
}
/**
* Check if a transfer is in progress
* \param[in] spi SPI number (0 or 1)
* \return >= 0 if no transfer is in progress
* \return -1 if disabled SPI port selected
* \return -2 if unsupported SPI port selected
* \return -3 if function has been called during an ongoing DMA transfer
*/
int32_t PIOS_OVERO_Busy(uint32_t overo_id)
{
struct pios_overo_dev * overo_dev = (struct pios_overo_dev *)overo_id;
bool valid = PIOS_OVERO_validate(overo_dev);
PIOS_Assert(valid)
/* DMA buffer has data or SPI transmit register not empty or SPI is busy*/
if (DMA_GetCurrDataCounter(overo_dev->cfg->dma.rx.channel) ||
!SPI_I2S_GetFlagStatus(overo_dev->cfg->regs, SPI_I2S_FLAG_TXE) ||
SPI_I2S_GetFlagStatus(overo_dev->cfg->regs, SPI_I2S_FLAG_BSY))
{
return -3;
}
return(0);
}
void PIOS_OVERO_IRQ_Handler(uint32_t spi_id)
{
struct pios_overo_dev * overo_dev = (struct pios_overo_dev *)overo_id;
bool valid = PIOS_OVERO_validate(overo_dev);
PIOS_Assert(valid)
// FIXME XXX Only RX channel or better clear flags for both channels?
DMA_ClearFlag(overo_dev->cfg->dma.rx.channel, overo_dev->cfg->dma.irq.flags);
if(overo_dev->cfg->init.SPI_Mode == SPI_Mode_Master) {
/* Wait for the final bytes of the transfer to complete, including CRC byte(s). */
while (!(SPI_I2S_GetFlagStatus(overo_dev->cfg->regs, SPI_I2S_FLAG_TXE))) ;
/* Wait for the final bytes of the transfer to complete, including CRC byte(s). */
while (SPI_I2S_GetFlagStatus(overo_dev->cfg->regs, SPI_I2S_FLAG_BSY)) ;
}
if (overo_dev->callback != NULL) {
bool crc_ok = true;
uint8_t crc_val;
if (SPI_I2S_GetFlagStatus(overo_dev->cfg->regs, SPI_FLAG_CRCERR)) {
crc_ok = false;
SPI_I2S_ClearFlag(overo_dev->cfg->regs, SPI_FLAG_CRCERR);
}
crc_val = SPI_GetCRC(overo_dev->cfg->regs, SPI_CRC_Rx);
overo_dev->callback(crc_ok, crc_val);
}
} }
#endif #endif

View File

@ -49,17 +49,12 @@ struct pios_overo_cfg {
struct pios_overo_dev { struct pios_overo_dev {
const struct pios_overo_cfg * cfg; const struct pios_overo_cfg * cfg;
void (*callback) (uint8_t, uint8_t); void (*callback) (uint8_t, uint8_t);
uint8_t tx_dummy_byte; uint32_t new_tx_buffer;
uint8_t rx_dummy_byte; uint32_t new_rx_buffer;
#if defined(PIOS_INCLUDE_FREERTOS)
xSemaphoreHandle busy;
#else
uint8_t busy;
#endif
}; };
extern int32_t PIOS_OVERO_Init(uint32_t * overo_id, const struct pios_overo_cfg * cfg); extern int32_t PIOS_Overo_Init(const struct pios_overo_cfg * cfg);
extern int32_t PIOS_OVERO_SwapBuffer(uint32_t overo_id, const uint8_t *send_buffer, uint8_t *receive_buffer, uint16_t len, void *callback); extern int32_t PIOS_Overo_SetNewBuffer(const uint8_t *send_buffer, uint8_t *receive_buffer, uint16_t len, void *callback);
#endif /* PIOS_OVERO_H */ #endif /* PIOS_OVERO_H */

View File

@ -86,6 +86,7 @@
#include <pios_rtc.h> #include <pios_rtc.h>
#include <pios_i2c.h> #include <pios_i2c.h>
#include <pios_spi.h> #include <pios_spi.h>
#include <pios_overo.h>
#include <pios_ppm.h> #include <pios_ppm.h>
#include <pios_pwm.h> #include <pios_pwm.h>
#include <pios_rcvr.h> #include <pios_rcvr.h>

View File

@ -404,7 +404,7 @@ void PIOS_Board_Init(void) {
#if defined(PIOS_OVERO_SPI) #if defined(PIOS_OVERO_SPI)
/* Set up the SPI interface to the gyro */ /* Set up the SPI interface to the gyro */
if (PIOS_SPI_Init(&pios_spi_overo_id, &pios_spi_overo_cfg)) { if (PIOS_Overo_Init(&pios_overo_cfg)) {
PIOS_DEBUG_Assert(0); PIOS_DEBUG_Assert(0);
} }
#endif #endif

View File

@ -451,10 +451,7 @@ void PIOS_SPI_flash_irq_handler(void)
/* SPI3 Interface /* SPI3 Interface
* - Used for flash communications * - Used for flash communications
*/ */
void PIOS_SPI_overo_irq_handler(void); static const struct pios_overo_cfg pios_overo_cfg = {
void DMA1_Stream0_IRQHandler(void) __attribute__((alias("PIOS_SPI_overo_irq_handler")));
void DMA1_Stream7_IRQHandler(void) __attribute__((alias("PIOS_SPI_overo_irq_handler")));
static const struct pios_spi_cfg pios_spi_overo_cfg = {
.regs = SPI3, .regs = SPI3,
.remap = GPIO_AF_SPI3, .remap = GPIO_AF_SPI3,
.init = { .init = {
@ -469,18 +466,7 @@ static const struct pios_spi_cfg pios_spi_overo_cfg = {
.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2, .SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2,
}, },
.use_crc = false, .use_crc = false,
.dma = { .dma = {
.irq = {
// Note this is the stream ID that triggers interrupts (in this case RX)
.flags = (DMA_IT_TCIF0 | DMA_IT_TEIF0 | DMA_IT_HTIF0),
.init = {
.NVIC_IRQChannel = DMA1_Stream0_IRQn,
.NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGH,
.NVIC_IRQChannelSubPriority = 0,
.NVIC_IRQChannelCmd = ENABLE,
},
},
.rx = { .rx = {
.channel = DMA1_Stream0, .channel = DMA1_Stream0,
.init = { .init = {
@ -562,12 +548,6 @@ static const struct pios_spi_cfg pios_spi_overo_cfg = {
} }, } },
}; };
uint32_t pios_spi_overo_id;
void PIOS_SPI_overo_irq_handler(void)
{
/* Call into the generic code to handle the IRQ for this specific device */
PIOS_SPI_IRQ_Handler(pios_spi_overo_id);
}
#else #else
uint32_t pios_spi_overo_id = 0; uint32_t pios_spi_overo_id = 0;
#endif /* PIOS_OVERO_SPI */ #endif /* PIOS_OVERO_SPI */

2
overo

@ -1 +1 @@
Subproject commit 207effa5bdc993b280fa0c5c05aafc10fcfafa28 Subproject commit 704c7b291a9effd3a9cf189e5fef167c598d79bf