mirror of
https://bitbucket.org/librepilot/librepilot.git
synced 2024-12-02 10:24:11 +01:00
pios spi: support both master and slave configs
Added support for SPI slave configurations to the pios SPI layer. Converted the board specific configuration for the PIOS SPI layer to use const static initializers rather than #defines (see pios_board.c). SPI interface between the OP board and the AHRS is now operational at a basic level, capable of moving simple single byte messages between boards. Multi-byte, CRC protected messages will be added on top of this. git-svn-id: svn://svn.openpilot.org/OpenPilot/trunk@759 ebee16cc-31ac-478f-84a7-5cbb03baadba
This commit is contained in:
parent
02e0017cbb
commit
8d015a57d0
@ -86,6 +86,7 @@ CMSISDIR = $(STMLIBDIR)/CMSIS/Core/CM3
|
||||
|
||||
## AHRS:
|
||||
SRC = ahrs.c
|
||||
SRC += pios_board.c
|
||||
|
||||
## PIOS Hardware (STM32F10x)
|
||||
SRC += $(PIOSSTM32F10X)/pios_sys.c
|
||||
@ -96,7 +97,7 @@ SRC += $(PIOSSTM32F10X)/pios_irq.c
|
||||
SRC += $(PIOSSTM32F10X)/pios_adc.c
|
||||
SRC += $(PIOSSTM32F10X)/pios_i2c.c
|
||||
SRC += $(PIOSSTM32F10X)/pios_gpio.c
|
||||
#SRC += $(PIOSSTM32F10X)/pios_spi.c
|
||||
SRC += $(PIOSSTM32F10X)/pios_spi.c
|
||||
|
||||
## PIOS Hardware (Common)
|
||||
SRC += $(PIOSCOMMON)/pios_com.c
|
||||
|
@ -71,6 +71,9 @@ int main()
|
||||
int16_t data[3] = {0};
|
||||
int32_t heading = 0;
|
||||
|
||||
/* SPI link to master */
|
||||
PIOS_SPI_Init();
|
||||
|
||||
// Main loop
|
||||
for(;;) {
|
||||
// Alive signal
|
||||
|
@ -1,4 +1,4 @@
|
||||
/**
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pios_board.h
|
||||
@ -115,6 +115,13 @@ TIM8 | | | |
|
||||
#define PIOS_I2C_IRQ_EV_PRIORITY 2
|
||||
#define PIOS_I2C_IRQ_ER_PRIORITY 2
|
||||
|
||||
//-------------------------
|
||||
// SPI
|
||||
//
|
||||
// See also pios_board.c
|
||||
//-------------------------
|
||||
#define PIOS_OP_SPI 0
|
||||
|
||||
//-------------------------
|
||||
// PIOS_USART1
|
||||
//-------------------------
|
||||
|
@ -34,6 +34,7 @@
|
||||
#define PIOS_INCLUDE_I2C
|
||||
#define PIOS_INCLUDE_IRQ
|
||||
#define PIOS_INCLUDE_LED
|
||||
#define PIOS_INCLUDE_SPI
|
||||
#define PIOS_INCLUDE_SYS
|
||||
#define PIOS_INCLUDE_USART
|
||||
#define PIOS_INCLUDE_COM
|
||||
|
144
flight/AHRS/pios_board.c
Normal file
144
flight/AHRS/pios_board.c
Normal file
@ -0,0 +1,144 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pios_board.c
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief Defines board specific static initializers for hardware for the AHRS board.
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <pios.h>
|
||||
|
||||
#if defined(PIOS_INCLUDE_SPI)
|
||||
|
||||
#include <pios_spi_priv.h>
|
||||
|
||||
/* OP Interface
|
||||
*
|
||||
* NOTE: Leave this declared as const static data so that it ends up in the
|
||||
* .rodata section (ie. Flash) rather than in the .bss section (RAM).
|
||||
*/
|
||||
void PIOS_SPI_op_irq_handler(void);
|
||||
static const struct pios_spi_cfg pios_spi_op_cfg = {
|
||||
.regs = SPI2,
|
||||
.init = {
|
||||
.SPI_Mode = SPI_Mode_Slave,
|
||||
.SPI_Direction = SPI_Direction_2Lines_FullDuplex,
|
||||
.SPI_DataSize = SPI_DataSize_8b,
|
||||
.SPI_NSS = SPI_NSS_Hard,
|
||||
.SPI_FirstBit = SPI_FirstBit_MSB,
|
||||
.SPI_CRCPolynomial = 7,
|
||||
.SPI_CPOL = SPI_CPOL_High,
|
||||
.SPI_CPHA = SPI_CPHA_2Edge,
|
||||
},
|
||||
.dma = {
|
||||
.ahb_clk = RCC_AHBPeriph_DMA1,
|
||||
|
||||
.irq = {
|
||||
.handler = PIOS_SPI_op_irq_handler,
|
||||
.flags = (DMA1_FLAG_TC4 | DMA1_FLAG_TE4 | DMA1_FLAG_HT4 | DMA1_FLAG_GL4),
|
||||
.init = {
|
||||
.NVIC_IRQChannel = DMA1_Channel4_IRQn,
|
||||
.NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGH,
|
||||
.NVIC_IRQChannelSubPriority = 0,
|
||||
.NVIC_IRQChannelCmd = ENABLE,
|
||||
},
|
||||
},
|
||||
|
||||
.rx = {
|
||||
.channel = DMA1_Channel4,
|
||||
.init = {
|
||||
.DMA_PeripheralBaseAddr = (uint32_t)&(SPI2->DR),
|
||||
.DMA_DIR = DMA_DIR_PeripheralSRC,
|
||||
.DMA_PeripheralInc = DMA_PeripheralInc_Disable,
|
||||
.DMA_MemoryInc = DMA_MemoryInc_Enable,
|
||||
.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte,
|
||||
.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte,
|
||||
.DMA_Mode = DMA_Mode_Normal,
|
||||
.DMA_Priority = DMA_Priority_Medium,
|
||||
.DMA_M2M = DMA_M2M_Disable,
|
||||
},
|
||||
},
|
||||
.tx = {
|
||||
.channel = DMA1_Channel5,
|
||||
.init = {
|
||||
.DMA_PeripheralBaseAddr = (uint32_t)&(SPI2->DR),
|
||||
.DMA_DIR = DMA_DIR_PeripheralDST,
|
||||
.DMA_PeripheralInc = DMA_PeripheralInc_Disable,
|
||||
.DMA_MemoryInc = DMA_MemoryInc_Enable,
|
||||
.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte,
|
||||
.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte,
|
||||
.DMA_Mode = DMA_Mode_Normal,
|
||||
.DMA_Priority = DMA_Priority_Medium,
|
||||
.DMA_M2M = DMA_M2M_Disable,
|
||||
},
|
||||
},
|
||||
},
|
||||
.ssel = {
|
||||
.gpio = GPIOB,
|
||||
.init = {
|
||||
.GPIO_Pin = GPIO_Pin_12,
|
||||
.GPIO_Speed = GPIO_Speed_50MHz,
|
||||
.GPIO_Mode = GPIO_Mode_IN_FLOATING,
|
||||
},
|
||||
},
|
||||
.sclk = {
|
||||
.gpio = GPIOB,
|
||||
.init = {
|
||||
.GPIO_Pin = GPIO_Pin_13,
|
||||
.GPIO_Speed = GPIO_Speed_50MHz,
|
||||
.GPIO_Mode = GPIO_Mode_IN_FLOATING,
|
||||
},
|
||||
},
|
||||
.miso = {
|
||||
.gpio = GPIOB,
|
||||
.init = {
|
||||
.GPIO_Pin = GPIO_Pin_14,
|
||||
.GPIO_Speed = GPIO_Speed_50MHz,
|
||||
.GPIO_Mode = GPIO_Mode_AF_PP,
|
||||
},
|
||||
},
|
||||
.mosi = {
|
||||
.gpio = GPIOB,
|
||||
.init = {
|
||||
.GPIO_Pin = GPIO_Pin_15,
|
||||
.GPIO_Speed = GPIO_Speed_50MHz,
|
||||
.GPIO_Mode = GPIO_Mode_IPU,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* Board specific number of devices.
|
||||
*/
|
||||
struct pios_spi_dev pios_spi_devs[] = {
|
||||
{
|
||||
.cfg = &pios_spi_op_cfg,
|
||||
},
|
||||
};
|
||||
|
||||
uint8_t pios_spi_num_devices = NELEMENTS(pios_spi_devs);
|
||||
|
||||
void PIOS_SPI_op_irq_handler(void)
|
||||
{
|
||||
/* Call into the generic code to handle the IRQ for this specific device */
|
||||
PIOS_SPI_IRQ_Handler(PIOS_OP_SPI);
|
||||
}
|
||||
|
||||
#endif
|
@ -112,6 +112,7 @@ SRC += ${OUTDIR}/InitMods.c
|
||||
## OPENPILOT CORE:
|
||||
SRC += ${OPMODULEDIR}/System/systemmod.c
|
||||
SRC += $(OPSYSTEM)/openpilot.c
|
||||
SRC += $(OPSYSTEM)/pios_board.c
|
||||
SRC += $(OPSYSTEM)/alarms.c
|
||||
SRC += $(OPUAVTALK)/uavtalk.c
|
||||
SRC += $(OPUAVOBJ)/uavobjectmanager.c
|
||||
|
@ -162,44 +162,11 @@ TIM8 | Servo 5 | Servo 6 | Servo 7 | Servo 8
|
||||
|
||||
//-------------------------
|
||||
// SPI
|
||||
//-------------------------
|
||||
#define PIOS_SPI_IRQ_DMA_PRIORITY PIOS_IRQ_PRIO_HIGH
|
||||
#define PIOS_SPI_NUM 2
|
||||
#define PIOS_SPI0_ENABLED 1
|
||||
#define PIOS_SPI0_PTR SPI1
|
||||
#define PIOS_SPI0_DMA_RX_PTR DMA1_Channel2
|
||||
#define PIOS_SPI0_DMA_TX_PTR DMA1_Channel3
|
||||
#define PIOS_SPI0_DMA_RX_IRQ_FLAGS (DMA1_FLAG_TC2 | DMA1_FLAG_TE2 | DMA1_FLAG_HT2 | DMA1_FLAG_GL2)
|
||||
#define PIOS_SPI0_DMA_IRQ_CHANNEL DMA1_Channel2_IRQn
|
||||
#define PIOS_SPI0_DMA_IRQHANDLER_FUNC void DMA1_Channel2_IRQHandler(void)
|
||||
#define PIOS_SPI0_RCLK1_PORT GPIOA
|
||||
#define PIOS_SPI0_RCLK1_PIN GPIO_Pin_4
|
||||
#define PIOS_SPI0_SCLK_PORT GPIOA
|
||||
#define PIOS_SPI0_SCLK_PIN GPIO_Pin_5
|
||||
#define PIOS_SPI0_MISO_PORT GPIOA
|
||||
#define PIOS_SPI0_MISO_PIN GPIO_Pin_6
|
||||
#define PIOS_SPI0_MOSI_PORT GPIOA
|
||||
#define PIOS_SPI0_MOSI_PIN GPIO_Pin_7
|
||||
#define PIOS_SPI1_ENABLED 1
|
||||
#define PIOS_SPI1_PTR SPI2
|
||||
#define PIOS_SPI1_DMA_RX_PTR DMA1_Channel4
|
||||
#define PIOS_SPI1_DMA_TX_PTR DMA1_Channel5
|
||||
#define PIOS_SPI1_DMA_RX_IRQ_FLAGS (DMA1_FLAG_TC4 | DMA1_FLAG_TE4 | DMA1_FLAG_HT4 | DMA1_FLAG_GL4)
|
||||
#define PIOS_SPI1_DMA_IRQ_CHANNEL DMA1_Channel4_IRQn
|
||||
#define PIOS_SPI1_DMA_IRQHANDLER_FUNC void DMA1_Channel4_IRQHandler(void)
|
||||
#define PIOS_SPI1_RCLK1_PORT GPIOB
|
||||
#define PIOS_SPI1_RCLK1_PIN GPIO_Pin_12
|
||||
#define PIOS_SPI1_SCLK_PORT GPIOB
|
||||
#define PIOS_SPI1_SCLK_PIN GPIO_Pin_13
|
||||
#define PIOS_SPI1_MISO_PORT GPIOB
|
||||
#define PIOS_SPI1_MISO_PIN GPIO_Pin_14
|
||||
#define PIOS_SPI1_MOSI_PORT GPIOB
|
||||
#define PIOS_SPI1_MOSI_PIN GPIO_Pin_15
|
||||
|
||||
//-------------------------
|
||||
// PIOS_SDCARD
|
||||
//
|
||||
// See also pios_board.c
|
||||
//-------------------------
|
||||
#define PIOS_SDCARD_SPI 0
|
||||
#define PIOS_OPAHRS_SPI 1
|
||||
|
||||
//-------------------------
|
||||
// Delay Timer
|
||||
|
245
flight/OpenPilot/System/pios_board.c
Normal file
245
flight/OpenPilot/System/pios_board.c
Normal file
@ -0,0 +1,245 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pios_board.c
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief Defines board specific static initializers for hardware for the OpenPilot board.
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#include <pios.h>
|
||||
#include <pios_spi_priv.h>
|
||||
|
||||
/* MicroSD Interface
|
||||
*
|
||||
* NOTE: Leave this declared as const static data so that it ends up in the
|
||||
* .rodata section (ie. Flash) rather than in the .bss section (RAM).
|
||||
*/
|
||||
void PIOS_SPI_sdcard_irq_handler(void);
|
||||
const struct pios_spi_cfg pios_spi_sdcard_cfg = {
|
||||
.regs = SPI1,
|
||||
.init = {
|
||||
.SPI_Mode = SPI_Mode_Master,
|
||||
.SPI_Direction = SPI_Direction_2Lines_FullDuplex,
|
||||
.SPI_DataSize = SPI_DataSize_8b,
|
||||
.SPI_NSS = SPI_NSS_Soft,
|
||||
.SPI_FirstBit = SPI_FirstBit_MSB,
|
||||
.SPI_CRCPolynomial = 7,
|
||||
.SPI_CPOL = SPI_CPOL_High,
|
||||
.SPI_CPHA = SPI_CPHA_2Edge,
|
||||
.SPI_BaudRatePrescaler = 7 << 3, /* Maximum divider (ie. slowest clock rate) */
|
||||
},
|
||||
.dma = {
|
||||
.ahb_clk = RCC_AHBPeriph_DMA1,
|
||||
|
||||
.irq = {
|
||||
.handler = PIOS_SPI_sdcard_irq_handler,
|
||||
.flags = (DMA1_FLAG_TC2 | DMA1_FLAG_TE2 | DMA1_FLAG_HT2 | DMA1_FLAG_GL2),
|
||||
.init = {
|
||||
.NVIC_IRQChannel = DMA1_Channel2_IRQn,
|
||||
.NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGH,
|
||||
.NVIC_IRQChannelSubPriority = 0,
|
||||
.NVIC_IRQChannelCmd = ENABLE,
|
||||
},
|
||||
},
|
||||
|
||||
.rx = {
|
||||
.channel = DMA1_Channel2,
|
||||
.init = {
|
||||
.DMA_PeripheralBaseAddr = (uint32_t)&(SPI1->DR),
|
||||
.DMA_DIR = DMA_DIR_PeripheralSRC,
|
||||
.DMA_PeripheralInc = DMA_PeripheralInc_Disable,
|
||||
.DMA_MemoryInc = DMA_MemoryInc_Enable,
|
||||
.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte,
|
||||
.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte,
|
||||
.DMA_Mode = DMA_Mode_Normal,
|
||||
.DMA_Priority = DMA_Priority_Medium,
|
||||
.DMA_M2M = DMA_M2M_Disable,
|
||||
},
|
||||
},
|
||||
.tx = {
|
||||
.channel = DMA1_Channel3,
|
||||
.init = {
|
||||
.DMA_PeripheralBaseAddr = (uint32_t)&(SPI1->DR),
|
||||
.DMA_DIR = DMA_DIR_PeripheralDST,
|
||||
.DMA_PeripheralInc = DMA_PeripheralInc_Disable,
|
||||
.DMA_MemoryInc = DMA_MemoryInc_Enable,
|
||||
.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte,
|
||||
.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte,
|
||||
.DMA_Mode = DMA_Mode_Normal,
|
||||
.DMA_Priority = DMA_Priority_Medium,
|
||||
.DMA_M2M = DMA_M2M_Disable,
|
||||
},
|
||||
},
|
||||
},
|
||||
.ssel = {
|
||||
.gpio = GPIOA,
|
||||
.init = {
|
||||
.GPIO_Pin = GPIO_Pin_4,
|
||||
.GPIO_Speed = GPIO_Speed_50MHz,
|
||||
.GPIO_Mode = GPIO_Mode_Out_PP,
|
||||
},
|
||||
},
|
||||
.sclk = {
|
||||
.gpio = GPIOA,
|
||||
.init = {
|
||||
.GPIO_Pin = GPIO_Pin_5,
|
||||
.GPIO_Speed = GPIO_Speed_50MHz,
|
||||
.GPIO_Mode = GPIO_Mode_AF_PP,
|
||||
},
|
||||
},
|
||||
.miso = {
|
||||
.gpio = GPIOA,
|
||||
.init = {
|
||||
.GPIO_Pin = GPIO_Pin_6,
|
||||
.GPIO_Speed = GPIO_Speed_50MHz,
|
||||
.GPIO_Mode = GPIO_Mode_IPU,
|
||||
},
|
||||
},
|
||||
.mosi = {
|
||||
.gpio = GPIOA,
|
||||
.init = {
|
||||
.GPIO_Pin = GPIO_Pin_7,
|
||||
.GPIO_Speed = GPIO_Speed_50MHz,
|
||||
.GPIO_Mode = GPIO_Mode_AF_PP,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
/* AHRS Interface
|
||||
*
|
||||
* NOTE: Leave this declared as const static data so that it ends up in the
|
||||
* .rodata section (ie. Flash) rather than in the .bss section (RAM).
|
||||
*/
|
||||
void PIOS_SPI_ahrs_irq_handler(void);
|
||||
const struct pios_spi_cfg pios_spi_ahrs_cfg = {
|
||||
.regs = SPI2,
|
||||
.init = {
|
||||
.SPI_Mode = SPI_Mode_Master,
|
||||
.SPI_Direction = SPI_Direction_2Lines_FullDuplex,
|
||||
.SPI_DataSize = SPI_DataSize_8b,
|
||||
.SPI_NSS = SPI_NSS_Soft,
|
||||
.SPI_FirstBit = SPI_FirstBit_MSB,
|
||||
.SPI_CRCPolynomial = 7,
|
||||
.SPI_CPOL = SPI_CPOL_High,
|
||||
.SPI_CPHA = SPI_CPHA_2Edge,
|
||||
.SPI_BaudRatePrescaler = 7 << 3, /* Maximum divider (ie. slowest clock rate) */
|
||||
},
|
||||
.dma = {
|
||||
.ahb_clk = RCC_AHBPeriph_DMA1,
|
||||
|
||||
.irq = {
|
||||
.handler = PIOS_SPI_ahrs_irq_handler,
|
||||
.flags = (DMA1_FLAG_TC4 | DMA1_FLAG_TE4 | DMA1_FLAG_HT4 | DMA1_FLAG_GL4),
|
||||
.init = {
|
||||
.NVIC_IRQChannel = DMA1_Channel4_IRQn,
|
||||
.NVIC_IRQChannelPreemptionPriority = PIOS_IRQ_PRIO_HIGH,
|
||||
.NVIC_IRQChannelSubPriority = 0,
|
||||
.NVIC_IRQChannelCmd = ENABLE,
|
||||
},
|
||||
},
|
||||
|
||||
.rx = {
|
||||
.channel = DMA1_Channel4,
|
||||
.init = {
|
||||
.DMA_PeripheralBaseAddr = (uint32_t)&(SPI2->DR),
|
||||
.DMA_DIR = DMA_DIR_PeripheralSRC,
|
||||
.DMA_PeripheralInc = DMA_PeripheralInc_Disable,
|
||||
.DMA_MemoryInc = DMA_MemoryInc_Enable,
|
||||
.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte,
|
||||
.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte,
|
||||
.DMA_Mode = DMA_Mode_Normal,
|
||||
.DMA_Priority = DMA_Priority_Medium,
|
||||
.DMA_M2M = DMA_M2M_Disable,
|
||||
},
|
||||
},
|
||||
.tx = {
|
||||
.channel = DMA1_Channel5,
|
||||
.init = {
|
||||
.DMA_PeripheralBaseAddr = (uint32_t)&(SPI2->DR),
|
||||
.DMA_DIR = DMA_DIR_PeripheralDST,
|
||||
.DMA_PeripheralInc = DMA_PeripheralInc_Disable,
|
||||
.DMA_MemoryInc = DMA_MemoryInc_Enable,
|
||||
.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte,
|
||||
.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte,
|
||||
.DMA_Mode = DMA_Mode_Normal,
|
||||
.DMA_Priority = DMA_Priority_Medium,
|
||||
.DMA_M2M = DMA_M2M_Disable,
|
||||
},
|
||||
},
|
||||
},
|
||||
.ssel = {
|
||||
.gpio = GPIOB,
|
||||
.init = {
|
||||
.GPIO_Pin = GPIO_Pin_12,
|
||||
.GPIO_Speed = GPIO_Speed_50MHz,
|
||||
.GPIO_Mode = GPIO_Mode_Out_PP,
|
||||
},
|
||||
},
|
||||
.sclk = {
|
||||
.gpio = GPIOB,
|
||||
.init = {
|
||||
.GPIO_Pin = GPIO_Pin_13,
|
||||
.GPIO_Speed = GPIO_Speed_50MHz,
|
||||
.GPIO_Mode = GPIO_Mode_AF_PP,
|
||||
},
|
||||
},
|
||||
.miso = {
|
||||
.gpio = GPIOB,
|
||||
.init = {
|
||||
.GPIO_Pin = GPIO_Pin_14,
|
||||
.GPIO_Speed = GPIO_Speed_50MHz,
|
||||
.GPIO_Mode = GPIO_Mode_IPU,
|
||||
},
|
||||
},
|
||||
.mosi = {
|
||||
.gpio = GPIOB,
|
||||
.init = {
|
||||
.GPIO_Pin = GPIO_Pin_15,
|
||||
.GPIO_Speed = GPIO_Speed_50MHz,
|
||||
.GPIO_Mode = GPIO_Mode_AF_PP,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
/*
|
||||
* Board specific number of devices.
|
||||
*/
|
||||
struct pios_spi_dev pios_spi_devs[] = {
|
||||
{
|
||||
.cfg = &pios_spi_sdcard_cfg,
|
||||
},
|
||||
{
|
||||
.cfg = &pios_spi_ahrs_cfg,
|
||||
},
|
||||
};
|
||||
|
||||
uint8_t pios_spi_num_devices = NELEMENTS(pios_spi_devs);
|
||||
|
||||
void PIOS_SPI_sdcard_irq_handler(void)
|
||||
{
|
||||
/* Call into the generic code to handle the IRQ for this specific device */
|
||||
PIOS_SPI_IRQ_Handler(PIOS_SDCARD_SPI);
|
||||
}
|
||||
|
||||
void PIOS_SPI_ahrs_irq_handler(void)
|
||||
{
|
||||
/* Call into the generic code to handle the IRQ for this specific device */
|
||||
PIOS_SPI_IRQ_Handler(PIOS_OPAHRS_SPI);
|
||||
}
|
@ -100,12 +100,12 @@ int32_t PIOS_SDCARD_Init(void)
|
||||
|
||||
sdcard_mounted = 0;
|
||||
|
||||
/* Ensure that fast pin drivers are activated */
|
||||
PIOS_SPI_IO_Init(PIOS_SDCARD_SPI, PIOS_SPI_PIN_DRIVER_STRONG);
|
||||
//PIOS_SPI_Init(PIOS_SDCARD_SPI);
|
||||
|
||||
/* Init SPI port for slow frequency access (ca. 0.3 MBit/s) */
|
||||
PIOS_SPI_TransferModeInit(PIOS_SDCARD_SPI, PIOS_SPI_MODE_CLK1_PHASE1, PIOS_SPI_PRESCALER_256);
|
||||
PIOS_SPI_SetClockSpeed(PIOS_SDCARD_SPI, PIOS_SPI_PRESCALER_256);
|
||||
|
||||
PIOS_SPI_TransferByte(PIOS_SDCARD_SPI, 0xFF);
|
||||
SDCARD_MUTEX_GIVE;
|
||||
|
||||
/* No error */
|
||||
@ -127,7 +127,7 @@ int32_t PIOS_SDCARD_PowerOn(void)
|
||||
PIOS_SPI_RC_PinSet(PIOS_SDCARD_SPI, 1); /* spi, pin_value */
|
||||
|
||||
/* Init SPI port for slow frequency access (ca. 0.3 MBit/s) */
|
||||
PIOS_SPI_TransferModeInit(PIOS_SDCARD_SPI, PIOS_SPI_MODE_CLK1_PHASE1, PIOS_SPI_PRESCALER_256);
|
||||
PIOS_SPI_SetClockSpeed(PIOS_SDCARD_SPI, PIOS_SPI_PRESCALER_256);
|
||||
|
||||
/* Send 80 clock cycles to start up */
|
||||
for(i=0; i<10; ++i) {
|
||||
@ -270,7 +270,7 @@ int32_t PIOS_SDCARD_CheckAvailable(uint8_t was_available)
|
||||
if(was_available) {
|
||||
/* Init SPI port for fast frequency access (ca. 18 MBit/s) */
|
||||
/* This is required for the case that the SPI port is shared with other devices */
|
||||
PIOS_SPI_TransferModeInit(PIOS_SDCARD_SPI, PIOS_SPI_MODE_CLK1_PHASE1, PIOS_SPI_PRESCALER_4);
|
||||
PIOS_SPI_SetClockSpeed(PIOS_SDCARD_SPI, PIOS_SPI_PRESCALER_4);
|
||||
|
||||
/* Activate chip select */
|
||||
PIOS_SPI_RC_PinSet(PIOS_SDCARD_SPI, 0); /* spi, pin_value */
|
||||
@ -279,7 +279,7 @@ int32_t PIOS_SDCARD_CheckAvailable(uint8_t was_available)
|
||||
ret = PIOS_SDCARD_SendSDCCmd(SDCMD_SEND_STATUS, 0, SDCMD_SEND_STATUS_CRC);
|
||||
} else {
|
||||
/* Ensure that SPI interface is clocked at low speed */
|
||||
PIOS_SPI_TransferModeInit(PIOS_SDCARD_SPI, PIOS_SPI_MODE_CLK1_PHASE1, PIOS_SPI_PRESCALER_256);
|
||||
PIOS_SPI_SetClockSpeed(PIOS_SDCARD_SPI, PIOS_SPI_PRESCALER_256);
|
||||
|
||||
/* Deactivate chip select */
|
||||
PIOS_SPI_RC_PinSet(PIOS_SDCARD_SPI, 1); /* spi, pin_value */
|
||||
@ -430,7 +430,7 @@ int32_t PIOS_SDCARD_SectorRead(uint32_t sector, uint8_t *buffer)
|
||||
|
||||
/* Init SPI port for fast frequency access (ca. 18 MBit/s) */
|
||||
/* this is required for the case that the SPI port is shared with other devices */
|
||||
PIOS_SPI_TransferModeInit(PIOS_SDCARD_SPI, PIOS_SPI_MODE_CLK1_PHASE1, PIOS_SPI_PRESCALER_4);
|
||||
PIOS_SPI_SetClockSpeed(PIOS_SDCARD_SPI, PIOS_SPI_PRESCALER_4);
|
||||
|
||||
if((status=PIOS_SDCARD_SendSDCCmd(SDCMD_READ_SINGLE_BLOCK, sector, SDCMD_READ_SINGLE_BLOCK_CRC))) {
|
||||
status = (status < 0) ? -256 : status; /* return timeout indicator or error flags */
|
||||
@ -503,7 +503,7 @@ int32_t PIOS_SDCARD_SectorWrite(uint32_t sector, uint8_t *buffer)
|
||||
|
||||
/* Init SPI port for fast frequency access (ca. 18 MBit/s) */
|
||||
/* This is required for the case that the SPI port is shared with other devices */
|
||||
PIOS_SPI_TransferModeInit(PIOS_SDCARD_SPI, PIOS_SPI_MODE_CLK1_PHASE1, PIOS_SPI_PRESCALER_4);
|
||||
PIOS_SPI_SetClockSpeed(PIOS_SDCARD_SPI, PIOS_SPI_PRESCALER_4);
|
||||
|
||||
if((status=PIOS_SDCARD_SendSDCCmd(SDCMD_WRITE_SINGLE_BLOCK, sector, SDCMD_WRITE_SINGLE_BLOCK_CRC))) {
|
||||
status = (status < 0) ? -256 : status; /* Return timeout indicator or error flags */
|
||||
@ -571,7 +571,7 @@ int32_t PIOS_SDCARD_CIDRead(SDCARDCidTypeDef *cid)
|
||||
/* This is required for the case that the SPI port is shared with other devices */
|
||||
SDCARD_MUTEX_TAKE;
|
||||
|
||||
PIOS_SPI_TransferModeInit(PIOS_SDCARD_SPI, PIOS_SPI_MODE_CLK1_PHASE1, PIOS_SPI_PRESCALER_4);
|
||||
PIOS_SPI_SetClockSpeed(PIOS_SDCARD_SPI, PIOS_SPI_PRESCALER_4);
|
||||
|
||||
if((status = PIOS_SDCARD_SendSDCCmd(SDCMD_SEND_CID, 0, SDCMD_SEND_CID_CRC))) {
|
||||
status = (status < 0) ? -256 : status; /* return timeout indicator or error flags */
|
||||
@ -661,7 +661,7 @@ int32_t PIOS_SDCARD_CSDRead(SDCARDCsdTypeDef *csd)
|
||||
|
||||
/* Init SPI port for fast frequency access (ca. 18 MBit/s) */
|
||||
/* This is required for the case that the SPI port is shared with other devices */
|
||||
PIOS_SPI_TransferModeInit(PIOS_SDCARD_SPI, PIOS_SPI_MODE_CLK1_PHASE1, PIOS_SPI_PRESCALER_4);
|
||||
PIOS_SPI_SetClockSpeed(PIOS_SDCARD_SPI, PIOS_SPI_PRESCALER_4);
|
||||
|
||||
if((status = PIOS_SDCARD_SendSDCCmd(SDCMD_SEND_CSD, 0, SDCMD_SEND_CSD_CRC))) {
|
||||
status = (status < 0) ? -256 : status; /* Return timeout indicator or error flags */
|
||||
@ -811,7 +811,7 @@ int32_t PIOS_SDCARD_StartupLog(void)
|
||||
/**
|
||||
* Check if the SD card has been mounted
|
||||
* @return 0 if no
|
||||
* @return 1 if yes
|
||||
* @return 1 if yes
|
||||
*/
|
||||
int32_t POIS_SDCARD_IsMounted()
|
||||
{
|
||||
|
@ -8,7 +8,7 @@
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
* @defgroup PIOS_SPI SPI Functions
|
||||
* @notes
|
||||
* J19 provides two RCLK (alias Chip Select) lines.<BR>
|
||||
* J19 provides two SSEL (alias Chip Select) lines.<BR>
|
||||
* It's a software emulated SPI, therefore the selected spi_prescaler has no
|
||||
* effect! Bytes are transfered so fast as possible. The usage of
|
||||
* PIOS_SPI_PIN_DRIVER_STRONG is strongly recommended ;)<BR>
|
||||
@ -41,12 +41,18 @@
|
||||
|
||||
#if defined(PIOS_INCLUDE_SPI)
|
||||
|
||||
#include <pios_spi_priv.h>
|
||||
|
||||
/* Local variables */
|
||||
static void (*spi_callback[PIOS_SPI_NUM])(void);
|
||||
static uint8_t tx_dummy_byte;
|
||||
static uint8_t rx_dummy_byte;
|
||||
static struct pios_spi_dev * find_spi_dev_by_id (uint8_t spi)
|
||||
{
|
||||
if (spi >= pios_spi_num_devices) {
|
||||
/* Undefined SPI port for this board (see pios_board.c) */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Get a handle for the device configuration */
|
||||
return &(pios_spi_devs[spi]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialises SPI pins
|
||||
@ -55,251 +61,94 @@ static uint8_t rx_dummy_byte;
|
||||
*/
|
||||
int32_t PIOS_SPI_Init(void)
|
||||
{
|
||||
DMA_InitTypeDef DMA_InitStructure;
|
||||
DMA_StructInit(&DMA_InitStructure);
|
||||
NVIC_InitTypeDef NVIC_InitStructure;
|
||||
struct pios_spi_dev * spi_dev;
|
||||
uint8_t i;
|
||||
|
||||
#if (PIOS_SPI0_ENABLED)
|
||||
/* SPI0 */
|
||||
/* Disable callback function */
|
||||
spi_callback[0] = NULL;
|
||||
for (i = 0; i < pios_spi_num_devices; i++) {
|
||||
/* Get a handle for the device configuration */
|
||||
spi_dev = find_spi_dev_by_id(i);
|
||||
PIOS_DEBUG_Assert(spi_dev);
|
||||
|
||||
/* Set RC pin(s) to 1 */
|
||||
PIOS_SPI_RC_PinSet(0, 1); // spi, rc_pin, pin_value
|
||||
/* Disable callback function */
|
||||
spi_dev->callback = NULL;
|
||||
|
||||
/* IO configuration */
|
||||
PIOS_SPI_IO_Init(0, PIOS_SPI_PIN_DRIVER_WEAK_OD);
|
||||
/* Set rx/tx dummy bytes to a known value */
|
||||
spi_dev->rx_dummy_byte = 0xFF;
|
||||
spi_dev->tx_dummy_byte = 0xFF;
|
||||
|
||||
/* Enable SPI peripheral clock (APB2 == high speed) */
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
|
||||
switch (spi_dev->cfg->init.SPI_NSS) {
|
||||
case SPI_NSS_Soft:
|
||||
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));
|
||||
} 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:
|
||||
GPIO_Init(spi_dev->cfg->ssel.gpio, &(spi_dev->cfg->ssel.init));
|
||||
break;
|
||||
default:
|
||||
PIOS_DEBUG_Assert(0);
|
||||
}
|
||||
|
||||
/* Initialize the GPIO pins */
|
||||
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));
|
||||
|
||||
/* Enable DMA1 clock */
|
||||
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
|
||||
/* Enable the associated peripheral clock */
|
||||
switch ((uint32_t)spi_dev->cfg->regs) {
|
||||
case (uint32_t)SPI1:
|
||||
/* Enable SPI peripheral clock (APB2 == high speed) */
|
||||
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE);
|
||||
break;
|
||||
case (uint32_t)SPI2:
|
||||
/* Enable SPI peripheral clock (APB1 == slow speed) */
|
||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
|
||||
break;
|
||||
case (uint32_t)SPI3:
|
||||
/* Enable SPI peripheral clock (APB1 == slow speed) */
|
||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Enable DMA clock */
|
||||
RCC_AHBPeriphClockCmd(spi_dev->cfg->dma.ahb_clk, ENABLE);
|
||||
|
||||
/* Configure DMA for SPI Rx */
|
||||
DMA_Cmd(spi_dev->cfg->dma.rx.channel, DISABLE);
|
||||
DMA_Init(spi_dev->cfg->dma.rx.channel, &(spi_dev->cfg->dma.rx.init));
|
||||
|
||||
/* Configure DMA for SPI Tx */
|
||||
DMA_Cmd(spi_dev->cfg->dma.tx.channel, DISABLE);
|
||||
DMA_Init(spi_dev->cfg->dma.tx.channel, &(spi_dev->cfg->dma.tx.init));
|
||||
|
||||
/* DMA Configuration for SPI Rx Event */
|
||||
DMA_Cmd(PIOS_SPI0_DMA_RX_PTR, DISABLE);
|
||||
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&PIOS_SPI0_PTR->DR;
|
||||
DMA_InitStructure.DMA_MemoryBaseAddr = 0; /* Will be configured later */
|
||||
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
|
||||
DMA_InitStructure.DMA_BufferSize = 0; /* Will be configured later */
|
||||
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
|
||||
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
|
||||
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
|
||||
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
|
||||
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
|
||||
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
|
||||
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
|
||||
DMA_Init(PIOS_SPI0_DMA_RX_PTR, &DMA_InitStructure);
|
||||
/* Initialize the SPI block */
|
||||
SPI_Init(spi_dev->cfg->regs, &(spi_dev->cfg->init));
|
||||
|
||||
/* DMA Configuration for SPI Tx Event */
|
||||
/* (partly re-using previous DMA setup) */
|
||||
DMA_Cmd(PIOS_SPI0_DMA_TX_PTR, DISABLE);
|
||||
DMA_InitStructure.DMA_MemoryBaseAddr = 0; /* Will be configured later */
|
||||
DMA_InitStructure.DMA_BufferSize = 0; /* Will be configured later */
|
||||
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
|
||||
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
|
||||
DMA_Init(PIOS_SPI0_DMA_TX_PTR, &DMA_InitStructure);
|
||||
/* Enable SPI */
|
||||
SPI_Cmd(spi_dev->cfg->regs, ENABLE);
|
||||
|
||||
/* Initial SPI peripheral configuration */
|
||||
PIOS_SPI_TransferModeInit(0, PIOS_SPI_MODE_CLK1_PHASE1, PIOS_SPI_PRESCALER_128);
|
||||
/* Enable SPI interrupts to DMA */
|
||||
SPI_I2S_DMACmd(spi_dev->cfg->regs, SPI_I2S_DMAReq_Tx | SPI_I2S_DMAReq_Rx, ENABLE);
|
||||
|
||||
/* Enable SPI */
|
||||
SPI_Cmd(PIOS_SPI0_PTR, ENABLE);
|
||||
/* Configure DMA interrupt */
|
||||
NVIC_Init(&(spi_dev->cfg->dma.irq.init));
|
||||
}
|
||||
|
||||
/* Enable SPI interrupts to DMA */
|
||||
SPI_I2S_DMACmd(PIOS_SPI0_PTR, SPI_I2S_DMAReq_Tx | SPI_I2S_DMAReq_Rx, ENABLE);
|
||||
|
||||
/* Configure DMA interrupt */
|
||||
NVIC_InitStructure.NVIC_IRQChannel = PIOS_SPI0_DMA_IRQ_CHANNEL;
|
||||
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = PIOS_SPI_IRQ_DMA_PRIORITY;
|
||||
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
|
||||
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
||||
NVIC_Init(&NVIC_InitStructure);
|
||||
#endif
|
||||
|
||||
#if (PIOS_SPI1_ENABLED)
|
||||
/* SPI1 */
|
||||
/* Disable callback function */
|
||||
spi_callback[1] = NULL;
|
||||
|
||||
/* Set RC pin(s) to 1 */
|
||||
PIOS_SPI_RC_PinSet(1, 1); /* spi, pin_value */
|
||||
|
||||
/* IO configuration */
|
||||
PIOS_SPI_IO_Init(1, PIOS_SPI_PIN_DRIVER_WEAK_OD);
|
||||
|
||||
/* Enable SPI peripheral clock (APB1 == slow speed) */
|
||||
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);
|
||||
|
||||
/* Enable DMA1 clock */
|
||||
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
|
||||
|
||||
/* DMA Configuration for SPI Rx Event */
|
||||
DMA_Cmd(PIOS_SPI1_DMA_RX_PTR, DISABLE);
|
||||
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&PIOS_SPI1_PTR->DR;
|
||||
DMA_InitStructure.DMA_MemoryBaseAddr = 0; // will be configured later
|
||||
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralSRC;
|
||||
DMA_InitStructure.DMA_BufferSize = 0; // will be configured later
|
||||
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
|
||||
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
|
||||
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
|
||||
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
|
||||
DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
|
||||
DMA_InitStructure.DMA_Priority = DMA_Priority_Medium;
|
||||
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
|
||||
DMA_Init(PIOS_SPI1_DMA_RX_PTR, &DMA_InitStructure);
|
||||
|
||||
/* DMA Configuration for SPI Tx Event */
|
||||
/* (partly re-using previous DMA setup) */
|
||||
DMA_Cmd(PIOS_SPI1_DMA_TX_PTR, DISABLE);
|
||||
DMA_InitStructure.DMA_MemoryBaseAddr = 0; // will be configured later
|
||||
DMA_InitStructure.DMA_BufferSize = 0; // will be configured later
|
||||
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
|
||||
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
|
||||
DMA_Init(PIOS_SPI1_DMA_TX_PTR, &DMA_InitStructure);
|
||||
|
||||
/* Initial SPI peripheral configuration */
|
||||
PIOS_SPI_TransferModeInit(1, PIOS_SPI_MODE_CLK1_PHASE1, PIOS_SPI_PRESCALER_128);
|
||||
|
||||
/* Enable SPI */
|
||||
SPI_Cmd(PIOS_SPI1_PTR, ENABLE);
|
||||
|
||||
/* Enable SPI interrupts to DMA */
|
||||
SPI_I2S_DMACmd(PIOS_SPI1_PTR, SPI_I2S_DMAReq_Tx | SPI_I2S_DMAReq_Rx, ENABLE);
|
||||
|
||||
/* Configure DMA interrupt */
|
||||
NVIC_InitStructure.NVIC_IRQChannel = PIOS_SPI1_DMA_IRQ_CHANNEL;
|
||||
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = PIOS_SPI_IRQ_DMA_PRIORITY; /* defined in PIOS_irq.h */
|
||||
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
|
||||
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
|
||||
NVIC_Init(&NVIC_InitStructure);
|
||||
#endif
|
||||
|
||||
/* No error */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* (Re-)initializes SPI IO Pins
|
||||
* By default, all output pins are configured with weak open drain drivers for 2 MHz
|
||||
* \param[in] spi SPI number (0, 1 or 2)
|
||||
* \param[in] spi_pin_driver configures the driver strength:
|
||||
* <UL>
|
||||
* <LI>PIOS_SPI_PIN_DRIVER_STRONG: Configures outputs for up to 50 MHz
|
||||
* <LI>PIOS_SPI_PIN_DRIVER_STRONG_OD: Configures outputs as open drain
|
||||
* for up to 50 MHz (allows voltage shifting via pull-resistors)
|
||||
* <LI>PIOS_SPI_PIN_DRIVER_WEAK: Configures outputs for up to 2 MHz (better EMC)
|
||||
* <LI>PIOS_SPI_PIN_DRIVER_WEAK_OD: Configures outputs as open drain for
|
||||
* up to 2 MHz (allows voltage shifting via pull-resistors)
|
||||
* </UL>
|
||||
* \return 0 if no error
|
||||
* \return -1 if disabled SPI port selected
|
||||
* \return -2 if unsupported SPI port selected
|
||||
* \return -3 if unsupported pin driver mode
|
||||
*/
|
||||
int32_t PIOS_SPI_IO_Init(uint8_t spi, SPIPinDriverTypeDef spi_pin_driver)
|
||||
{
|
||||
/* Init GPIO structure */
|
||||
GPIO_InitTypeDef GPIO_InitStructure;
|
||||
GPIO_StructInit(&GPIO_InitStructure);
|
||||
|
||||
/* Select pin driver and output mode */
|
||||
uint32_t af_mode;
|
||||
uint32_t gp_mode;
|
||||
|
||||
switch(spi_pin_driver) {
|
||||
case PIOS_SPI_PIN_DRIVER_STRONG:
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
||||
af_mode = GPIO_Mode_AF_PP;
|
||||
gp_mode = GPIO_Mode_Out_PP;
|
||||
break;
|
||||
|
||||
case PIOS_SPI_PIN_DRIVER_STRONG_OD:
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
|
||||
af_mode = GPIO_Mode_AF_OD;
|
||||
gp_mode = GPIO_Mode_Out_OD;
|
||||
break;
|
||||
|
||||
case PIOS_SPI_PIN_DRIVER_WEAK:
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
af_mode = GPIO_Mode_AF_PP;
|
||||
gp_mode = GPIO_Mode_Out_PP;
|
||||
break;
|
||||
|
||||
case PIOS_SPI_PIN_DRIVER_WEAK_OD:
|
||||
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_2MHz;
|
||||
af_mode = GPIO_Mode_AF_OD;
|
||||
gp_mode = GPIO_Mode_Out_OD;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Unsupported pin driver mode */
|
||||
return -3;
|
||||
}
|
||||
|
||||
switch(spi) {
|
||||
case 0:
|
||||
/* SCLK and DOUT are outputs assigned to alternate functions */
|
||||
GPIO_InitStructure.GPIO_Mode = af_mode;
|
||||
GPIO_InitStructure.GPIO_Pin = PIOS_SPI0_SCLK_PIN;
|
||||
GPIO_Init(PIOS_SPI0_SCLK_PORT, &GPIO_InitStructure);
|
||||
GPIO_InitStructure.GPIO_Pin = PIOS_SPI0_MOSI_PIN;
|
||||
GPIO_Init(PIOS_SPI0_MOSI_PORT, &GPIO_InitStructure);
|
||||
|
||||
/* RCLK outputs assigned to GPIO */
|
||||
GPIO_InitStructure.GPIO_Mode = gp_mode;
|
||||
GPIO_InitStructure.GPIO_Pin = PIOS_SPI0_RCLK1_PIN;
|
||||
GPIO_Init(PIOS_SPI0_RCLK1_PORT, &GPIO_InitStructure);
|
||||
|
||||
/* DIN is input with pull-up */
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
|
||||
GPIO_InitStructure.GPIO_Pin = PIOS_SPI0_MISO_PIN;
|
||||
GPIO_Init(PIOS_SPI0_MISO_PORT, &GPIO_InitStructure);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
/* SCLK and DOUT are outputs assigned to alternate functions */
|
||||
GPIO_InitStructure.GPIO_Mode = af_mode;
|
||||
GPIO_InitStructure.GPIO_Pin = PIOS_SPI1_SCLK_PIN;
|
||||
GPIO_Init(PIOS_SPI1_SCLK_PORT, &GPIO_InitStructure);
|
||||
GPIO_InitStructure.GPIO_Pin = PIOS_SPI1_MOSI_PIN;
|
||||
GPIO_Init(PIOS_SPI1_MOSI_PORT, &GPIO_InitStructure);
|
||||
|
||||
/* RCLK outputs assigned to GPIO */
|
||||
GPIO_InitStructure.GPIO_Mode = gp_mode;
|
||||
GPIO_InitStructure.GPIO_Pin = PIOS_SPI1_RCLK1_PIN;
|
||||
GPIO_Init(PIOS_SPI1_RCLK1_PORT, &GPIO_InitStructure);
|
||||
|
||||
/* DIN is input with pull-up */
|
||||
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
|
||||
GPIO_InitStructure.GPIO_Pin = PIOS_SPI1_MISO_PIN;
|
||||
GPIO_Init(PIOS_SPI1_MISO_PORT, &GPIO_InitStructure);
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Unsupported SPI port */
|
||||
return -2;
|
||||
}
|
||||
|
||||
/* No error */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* (Re-)initialises SPI peripheral transfer mode
|
||||
* By default, all SPI peripherals are configured with
|
||||
* PIOS_SPI_MODE_CLK1_PHASE1 and PIOS_SPI_PRESCALER_128
|
||||
* (Re-)initialises SPI peripheral clock rate
|
||||
*
|
||||
* \param[in] spi SPI number (0 or 1)
|
||||
* \param[in] spi_mode configures clock and capture phase:
|
||||
* <UL>
|
||||
* <LI>PIOS_SPI_MODE_CLK0_PHASE0: Idle level of clock is 0, data captured at rising edge
|
||||
* <LI>PIOS_SPI_MODE_CLK0_PHASE1: Idle level of clock is 0, data captured at falling edge
|
||||
* <LI>PIOS_SPI_MODE_CLK1_PHASE0: Idle level of clock is 1, data captured at falling edge
|
||||
* <LI>PIOS_SPI_MODE_CLK1_PHASE1: Idle level of clock is 1, data captured at rising edge
|
||||
* </UL>
|
||||
* \param[in] spi_prescaler configures the SPI speed:
|
||||
* <UL>
|
||||
* <LI>PIOS_SPI_PRESCALER_2: sets clock rate 27.7~ nS @ 72 MHz (36 MBit/s) (only supported for spi==0, spi1 uses 4 instead)
|
||||
@ -315,94 +164,38 @@ int32_t PIOS_SPI_IO_Init(uint8_t spi, SPIPinDriverTypeDef spi_pin_driver)
|
||||
* \return -1 if disabled SPI port selected
|
||||
* \return -2 if unsupported SPI port selected
|
||||
* \return -3 if invalid spi_prescaler selected
|
||||
* \return -4 if invalid spi_mode selected
|
||||
*/
|
||||
int32_t PIOS_SPI_TransferModeInit(uint8_t spi, SPIModeTypeDef spi_mode, SPIPrescalerTypeDef spi_prescaler)
|
||||
int32_t PIOS_SPI_SetClockSpeed(uint8_t spi, SPIPrescalerTypeDef spi_prescaler)
|
||||
{
|
||||
/* SPI configuration */
|
||||
SPI_InitTypeDef SPI_InitStructure;
|
||||
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
|
||||
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
|
||||
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
|
||||
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
|
||||
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
|
||||
SPI_InitStructure.SPI_CRCPolynomial = 7;
|
||||
struct pios_spi_dev * spi_dev;
|
||||
SPI_InitTypeDef SPI_InitStructure;
|
||||
|
||||
switch(spi_mode) {
|
||||
case PIOS_SPI_MODE_CLK0_PHASE0:
|
||||
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
|
||||
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
|
||||
break;
|
||||
case PIOS_SPI_MODE_CLK0_PHASE1:
|
||||
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
|
||||
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
|
||||
break;
|
||||
case PIOS_SPI_MODE_CLK1_PHASE0:
|
||||
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
|
||||
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
|
||||
break;
|
||||
case PIOS_SPI_MODE_CLK1_PHASE1:
|
||||
SPI_InitStructure.SPI_CPOL = SPI_CPOL_High;
|
||||
SPI_InitStructure.SPI_CPHA = SPI_CPHA_2Edge;
|
||||
break;
|
||||
default:
|
||||
/* Invalid SPI clock/phase mode */
|
||||
return -4;
|
||||
}
|
||||
/* Get a handle for the device configuration */
|
||||
spi_dev = find_spi_dev_by_id(spi);
|
||||
|
||||
if(spi_prescaler >= 8) {
|
||||
/* Invalid prescaler selected */
|
||||
return -3;
|
||||
}
|
||||
if (!spi_dev) {
|
||||
/* Undefined SPI port for this board (see pios_board.c) */
|
||||
return -2;
|
||||
}
|
||||
|
||||
switch(spi) {
|
||||
case 0: {
|
||||
uint16_t prev_cr1 = PIOS_SPI0_PTR->CR1;
|
||||
/* SPI1 perpipheral is located in APB2 domain and clocked at full speed */
|
||||
/* therefore we have to add +1 to the prescaler */
|
||||
SPI_InitStructure.SPI_BaudRatePrescaler = ((uint16_t)spi_prescaler&7) << 3;
|
||||
SPI_Init(PIOS_SPI0_PTR, &SPI_InitStructure);
|
||||
if(spi_prescaler >= 8) {
|
||||
/* Invalid prescaler selected */
|
||||
return -3;
|
||||
}
|
||||
|
||||
if((prev_cr1 ^ PIOS_SPI0_PTR->CR1) & 3) {
|
||||
/* CPOL and CPHA located at bit #1 and #0 */
|
||||
/* clock configuration has been changed - we should send a dummy byte */
|
||||
/* before the application activates chip select. */
|
||||
/* this solves a dependency between SDCard and ENC28J60 driver */
|
||||
PIOS_SPI_TransferByte(spi, 0xff);
|
||||
}
|
||||
/* Start with a copy of the default configuration for the peripheral */
|
||||
SPI_InitStructure = spi_dev->cfg->init;
|
||||
|
||||
} break;
|
||||
/* Adjust the prescaler for the peripheral's clock */
|
||||
SPI_InitStructure.SPI_BaudRatePrescaler = ((uint16_t)spi_prescaler & 7) << 3;
|
||||
|
||||
case 1: {
|
||||
uint16_t prev_cr1 = PIOS_SPI1_PTR->CR1;
|
||||
/* Write back the new configuration */
|
||||
SPI_Init(spi_dev->cfg->regs, &SPI_InitStructure);
|
||||
|
||||
/* SPI2 perpipheral is located in APB1 domain and clocked at half speed */
|
||||
if(spi_prescaler == 0) {
|
||||
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2;
|
||||
} else {
|
||||
SPI_InitStructure.SPI_BaudRatePrescaler = (((uint16_t)spi_prescaler&7)-1) << 3;
|
||||
}
|
||||
SPI_Init(PIOS_SPI1_PTR, &SPI_InitStructure);
|
||||
|
||||
if((prev_cr1 ^ PIOS_SPI1_PTR->CR1) & 3) {
|
||||
/* CPOL and CPHA located at bit #1 and #0 */
|
||||
/* clock configuration has been changed - we should send a dummy byte */
|
||||
/* before the application activates chip select. */
|
||||
/* this solves a dependency between SDCard and ENC28J60 driver */
|
||||
PIOS_SPI_TransferByte(spi, 0xff);
|
||||
}
|
||||
} break;
|
||||
|
||||
default:
|
||||
/* Unsupported SPI port */
|
||||
return -2;
|
||||
}
|
||||
|
||||
/* No error */
|
||||
return 0;
|
||||
PIOS_SPI_TransferByte(spi, 0xFF);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Controls the RC (Register Clock alias Chip Select) pin of a SPI port
|
||||
* \param[in] spi SPI number (0 or 1)
|
||||
@ -413,34 +206,25 @@ int32_t PIOS_SPI_TransferModeInit(uint8_t spi, SPIModeTypeDef spi_mode, SPIPresc
|
||||
*/
|
||||
int32_t PIOS_SPI_RC_PinSet(uint8_t spi, uint8_t pin_value)
|
||||
{
|
||||
switch(spi) {
|
||||
case 0:
|
||||
if(pin_value) {
|
||||
PIOS_SPI0_RCLK1_PORT->BSRR = PIOS_SPI0_RCLK1_PIN;
|
||||
} else {
|
||||
PIOS_SPI0_RCLK1_PORT->BRR = PIOS_SPI0_RCLK1_PIN;
|
||||
}
|
||||
break;
|
||||
struct pios_spi_dev * spi_dev;
|
||||
|
||||
case 1:
|
||||
if(pin_value) {
|
||||
PIOS_SPI1_RCLK1_PORT->BSRR = PIOS_SPI1_RCLK1_PIN;
|
||||
} else {
|
||||
PIOS_SPI1_RCLK1_PORT->BRR = PIOS_SPI1_RCLK1_PIN;
|
||||
}
|
||||
/* Get a handle for the device configuration */
|
||||
spi_dev = find_spi_dev_by_id(spi);
|
||||
|
||||
break;
|
||||
if (!spi_dev) {
|
||||
/* Undefined SPI port for this board (see pios_board.c) */
|
||||
return -2;
|
||||
}
|
||||
|
||||
default:
|
||||
/* Unsupported SPI port */
|
||||
return -2;
|
||||
}
|
||||
if (pin_value) {
|
||||
GPIO_SetBits(spi_dev->cfg->ssel.gpio, spi_dev->cfg->ssel.init.GPIO_Pin);
|
||||
} else {
|
||||
GPIO_ResetBits(spi_dev->cfg->ssel.gpio, spi_dev->cfg->ssel.init.GPIO_Pin);
|
||||
}
|
||||
|
||||
/* No error */
|
||||
return 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Transfers a byte to SPI output and reads back the return value from SPI input
|
||||
* \param[in] spi SPI number (0 or 1)
|
||||
@ -452,41 +236,42 @@ int32_t PIOS_SPI_RC_PinSet(uint8_t spi, uint8_t pin_value)
|
||||
*/
|
||||
int32_t PIOS_SPI_TransferByte(uint8_t spi, uint8_t b)
|
||||
{
|
||||
SPI_TypeDef *spi_ptr;
|
||||
struct pios_spi_dev * spi_dev;
|
||||
uint8_t dummy;
|
||||
uint8_t rx_byte;
|
||||
|
||||
switch(spi) {
|
||||
case 0:
|
||||
spi_ptr = PIOS_SPI0_PTR;
|
||||
break;
|
||||
/* Get a handle for the device configuration */
|
||||
spi_dev = find_spi_dev_by_id(spi);
|
||||
|
||||
case 1:
|
||||
spi_ptr = PIOS_SPI1_PTR;
|
||||
break;
|
||||
if (!spi_dev) {
|
||||
/* Undefined SPI port for this board (see pios_board.c) */
|
||||
return -2;
|
||||
}
|
||||
|
||||
default:
|
||||
/* Unsupported SPI port */
|
||||
return -2;
|
||||
}
|
||||
/*
|
||||
* Procedure taken from STM32F10xxx Reference Manual section 23.3.5
|
||||
*/
|
||||
|
||||
/* Send byte */
|
||||
spi_ptr->DR = b;
|
||||
/* Make sure the RXNE flag is cleared by reading the DR register */
|
||||
dummy = spi_dev->cfg->regs->DR;
|
||||
|
||||
if(spi_ptr->SR); /* Dummy read due to undocumented pipelining issue :-/ */
|
||||
/* TK: without this read (which can be done to any bus location) we could sporadically */
|
||||
/* get the status byte at the moment where DR is written. Accordingly, the busy bit */
|
||||
/* will be 0. */
|
||||
/* you won't see this dummy read in STM drivers, as they never have a DR write */
|
||||
/* followed by SR read, or as they are using SPI1/SPI2 pointers, which results into */
|
||||
/* some additional CPU instructions between strh/ldrh accesses. */
|
||||
/* We use a bus access instead of NOPs to avoid any risk for back-to-back transactions */
|
||||
/* over AHB (if SPI1/SPI2 pointers are used, there is still a risk for such a scenario, */
|
||||
/* e.g. if DMA loads the bus!) */
|
||||
/* Start the transfer */
|
||||
spi_dev->cfg->regs->DR = b;
|
||||
|
||||
/* Wait until SPI transfer finished */
|
||||
while(spi_ptr->SR & SPI_I2S_FLAG_BSY);
|
||||
/* Wait until there is a byte to read */
|
||||
while(!(spi_dev->cfg->regs->SR & SPI_I2S_FLAG_RXNE));
|
||||
|
||||
/* Return received byte */
|
||||
return spi_ptr->DR;
|
||||
/* Read the rx'd byte */
|
||||
rx_byte = spi_dev->cfg->regs->DR;
|
||||
|
||||
/* Wait until the TXE goes high */
|
||||
while (!(spi_dev->cfg->regs->SR & SPI_I2S_FLAG_TXE));
|
||||
|
||||
/* Wait for SPI transfer to have fully completed */
|
||||
while (spi_dev->cfg->regs->SR & SPI_I2S_FLAG_BSY);
|
||||
|
||||
/* Return received byte */
|
||||
return rx_byte;
|
||||
}
|
||||
|
||||
|
||||
@ -509,94 +294,90 @@ int32_t PIOS_SPI_TransferByte(uint8_t spi, uint8_t b)
|
||||
*/
|
||||
int32_t PIOS_SPI_TransferBlock(uint8_t spi, uint8_t *send_buffer, uint8_t *receive_buffer, uint16_t len, void *callback)
|
||||
{
|
||||
DMA_Channel_TypeDef *dma_tx_ptr, *dma_rx_ptr;
|
||||
struct pios_spi_dev * spi_dev;
|
||||
DMA_InitTypeDef dma_init;
|
||||
|
||||
switch(spi) {
|
||||
case 0:
|
||||
dma_tx_ptr = PIOS_SPI0_DMA_TX_PTR;
|
||||
dma_rx_ptr = PIOS_SPI0_DMA_RX_PTR;
|
||||
break;
|
||||
/* Get a handle for the device configuration */
|
||||
spi_dev = find_spi_dev_by_id(spi);
|
||||
|
||||
case 1:
|
||||
dma_tx_ptr = PIOS_SPI1_DMA_TX_PTR;
|
||||
dma_rx_ptr = PIOS_SPI1_DMA_RX_PTR;
|
||||
break;
|
||||
if (!spi_dev) {
|
||||
/* Undefined SPI port for this board (see pios_board.c) */
|
||||
return -2;
|
||||
}
|
||||
|
||||
default:
|
||||
/* Unsupported SPI port */
|
||||
return -2;
|
||||
}
|
||||
|
||||
/* Exit if ongoing transfer */
|
||||
if(dma_rx_ptr->CNDTR) {
|
||||
return -3;
|
||||
}
|
||||
/* Exit if ongoing transfer */
|
||||
if(spi_dev->cfg->dma.rx.channel->CNDTR) {
|
||||
return -3;
|
||||
}
|
||||
|
||||
/* Set callback function */
|
||||
spi_callback[spi] = callback;
|
||||
/* Set callback function */
|
||||
spi_dev->callback = callback;
|
||||
|
||||
/* Configure Rx channel */
|
||||
DMA_Cmd(dma_rx_ptr, DISABLE);
|
||||
if(receive_buffer != NULL) {
|
||||
/* Enable memory addr. increment - bytes written into receive buffer */
|
||||
dma_rx_ptr->CMAR = (uint32_t)receive_buffer;
|
||||
dma_rx_ptr->CCR |= DMA_MemoryInc_Enable;
|
||||
} else {
|
||||
/* Disable memory addr. increment - bytes written into dummy buffer */
|
||||
rx_dummy_byte = 0xff;
|
||||
dma_rx_ptr->CMAR = (uint32_t)&rx_dummy_byte;
|
||||
dma_rx_ptr->CCR &= ~DMA_MemoryInc_Enable;
|
||||
}
|
||||
dma_rx_ptr->CNDTR = len;
|
||||
DMA_Cmd(dma_rx_ptr, ENABLE);
|
||||
/* Configure Rx channel */
|
||||
DMA_Cmd(spi_dev->cfg->dma.rx.channel, DISABLE);
|
||||
|
||||
/* Configure Tx channel */
|
||||
DMA_Cmd(dma_tx_ptr, DISABLE);
|
||||
if(send_buffer != NULL) {
|
||||
/* Enable memory addr. increment - bytes read from send buffer */
|
||||
dma_tx_ptr->CMAR = (uint32_t)send_buffer;
|
||||
dma_tx_ptr->CCR |= DMA_MemoryInc_Enable;
|
||||
} else {
|
||||
/* Disable memory addr. increment - bytes read from dummy buffer */
|
||||
tx_dummy_byte = 0xff;
|
||||
dma_tx_ptr->CMAR = (uint32_t)&tx_dummy_byte;
|
||||
dma_tx_ptr->CCR &= ~DMA_MemoryInc_Enable;
|
||||
}
|
||||
dma_tx_ptr->CNDTR = len;
|
||||
/* Start with the default configuration for this peripheral */
|
||||
dma_init = spi_dev->cfg->dma.rx.init;
|
||||
|
||||
/* Enable DMA interrupt if callback function active */
|
||||
DMA_ITConfig(dma_rx_ptr, DMA_IT_TC, (callback != NULL) ? ENABLE : DISABLE);
|
||||
if(receive_buffer != NULL) {
|
||||
/* Enable memory addr. increment - bytes written into receive buffer */
|
||||
dma_init.DMA_MemoryBaseAddr = (uint32_t)receive_buffer;
|
||||
dma_init.DMA_MemoryInc = DMA_MemoryInc_Enable;
|
||||
} else {
|
||||
/* Disable memory addr. increment - bytes written into dummy buffer */
|
||||
spi_dev->rx_dummy_byte = 0xff;
|
||||
dma_init.DMA_MemoryBaseAddr = (uint32_t)&spi_dev->rx_dummy_byte;
|
||||
dma_init.DMA_MemoryInc = DMA_MemoryInc_Disable;
|
||||
}
|
||||
dma_init.DMA_MemoryDataSize = len;
|
||||
DMA_Init(spi_dev->cfg->dma.rx.channel, &(dma_init));
|
||||
DMA_Cmd(spi_dev->cfg->dma.rx.channel, ENABLE);
|
||||
|
||||
/* Start DMA transfer */
|
||||
DMA_Cmd(dma_tx_ptr, ENABLE);
|
||||
/* Configure Tx channel */
|
||||
DMA_Cmd(spi_dev->cfg->dma.tx.channel, DISABLE);
|
||||
|
||||
/* Wait until all bytes have been transmitted/received */
|
||||
while(dma_rx_ptr->CNDTR);
|
||||
/* Start with the default configuration for this peripheral */
|
||||
dma_init = spi_dev->cfg->dma.tx.init;
|
||||
|
||||
/* No error */
|
||||
return 0;
|
||||
if(send_buffer != NULL) {
|
||||
/* Enable memory addr. increment - bytes written into receive buffer */
|
||||
dma_init.DMA_MemoryBaseAddr = (uint32_t)send_buffer;
|
||||
dma_init.DMA_MemoryInc = DMA_MemoryInc_Enable;
|
||||
} else {
|
||||
/* Disable memory addr. increment - bytes written into dummy buffer */
|
||||
spi_dev->tx_dummy_byte = 0xff;
|
||||
dma_init.DMA_MemoryBaseAddr = (uint32_t)&spi_dev->tx_dummy_byte;
|
||||
dma_init.DMA_MemoryInc = DMA_MemoryInc_Disable;
|
||||
}
|
||||
dma_init.DMA_MemoryDataSize = len;
|
||||
DMA_Init(spi_dev->cfg->dma.tx.channel, &(dma_init));
|
||||
|
||||
/* Enable DMA interrupt if callback function active */
|
||||
DMA_ITConfig(spi_dev->cfg->dma.rx.channel, DMA_IT_TC, (callback != NULL) ? ENABLE : DISABLE);
|
||||
|
||||
/* Start DMA Tx transfer */
|
||||
DMA_Cmd(spi_dev->cfg->dma.tx.channel, ENABLE);
|
||||
|
||||
/* Wait until all bytes have been transmitted/received */
|
||||
while(DMA_GetCurrDataCounter(spi_dev->cfg->dma.tx.channel));
|
||||
|
||||
/* No error */
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called when callback function has been defined and SPI transfer has finished
|
||||
*/
|
||||
PIOS_SPI0_DMA_IRQHANDLER_FUNC
|
||||
void PIOS_SPI_IRQ_Handler(uint8_t spi)
|
||||
{
|
||||
DMA_ClearFlag(PIOS_SPI0_DMA_RX_IRQ_FLAGS);
|
||||
struct pios_spi_dev * spi_dev;
|
||||
|
||||
if(spi_callback[0] != NULL) {
|
||||
spi_callback[0]();
|
||||
}
|
||||
}
|
||||
spi_dev = find_spi_dev_by_id (spi);
|
||||
PIOS_DEBUG_Assert(spi_dev);
|
||||
|
||||
PIOS_SPI1_DMA_IRQHANDLER_FUNC
|
||||
{
|
||||
DMA_ClearFlag(PIOS_SPI1_DMA_RX_IRQ_FLAGS);
|
||||
DMA_ClearFlag(spi_dev->cfg->dma.irq.flags);
|
||||
|
||||
if(spi_callback[1] != NULL) {
|
||||
spi_callback[1]();
|
||||
}
|
||||
if(spi_dev->callback != NULL) {
|
||||
spi_dev->callback();
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -28,20 +28,6 @@
|
||||
#define PIOS_SPI_H
|
||||
|
||||
/* Global types */
|
||||
typedef enum {
|
||||
PIOS_SPI_PIN_DRIVER_STRONG = 0,
|
||||
PIOS_SPI_PIN_DRIVER_STRONG_OD = 1,
|
||||
PIOS_SPI_PIN_DRIVER_WEAK = 2,
|
||||
PIOS_SPI_PIN_DRIVER_WEAK_OD = 3,
|
||||
} SPIPinDriverTypeDef;
|
||||
|
||||
typedef enum {
|
||||
PIOS_SPI_MODE_CLK0_PHASE0 = 0,
|
||||
PIOS_SPI_MODE_CLK0_PHASE1 = 1,
|
||||
PIOS_SPI_MODE_CLK1_PHASE0 = 2,
|
||||
PIOS_SPI_MODE_CLK1_PHASE1 = 3
|
||||
} SPIModeTypeDef;
|
||||
|
||||
typedef enum {
|
||||
PIOS_SPI_PRESCALER_2 = 0,
|
||||
PIOS_SPI_PRESCALER_4 = 1,
|
||||
@ -53,13 +39,12 @@ typedef enum {
|
||||
PIOS_SPI_PRESCALER_256 = 7
|
||||
} SPIPrescalerTypeDef;
|
||||
|
||||
|
||||
/* PUblic Functions */
|
||||
/* Public Functions */
|
||||
extern int32_t PIOS_SPI_Init(void);
|
||||
extern int32_t PIOS_SPI_IO_Init(uint8_t spi, SPIPinDriverTypeDef spi_pin_driver);
|
||||
extern int32_t PIOS_SPI_TransferModeInit(uint8_t spi, SPIModeTypeDef spi_mode, SPIPrescalerTypeDef spi_prescaler);
|
||||
extern int32_t PIOS_SPI_SetClockSpeed(uint8_t spi, SPIPrescalerTypeDef spi_prescaler);
|
||||
extern int32_t PIOS_SPI_RC_PinSet(uint8_t spi, uint8_t pin_value);
|
||||
extern int32_t PIOS_SPI_TransferByte(uint8_t spi, uint8_t b);
|
||||
extern int32_t PIOS_SPI_TransferBlock(uint8_t spi, uint8_t *send_buffer, uint8_t *receive_buffer, uint16_t len, void *callback);
|
||||
extern void PIOS_SPI_IRQ_Handler(uint8_t spi);
|
||||
|
||||
#endif /* PIOS_SSPI_H */
|
||||
#endif /* PIOS_SPI_H */
|
||||
|
54
flight/PiOS/inc/pios_spi_priv.h
Normal file
54
flight/PiOS/inc/pios_spi_priv.h
Normal file
@ -0,0 +1,54 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pios_spi_priv.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* Parts by Thorsten Klose (tk@midibox.org)
|
||||
* @brief SPI private definitions.
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef PIOS_SPI_PRIV_H
|
||||
#define PIOS_SPI_PRIV_H
|
||||
|
||||
#include <pios.h>
|
||||
#include <pios_stm32.h>
|
||||
|
||||
struct pios_spi_cfg {
|
||||
SPI_TypeDef * regs;
|
||||
SPI_InitTypeDef init;
|
||||
bool * master;
|
||||
struct stm32_dma dma;
|
||||
struct stm32_gpio ssel;
|
||||
struct stm32_gpio sclk;
|
||||
struct stm32_gpio miso;
|
||||
struct stm32_gpio mosi;
|
||||
};
|
||||
|
||||
struct pios_spi_dev {
|
||||
const struct pios_spi_cfg * const cfg;
|
||||
void (*callback)(void);
|
||||
uint8_t tx_dummy_byte;
|
||||
uint8_t rx_dummy_byte;
|
||||
};
|
||||
|
||||
extern struct pios_spi_dev pios_spi_devs[];
|
||||
extern uint8_t pios_spi_num_devices;
|
||||
|
||||
#endif /* PIOS_SPI_PRIV_H */
|
52
flight/PiOS/inc/pios_stm32.h
Normal file
52
flight/PiOS/inc/pios_stm32.h
Normal file
@ -0,0 +1,52 @@
|
||||
/**
|
||||
******************************************************************************
|
||||
*
|
||||
* @file pios_stm32.h
|
||||
* @author The OpenPilot Team, http://www.openpilot.org Copyright (C) 2010.
|
||||
* @brief Types that are specific to the STM32 peripherals
|
||||
* @see The GNU Public License (GPL) Version 3
|
||||
*
|
||||
*****************************************************************************/
|
||||
/*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful, but
|
||||
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
*/
|
||||
|
||||
#ifndef PIOS_STM32_H
|
||||
#define PIOS_STM32_H
|
||||
|
||||
struct stm32_irq {
|
||||
void (*handler)(void);
|
||||
uint32_t flags;
|
||||
NVIC_InitTypeDef init;
|
||||
};
|
||||
|
||||
struct stm32_dma_chan {
|
||||
DMA_Channel_TypeDef * channel;
|
||||
DMA_InitTypeDef init;
|
||||
};
|
||||
|
||||
struct stm32_dma {
|
||||
uint32_t ahb_clk;
|
||||
struct stm32_irq irq;
|
||||
struct stm32_dma_chan rx;
|
||||
struct stm32_dma_chan tx;
|
||||
};
|
||||
|
||||
struct stm32_gpio {
|
||||
GPIO_TypeDef * gpio;
|
||||
GPIO_InitTypeDef init;
|
||||
};
|
||||
|
||||
#endif /* PIOS_STM32_H */
|
@ -28,9 +28,8 @@
|
||||
#ifndef PIOS_H
|
||||
#define PIOS_H
|
||||
|
||||
/* PIOS Compile Time Configuration */
|
||||
/* PIOS Feature Selection */
|
||||
#include "pios_config.h"
|
||||
#include "pios_board.h"
|
||||
|
||||
#if defined(PIOS_INCLUDE_FREERTOS)
|
||||
/* FreeRTOS Includes */
|
||||
@ -62,6 +61,9 @@
|
||||
#include <msd.h>
|
||||
#endif
|
||||
|
||||
/* PIOS Board Specific Device Configuration */
|
||||
#include "pios_board.h"
|
||||
|
||||
/* PIOS Hardware Includes (STM32F10x) */
|
||||
#include <pios_sys.h>
|
||||
#include <pios_delay.h>
|
||||
@ -100,4 +102,6 @@
|
||||
#include <usb_lib.h>
|
||||
#endif
|
||||
|
||||
#define NELEMENTS(x) (sizeof(x) / sizeof(*(x)))
|
||||
|
||||
#endif /* PIOS_H */
|
||||
|
Loading…
Reference in New Issue
Block a user