mirror of
https://github.com/paparazzi/paparazzi.git
synced 2026-05-30 03:27:33 +08:00
picked changes from spi_rewrite
* up to 30c07a6ba53e45453ed766c6ffefd6cd0d606493
This commit is contained in:
@@ -144,7 +144,7 @@ ap.CFLAGS += -DUSE_I2C2
|
||||
else ifeq ($(BOARD), navgo)
|
||||
include $(CFG_ROTORCRAFT)/spi.makefile
|
||||
ap.CFLAGS += -DUSE_SPI_SLAVE0
|
||||
ap.CFLAGS += -DSPI_NO_UNSELECT_SLAVE
|
||||
ap.CFLAGS += -DUSE_SPI1
|
||||
ap.CFLAGS += -DSPI_MASTER
|
||||
ap.srcs += peripherals/mcp355x.c
|
||||
endif
|
||||
|
||||
@@ -207,27 +207,59 @@
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// Serial Peripheral Interface 1 (SPI1)
|
||||
#define SPI1 ((spiRegs_t *)0xE0030000)
|
||||
#define SPI1 ((sspRegs_t *)0xE0068000)
|
||||
|
||||
// SPI1 Registers
|
||||
#define S1SPCR SPI1->cr /* Control Register */
|
||||
#define S1SPSR SPI1->sr /* Status Register */
|
||||
#define S1SPDR SPI1->dr /* Data Register */
|
||||
#define S1SPCCR SPI1->ccr /* Clock Counter Register */
|
||||
#define S1SPINT SPI1->flag /* Interrupt Flag Register */
|
||||
//#define S1SPCR SPI1->cr /* Control Register */
|
||||
//#define S1SPSR SPI1->sr /* Status Register */
|
||||
//#define S1SPDR SPI1->dr /* Data Register */
|
||||
//#define S1SPCCR SPI1->ccr /* Clock Counter Register */
|
||||
//#define S1SPINT SPI1->flag /* Interrupt Flag Register */
|
||||
|
||||
/* S1SPINT bits definition */
|
||||
#define SPI1IF 0
|
||||
|
||||
#define SSPCR0 (*(REG16*) 0xE0068000) /* Control Register 0 */
|
||||
#define SSPCR1 (*(REG_8*) 0xE0068004) /* Control Register 1 */
|
||||
#define SSPDR (*(REG16*) 0xE0068008) /* Data register */
|
||||
#define SSPSR (*(REG_8*) 0xE006800C) /* Status register */
|
||||
#define SSPCPSR (*(REG_8*) 0xE0068010) /* Clock prescale register */
|
||||
#define SSPIMSC (*(REG_8*) 0xE0068014) /* Interrupt mask register */
|
||||
#define SSPRIS (*(REG_8*) 0xE0068018) /* Raw interrupt status register */
|
||||
#define SSPMIS (*(REG_8*) 0xE006801C) /* Masked interrupt status register */
|
||||
#define SSPICR (*(REG_8*) 0xE0068020) /* Interrupt clear register */
|
||||
#define SSPCR0 SPI1->cr0 /* Control Register 0 */
|
||||
#define SSPCR1 SPI1->cr1 /* Control Register 1 */
|
||||
#define SSPDR SPI1->dr /* Data register */
|
||||
#define SSPSR SPI1->sr /* Status register */
|
||||
#define SSPCPSR SPI1->cpsr /* Clock prescale register */
|
||||
#define SSPIMSC SPI1->imsc /* Interrupt mask register */
|
||||
#define SSPRIS SPI1->ris /* Raw interrupt status register */
|
||||
#define SSPMIS SPI1->mis /* Masked interrupt status register */
|
||||
#define SSPICR SPI1->icr /* Interrupt clear register */
|
||||
|
||||
//#define SSPCR0 (*(REG16*) 0xE0068000) /* Control Register 0 */
|
||||
//#define SSPCR1 (*(REG_8*) 0xE0068004) /* Control Register 1 */
|
||||
//#define SSPDR (*(REG16*) 0xE0068008) /* Data register */
|
||||
//#define SSPSR (*(REG_8*) 0xE006800C) /* Status register */
|
||||
//#define SSPCPSR (*(REG_8*) 0xE0068010) /* Clock prescale register */
|
||||
//#define SSPIMSC (*(REG_8*) 0xE0068014) /* Interrupt mask register */
|
||||
//#define SSPRIS (*(REG_8*) 0xE0068018) /* Raw interrupt status register */
|
||||
//#define SSPMIS (*(REG_8*) 0xE006801C) /* Masked interrupt status register */
|
||||
//#define SSPICR (*(REG_8*) 0xE0068020) /* Interrupt clear register */
|
||||
|
||||
/* SSPCR0 bits definition */
|
||||
#define DSS 0
|
||||
#define FRF 4
|
||||
#define CPOL 6
|
||||
#define CPHA 7
|
||||
#define SCR 8
|
||||
|
||||
/* SSPDSS values definition */
|
||||
#define DSS_VAL4 0x3
|
||||
#define DSS_VAL5 0x4
|
||||
#define DSS_VAL6 0x5
|
||||
#define DSS_VAL7 0x6
|
||||
#define DSS_VAL8 0x7
|
||||
#define DSS_VAL9 0x8
|
||||
#define DSS_VAL10 0x9
|
||||
#define DSS_VAL11 0xA
|
||||
#define DSS_VAL12 0xB
|
||||
#define DSS_VAL13 0XC
|
||||
#define DSS_VAL14 0xD
|
||||
#define DSS_VAL15 0xE
|
||||
#define DSS_VAL16 0xF
|
||||
|
||||
/* SSPCR1 bits definition */
|
||||
#define LBM 0
|
||||
|
||||
@@ -35,4 +35,27 @@ typedef struct
|
||||
REG_8 _pad7[3];
|
||||
} spiRegs_t;
|
||||
|
||||
// Serial Serial Port Registers (SSP/SPI)
|
||||
typedef struct
|
||||
{
|
||||
REG_8 cr0; // Control Register 0
|
||||
REG_8 _pad0[3];
|
||||
REG_8 cr1; // Control Register 1
|
||||
REG_8 _pad1[3];
|
||||
REG_8 dr; // Data Register
|
||||
REG_8 _pad2[3];
|
||||
REG_8 sr; // Status Register
|
||||
REG_8 _pad3[3];
|
||||
REG_8 cpsr; // Clock Prescale Register
|
||||
REG_8 _pad4[3];
|
||||
REG_8 imsc; // Interrupt Mask Set and Clear Register
|
||||
REG_8 _pad5[3];
|
||||
REG_8 ris; // Raw Interrupt Status Register
|
||||
REG_8 _pad6[3];
|
||||
REG_8 mis; // Masked Interrupt Status Register
|
||||
REG_8 _pad7[3];
|
||||
REG_8 icr; // Interrupt Clear Register
|
||||
REG_8 _pad8[3];
|
||||
} sspRegs_t;
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -32,89 +32,19 @@
|
||||
#include "LPC21xx.h"
|
||||
#include BOARD_CONFIG
|
||||
|
||||
extern volatile uint8_t spi_tx_idx;
|
||||
extern volatile uint8_t spi_rx_idx;
|
||||
|
||||
#define SpiInitBuf() { \
|
||||
spi_rx_idx = 0; \
|
||||
spi_tx_idx = 0; \
|
||||
spi_message_received = FALSE; \
|
||||
SpiTransmit(); /* fill fifo */ \
|
||||
}
|
||||
|
||||
#define SpiTransmit() { \
|
||||
while (spi_tx_idx < spi_buffer_length \
|
||||
&& bit_is_set(SSPSR, TNF)) { \
|
||||
SpiSend(spi_buffer_output[spi_tx_idx]); \
|
||||
spi_tx_idx++; \
|
||||
} \
|
||||
if (spi_tx_idx == spi_buffer_length) \
|
||||
SpiDisableTxi(); \
|
||||
}
|
||||
// SSP is on SPI1 on lpc
|
||||
#if defined USE_SSP & !USE_SPI1
|
||||
#define USE_SP11 1
|
||||
// TODO other defines ?
|
||||
#endif
|
||||
|
||||
#define SpiReceive() { \
|
||||
while (bit_is_set(SSPSR, RNE)) { \
|
||||
if (spi_rx_idx < spi_buffer_length) { \
|
||||
SpiRead(spi_buffer_input[spi_rx_idx]) \
|
||||
spi_rx_idx++; \
|
||||
} \
|
||||
else { \
|
||||
uint8_t foo; \
|
||||
SpiRead(foo); \
|
||||
} \
|
||||
} \
|
||||
}
|
||||
|
||||
#define SpiEnable() { \
|
||||
SetBit(SSPCR1, SSE); \
|
||||
}
|
||||
|
||||
#define SpiDisable() { \
|
||||
ClearBit(SSPCR1, SSE); \
|
||||
}
|
||||
|
||||
#define SpiEnableRti() { \
|
||||
SetBit(SSPIMSC, RTIM); \
|
||||
}
|
||||
|
||||
#define SpiDisableRti() { \
|
||||
ClearBit(SSPIMSC, RTIM); \
|
||||
}
|
||||
|
||||
#define SpiClearRti() { \
|
||||
SetBit(SSPICR, RTIC); \
|
||||
}
|
||||
|
||||
#define SpiEnableTxi() { \
|
||||
SetBit(SSPIMSC, TXIM); \
|
||||
}
|
||||
|
||||
#define SpiDisableTxi() { \
|
||||
ClearBit(SSPIMSC, TXIM); \
|
||||
}
|
||||
|
||||
#define SpiEnableRxi() { \
|
||||
SetBit(SSPIMSC, RXIM); \
|
||||
}
|
||||
|
||||
#define SpiDisableRxi() { \
|
||||
ClearBit(SSPIMSC, RXIM); \
|
||||
}
|
||||
|
||||
#define SpiSend(a) { \
|
||||
SSPDR = a; \
|
||||
}
|
||||
|
||||
#define SpiRead(a) { \
|
||||
a = SSPDR; \
|
||||
}
|
||||
|
||||
#ifdef SPI_SLAVE
|
||||
#define SpiStart() { \
|
||||
SpiEnable(); \
|
||||
SpiInitBuf(); \
|
||||
SpiEnableTxi(); /* enable tx fifo half empty interrupt */ \
|
||||
}
|
||||
|
||||
extern volatile uint8_t spi_tx_idx;
|
||||
extern volatile uint8_t spi_rx_idx;
|
||||
|
||||
#endif /* SPI_SLAVE */
|
||||
|
||||
@@ -123,73 +53,7 @@ extern volatile uint8_t spi_rx_idx;
|
||||
#ifdef SPI_MASTER
|
||||
|
||||
|
||||
/* !!!!!!!!!!!!! Code for one single slave at a time !!!!!!!!!!!!!!!!! */
|
||||
#if defined SPI_SELECT_SLAVE1_PIN && defined SPI_SELECT_SLAVE0_PIN
|
||||
#error "SPI: one single slave, please"
|
||||
#endif
|
||||
|
||||
|
||||
#define SpiStart() { \
|
||||
SpiEnable(); \
|
||||
SpiInitBuf(); \
|
||||
SpiEnableTxi(); /* enable tx fifo half empty interrupt */ \
|
||||
}
|
||||
|
||||
/*
|
||||
* Slave0 select : P0.20 PINSEL1 00 << 8
|
||||
* Slave1 select : P1.20
|
||||
*
|
||||
*/
|
||||
|
||||
#define SPI_SELECT_SLAVE_IO__(port, reg) IO ## port ## reg
|
||||
#define SPI_SELECT_SLAVE_IO_(port, reg) SPI_SELECT_SLAVE_IO__(port, reg)
|
||||
|
||||
#define SPI_SELECT_SLAVE0_IODIR SPI_SELECT_SLAVE_IO_(SPI_SELECT_SLAVE0_PORT, DIR)
|
||||
#define SPI_SELECT_SLAVE0_IOCLR SPI_SELECT_SLAVE_IO_(SPI_SELECT_SLAVE0_PORT, CLR)
|
||||
#define SPI_SELECT_SLAVE0_IOSET SPI_SELECT_SLAVE_IO_(SPI_SELECT_SLAVE0_PORT, SET)
|
||||
|
||||
#define SPI_SELECT_SLAVE1_IODIR SPI_SELECT_SLAVE_IO_(SPI_SELECT_SLAVE1_PORT, DIR)
|
||||
#define SPI_SELECT_SLAVE1_IOCLR SPI_SELECT_SLAVE_IO_(SPI_SELECT_SLAVE1_PORT, CLR)
|
||||
#define SPI_SELECT_SLAVE1_IOSET SPI_SELECT_SLAVE_IO_(SPI_SELECT_SLAVE1_PORT, SET)
|
||||
|
||||
|
||||
#define SpiSelectSlave0() { \
|
||||
spi_cur_slave = SPI_SLAVE0; \
|
||||
SetBit(SPI_SELECT_SLAVE0_IOCLR, SPI_SELECT_SLAVE0_PIN); \
|
||||
}
|
||||
|
||||
#define SpiUnselectSlave0() { \
|
||||
spi_cur_slave = SPI_NONE; \
|
||||
SetBit(SPI_SELECT_SLAVE0_IOSET, SPI_SELECT_SLAVE0_PIN); \
|
||||
}
|
||||
|
||||
|
||||
#define SpiSelectSlave1() { \
|
||||
spi_cur_slave = SPI_SLAVE1; \
|
||||
SetBit(SPI_SELECT_SLAVE1_IOCLR, SPI_SELECT_SLAVE1_PIN); \
|
||||
}
|
||||
|
||||
#define SpiUnselectSlave1() { \
|
||||
spi_cur_slave = SPI_NONE; \
|
||||
SetBit(SPI_SELECT_SLAVE1_IOSET, SPI_SELECT_SLAVE1_PIN); \
|
||||
}
|
||||
|
||||
#ifdef SPI_SELECT_SLAVE0_PIN
|
||||
#define SpiUnselectCurrentSlave() SpiUnselectSlave0()
|
||||
#endif
|
||||
|
||||
#ifdef SPI_SELECT_SLAVE1_PIN
|
||||
#define SpiUnselectCurrentSlave() SpiUnselectSlave1()
|
||||
#endif
|
||||
|
||||
#endif /* SPI_MASTER */
|
||||
|
||||
|
||||
#define SpiSetCPOL() (SSPCR0 |= _BV(6))
|
||||
#define SpiClrCPOL() (SSPCR0 &= ~(_BV(6)))
|
||||
|
||||
#define SpiSetCPHA() (SSPCR0 |= _BV(7))
|
||||
#define SpiClrCPHA() (SSPCR0 &= ~(_BV(7)))
|
||||
|
||||
|
||||
#endif /* SPI_ARCH_H */
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
#include "subsystems/imu.h"
|
||||
|
||||
#include <libopencm3/stm32/nvic.h>
|
||||
#include <libopencm3/stm32/f1/gpio.h>
|
||||
@@ -9,9 +8,62 @@
|
||||
|
||||
#include "mcu_periph/spi.h"
|
||||
|
||||
struct spi_transaction* slave0;
|
||||
|
||||
// SPI2 Slave Selection
|
||||
#define Spi2Slave0Unselect() GPIO_BSRR(GPIOB) = GPIO12
|
||||
#define Spi2Slave0Select() GPIO_BRR(GPIOB) = GPIO12
|
||||
|
||||
#define SPI2_SLAVE0_PORT GPIOB
|
||||
#define SPI2_SLAVE0_PIN GPIO12
|
||||
|
||||
#define SPI2_SLAVE1_PORT GPIOB
|
||||
#define SPI2_SLAVE1_PIN GPIO5
|
||||
|
||||
#define SPI2_SLAVE2_PORT GPIOB
|
||||
#define SPI2_SLAVE2_PIN GPIO3
|
||||
|
||||
static inline void Spi2SlaveUnselect(uint8_t slave)
|
||||
{
|
||||
switch(slave) {
|
||||
case 0:
|
||||
GPIO_BSRR(SPI2_SLAVE0_PORT) = SPI2_SLAVE0_PIN;
|
||||
break;
|
||||
#if USE_SPI2_SLAVE1
|
||||
case 1:
|
||||
GPIO_BSRR(SPI2_SLAVE1_PORT) = SPI2_SLAVE1_PIN;
|
||||
break;
|
||||
#endif //USE_SPI2_SLAVE1
|
||||
#if USE_SPI2_SLAVE2
|
||||
case 2:
|
||||
GPIO_BSRR(SPI2_SLAVE2_PORT) = SPI2_SLAVE2_PIN;
|
||||
break;
|
||||
#endif //USE_SPI2_SLAVE2
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static inline void Spi2SlaveSelect(uint8_t slave)
|
||||
{
|
||||
switch(slave) {
|
||||
case 0:
|
||||
GPIO_BRR(SPI2_SLAVE0_PORT) = SPI2_SLAVE0_PIN;
|
||||
break;
|
||||
#if USE_SPI2_SLAVE1
|
||||
case 1:
|
||||
GPIO_BRR(SPI2_SLAVE1_PORT) = SPI2_SLAVE1_PIN;
|
||||
break;
|
||||
#endif //USE_SPI2_SLAVE1
|
||||
#if USE_SPI2_SLAVE2
|
||||
case 2:
|
||||
GPIO_BRR(SPI2_SLAVE2_PORT) = SPI2_SLAVE2_PIN;
|
||||
break;
|
||||
#endif //USE_SPI2_SLAVE2
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// spi dma end of rx handler
|
||||
// XXX: should be provided by libopencm3?
|
||||
@@ -72,41 +124,40 @@ void spi_init(void) {
|
||||
|
||||
// SLAVE 0
|
||||
// set accel slave select as output and assert it ( on PB12)
|
||||
Spi2Slave0Unselect();
|
||||
Spi2SlaveUnselect(0);
|
||||
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPBEN);
|
||||
gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ,
|
||||
GPIO_CNF_OUTPUT_PUSHPULL, GPIO12);
|
||||
GPIO_CNF_OUTPUT_PUSHPULL, SPI2_SLAVE0_PIN);
|
||||
|
||||
// SLAVE 1
|
||||
Spi2SlaveUnselect(1);
|
||||
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPBEN);
|
||||
gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ,
|
||||
GPIO_CNF_OUTPUT_PUSHPULL, SPI2_SLAVE1_PIN);
|
||||
|
||||
// SLAVE 2
|
||||
Spi2SlaveUnselect(1);
|
||||
rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_IOPBEN);
|
||||
gpio_set_mode(GPIOB, GPIO_MODE_OUTPUT_50_MHZ,
|
||||
GPIO_CNF_OUTPUT_PUSHPULL, SPI2_SLAVE2_PIN);
|
||||
//GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE); //Slave2 is on JTDO pin, so disable JTAG DP
|
||||
|
||||
|
||||
spi2.trans_insert_idx = 0;
|
||||
spi2.trans_extract_idx = 0;
|
||||
spi2.status = SPIIdle;
|
||||
|
||||
spi_arch_int_enable();
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
void adxl345_write_to_reg(uint8_t addr, uint8_t val) {
|
||||
|
||||
Adxl345Select();
|
||||
SPI_I2S_SendData(SPI2, addr);
|
||||
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);
|
||||
SPI_I2S_SendData(SPI2, val);
|
||||
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);
|
||||
while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_BSY) == SET);
|
||||
Adxl345Unselect();
|
||||
}
|
||||
|
||||
void spi_clear_rx_buf(void) {
|
||||
uint8_t __attribute__ ((unused)) ret = SPI_I2S_ReceiveData(SPI2);
|
||||
}
|
||||
*/
|
||||
|
||||
struct spi_transaction* slave0;
|
||||
|
||||
void spi_rw(struct spi_transaction * _trans)
|
||||
{
|
||||
// Store local copy to notify of the results
|
||||
slave0 = _trans;
|
||||
slave0->status = SPITransRunning;
|
||||
|
||||
Spi2Slave0Select();
|
||||
spi2.status = SPIRunning;
|
||||
Spi2SlaveSelect(slave0->slave_idx);
|
||||
|
||||
|
||||
// SPI2_Rx_DMA_Channel configuration ------------------------------------
|
||||
@@ -151,11 +202,37 @@ void spi_rw(struct spi_transaction * _trans)
|
||||
|
||||
}
|
||||
|
||||
bool_t spi_submit(struct spi_periph* p, struct spi_transaction* t)
|
||||
{
|
||||
uint8_t idx;
|
||||
idx = p->trans_insert_idx + 1;
|
||||
if (idx >= SPI_TRANSACTION_QUEUE_LEN) idx = 0;
|
||||
if (idx == p->trans_extract_idx) {
|
||||
t->status = SPITransFailed;
|
||||
return FALSE; /* queue full */
|
||||
}
|
||||
t->status = SPITransPending;
|
||||
// FIXME: still needed?
|
||||
//*(t->ready) = 0;
|
||||
//Disable interrupts to avoid race conflict with end of DMA transfer interrupt
|
||||
__disable_irq();
|
||||
p->trans[p->trans_insert_idx] = t;
|
||||
p->trans_insert_idx = idx;
|
||||
|
||||
/* if peripheral is idle, start the transaction */
|
||||
if (p->status == SPIIdle) {
|
||||
spi_rw(p->trans[p->trans_extract_idx]);
|
||||
}
|
||||
__enable_irq();
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
// Accel end of DMA transferred
|
||||
void dma1_channel4_isr(void)
|
||||
{
|
||||
|
||||
Spi2Slave0Unselect();
|
||||
Spi2SlaveUnselect(spi2.trans[spi2.trans_extract_idx]->slave_idx);
|
||||
|
||||
if ((DMA1_ISR & DMA_ISR_TCIF4) != 0) {
|
||||
// clear int pending bit
|
||||
@@ -164,7 +241,6 @@ void dma1_channel4_isr(void)
|
||||
// mark as available
|
||||
spi_message_received = TRUE;
|
||||
}
|
||||
|
||||
// disable DMA Channel
|
||||
dma_disable_transfer_complete_interrupt(DMA1, DMA_CHANNEL4);
|
||||
|
||||
@@ -178,7 +254,15 @@ void dma1_channel4_isr(void)
|
||||
|
||||
slave0->status = SPITransSuccess;
|
||||
*(slave0->ready) = 1;
|
||||
spi2.trans_extract_idx++;
|
||||
|
||||
// Check if there is another pending SPI transaction
|
||||
if (spi2.trans_extract_idx >= SPI_TRANSACTION_QUEUE_LEN)
|
||||
spi2.trans_extract_idx = 0;
|
||||
if (spi2.trans_extract_idx == spi2.trans_insert_idx)
|
||||
spi2.status = SPIIdle;
|
||||
else
|
||||
spi_rw(spi2.trans[spi2.trans_extract_idx]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -37,7 +37,6 @@ extern void spi_arch_int_disable(void);
|
||||
extern void spi_clear_rx_buf(void);
|
||||
void spi_rw(struct spi_transaction * _trans);
|
||||
|
||||
|
||||
/*
|
||||
|
||||
//////////
|
||||
|
||||
@@ -51,8 +51,8 @@ extern bool_t link_mcu_received;
|
||||
|
||||
extern void link_mcu_event_task( void );
|
||||
|
||||
#if defined MCU_SPI_LINK && ! defined USE_SPI
|
||||
#define USE_SPI
|
||||
#if defined MCU_SPI_LINK && !USE_SPI
|
||||
#define USE_SPI 1
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
+12
-3
@@ -46,7 +46,7 @@
|
||||
#ifdef USE_USB_SERIAL
|
||||
#include "mcu_periph/usb_serial.h"
|
||||
#endif
|
||||
#ifdef USE_SPI
|
||||
#if USE_SPI0 || USE_SPI1 || USE_SPI2
|
||||
#include "mcu_periph/spi.h"
|
||||
#endif
|
||||
#ifdef USE_DAC
|
||||
@@ -100,8 +100,17 @@ void mcu_init(void) {
|
||||
#ifdef USE_USB_SERIAL
|
||||
VCOM_init();
|
||||
#endif
|
||||
#ifdef USE_SPI
|
||||
spi_init();
|
||||
#if USE_SPI0
|
||||
spi0_init();
|
||||
#endif
|
||||
#if USE_SPI1
|
||||
spi1_init();
|
||||
#endif
|
||||
#if USE_SPI2
|
||||
spi2_init();
|
||||
#endif
|
||||
#if USE_SPI0 || USE_SPI1 || USE_SPI2
|
||||
spi_init_slaves();
|
||||
#endif
|
||||
#ifdef USE_DAC
|
||||
dac_init();
|
||||
|
||||
@@ -25,14 +25,54 @@
|
||||
#include "std.h"
|
||||
#include "mcu_periph/spi.h"
|
||||
|
||||
#ifdef SPI_MASTER
|
||||
|
||||
#if USE_SPI0
|
||||
|
||||
struct spi_periph spi0;
|
||||
|
||||
void spi0_init(void) {
|
||||
spi_init(&spi0);
|
||||
spi0_arch_init();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if USE_SPI1
|
||||
|
||||
struct spi_periph spi1;
|
||||
|
||||
void spi1_init(void) {
|
||||
spi_init(&spi1);
|
||||
spi1_arch_init();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if USE_SPI2
|
||||
|
||||
struct spi_periph spi2;
|
||||
|
||||
void spi2_init(void) {
|
||||
spi_init(&spi2);
|
||||
spi2_arch_init();
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void spi_init(struct spi_periph* p) {
|
||||
p->trans_insert_idx = 0;
|
||||
p->trans_extract_idx = 0;
|
||||
p->status = SPIIdle;
|
||||
}
|
||||
|
||||
#endif /* SPI_MASTER */
|
||||
|
||||
#ifdef SPI_SLAVE
|
||||
|
||||
uint8_t* spi_buffer_input;
|
||||
uint8_t* spi_buffer_output;
|
||||
uint8_t spi_buffer_length;
|
||||
volatile bool_t spi_message_received;
|
||||
|
||||
#ifdef SPI_MASTER
|
||||
|
||||
volatile uint8_t spi_cur_slave;
|
||||
uint8_t spi_nb_ovrn;
|
||||
|
||||
#endif /* SPI_MASTER */
|
||||
#endif
|
||||
|
||||
+170
-22
@@ -29,27 +29,188 @@
|
||||
#ifndef SPI_H
|
||||
#define SPI_H
|
||||
|
||||
#ifdef USE_SPI
|
||||
//#if USE_SPI
|
||||
|
||||
#include "std.h"
|
||||
|
||||
#include "mcu_periph/spi_arch.h"
|
||||
|
||||
// FIXME how to use this properly ?
|
||||
enum SPIMode {
|
||||
SPIMaster,
|
||||
SPISlave
|
||||
};
|
||||
|
||||
/** SPI slave selection behavior.
|
||||
* SelectUnselect: slave is selected before transaction and unselected after
|
||||
* Select: slave is selected before transaction but not unselected
|
||||
* Unselect: slave is not selected but unselected after transaction
|
||||
* NoSelect: slave is not selected nor unselected
|
||||
*
|
||||
* Default operation should be SelectUnselected, but some peripherals
|
||||
* might need some special control
|
||||
* Use non-default control only if you know what you're doing
|
||||
*/
|
||||
enum SPISlaveSelect {
|
||||
SPISelectUnselect,
|
||||
SPISelect,
|
||||
SPIUnselect,
|
||||
SPINoSelect
|
||||
};
|
||||
|
||||
/** SPI clock phase control.
|
||||
* control when data are sampled (rising or falling edge of clock)
|
||||
* depending of the clock polarity
|
||||
* Mode 0: data sampled on first clock edge
|
||||
* Mode 1: data sampled on second clock edge
|
||||
*/
|
||||
enum SPIClockPhase {
|
||||
SPICPHA_Mode0,
|
||||
SPICPHA_Mode1
|
||||
};
|
||||
|
||||
/** SPI clock polarity control.
|
||||
* Mode 0: clock idle low
|
||||
* Mode 1: clock idle high
|
||||
*/
|
||||
enum SPIClockPolarity {
|
||||
SPICPOL_Mode0,
|
||||
SPICPOL_Mode1
|
||||
};
|
||||
|
||||
/** SPI Data size transfer.
|
||||
*/
|
||||
enum SPIDataSizeSelect {
|
||||
DSS8bit,
|
||||
DSS16bit
|
||||
};
|
||||
|
||||
/** SPI transaction status.
|
||||
*/
|
||||
enum SPITransactionStatus {
|
||||
SPITransPending,
|
||||
SPITransRunning,
|
||||
SPITransSuccess,
|
||||
SPITransFailed
|
||||
SPITransFailed,
|
||||
SPITransDone
|
||||
};
|
||||
|
||||
/** SPI peripheral status.
|
||||
*/
|
||||
enum SPIStatus {
|
||||
SPIIdle,
|
||||
SPIRunning
|
||||
};
|
||||
|
||||
#ifndef SPI_BUF_LEN
|
||||
#define SPI_BUF_LEN 32
|
||||
#endif
|
||||
|
||||
struct spi_transaction {
|
||||
volatile uint8_t* mosi_buf;
|
||||
volatile uint8_t* miso_buf;
|
||||
volatile uint8_t* ready;
|
||||
volatile uint8_t input_buf[SPI_BUF_LEN];
|
||||
volatile uint8_t output_buf[SPI_BUF_LEN];
|
||||
volatile uint8_t* ready; // FIXME what is the difference with status ?
|
||||
uint8_t length;
|
||||
uint8_t slave_idx;
|
||||
enum SPISlaveSelect select;
|
||||
enum SPIClockPolarity cpol;
|
||||
enum SPIClockPhase cpha;
|
||||
enum SPIDataSizeSelect dss; // Architecture dependant options (LPC21) ?
|
||||
volatile enum SPITransactionStatus status;
|
||||
};
|
||||
|
||||
#include "mcu_periph/spi_arch.h"
|
||||
#ifndef SPI_TRANSACTION_QUEUE_LEN
|
||||
#define SPI_TRANSACTION_QUEUE_LEN 8
|
||||
#endif
|
||||
|
||||
struct spi_periph {
|
||||
/* circular buffer holding transactions */
|
||||
struct spi_transaction* trans[SPI_TRANSACTION_QUEUE_LEN];
|
||||
uint8_t trans_insert_idx;
|
||||
uint8_t trans_extract_idx;
|
||||
/* internal state of the peripheral */
|
||||
volatile enum SPIStatus status;
|
||||
volatile uint8_t tx_idx_buf;
|
||||
volatile uint8_t rx_idx_buf;
|
||||
void* reg_addr;
|
||||
enum SPIMode mode;
|
||||
};
|
||||
|
||||
#ifdef SPI_MASTER
|
||||
|
||||
#define SPI_SLAVE0 0
|
||||
#define SPI_SLAVE1 1
|
||||
#define SPI_SLAVE2 2
|
||||
|
||||
//extern uint8_t spi_nb_ovrn; //TODO SPI error struct
|
||||
|
||||
#if USE_SPI0
|
||||
|
||||
extern struct spi_periph spi0;
|
||||
extern void spi0_init(void);
|
||||
|
||||
/** Architecture dependant SPI0 initialization.
|
||||
* Must be implemented by underlying architecture
|
||||
*/
|
||||
extern void spi0_arch_init(void);
|
||||
|
||||
#endif
|
||||
|
||||
#if USE_SPI1
|
||||
|
||||
extern struct spi_periph spi1;
|
||||
extern void spi1_init(void);
|
||||
|
||||
/** Architecture dependant SPI1 initialization.
|
||||
* Must be implemented by underlying architecture
|
||||
*/
|
||||
extern void spi1_arch_init(void);
|
||||
|
||||
#endif
|
||||
|
||||
#if USE_SPI2
|
||||
|
||||
extern struct spi_periph spi2;
|
||||
extern void spi2_init(void);
|
||||
|
||||
/** Architecture dependant SPI2 initialization.
|
||||
* Must be implemented by underlying architecture
|
||||
*/
|
||||
extern void spi2_arch_init(void);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
/** Initialize a spi peripheral.
|
||||
* @param p spi peripheral to be configured
|
||||
*/
|
||||
extern void spi_init(struct spi_periph* p);
|
||||
|
||||
/** Initialize all used slaves and uselect them.
|
||||
*/
|
||||
extern void spi_init_slaves(void);
|
||||
|
||||
/** Submit a spi transaction.
|
||||
* Must be implemented by the underlying architecture
|
||||
* @param p spi peripheral to be used
|
||||
* @param t spi transaction
|
||||
* @return return true if insertion to the transaction queue succed
|
||||
*/
|
||||
extern bool_t spi_submit(struct spi_periph* p, struct spi_transaction* t);
|
||||
|
||||
/** Select a slave.
|
||||
* @param slave slave id
|
||||
*/
|
||||
void spi_slave_select(uint8_t slave);
|
||||
|
||||
/** Unselect a slave.
|
||||
* @param slave slave id
|
||||
*/
|
||||
void spi_slave_unselect(uint8_t slave);
|
||||
|
||||
#endif /* SPI_MASTER */
|
||||
|
||||
#ifdef SPI_SLAVE
|
||||
|
||||
extern uint8_t* spi_buffer_input;
|
||||
extern uint8_t* spi_buffer_output;
|
||||
@@ -57,23 +218,10 @@ extern uint8_t spi_buffer_length;
|
||||
|
||||
extern volatile bool_t spi_message_received;
|
||||
|
||||
void spi_init(void);
|
||||
void spi_slave_init(void);
|
||||
|
||||
#ifdef SPI_MASTER
|
||||
#endif
|
||||
|
||||
#define SPI_NONE 0
|
||||
#define SPI_SLAVE0 1
|
||||
#define SPI_SLAVE1 2
|
||||
#define SPI_SLAVE2 3
|
||||
|
||||
extern volatile uint8_t spi_cur_slave;
|
||||
extern uint8_t spi_nb_ovrn;
|
||||
|
||||
#define SpiCheckAvailable() (spi_cur_slave == SPI_NONE)
|
||||
#define SpiOverRun() {spi_nb_ovrn++;}
|
||||
|
||||
#endif /* SPI_MASTER */
|
||||
|
||||
#endif /* USE_SPI */
|
||||
//#endif /* USE_SPI */
|
||||
|
||||
#endif /* SPI_H */
|
||||
|
||||
@@ -28,34 +28,40 @@
|
||||
|
||||
bool_t mcp355x_data_available;
|
||||
int32_t mcp355x_data;
|
||||
uint8_t mcp355x_spi_buf[4];
|
||||
|
||||
struct spi_transaction mcp355x_spi_trans;
|
||||
|
||||
void mcp355x_init(void) {
|
||||
mcp355x_data_available = FALSE;
|
||||
mcp355x_data = 0;
|
||||
|
||||
SpiClrCPOL();
|
||||
SpiClrCPHA();
|
||||
mcp355x_spi_trans.length = 4;
|
||||
mcp355x_spi_trans.slave_idx = SPI_SLAVE0;
|
||||
mcp355x_spi_trans.select = SPISelect;
|
||||
mcp355x_spi_trans.cpol = SPICPOL_Mode0;
|
||||
mcp355x_spi_trans.cpha = SPICPHA_Mode0;
|
||||
mcp355x_spi_trans.dss = DSS8bit;
|
||||
|
||||
}
|
||||
|
||||
void mcp355x_read(void) {
|
||||
spi_buffer_length = 4;
|
||||
spi_buffer_input = mcp355x_spi_buf;
|
||||
//SpiSelectSlave0();
|
||||
SpiStart();
|
||||
spi_submit(&spi1, &mcp355x_spi_trans);
|
||||
}
|
||||
|
||||
void mcp355x_event(void) {
|
||||
if (spi_message_received) {
|
||||
spi_message_received = FALSE;
|
||||
if ((mcp355x_spi_buf[0]>>4) == 0) {
|
||||
if (mcp355x_spi_trans.status == SPITransSuccess) {
|
||||
if ((mcp355x_spi_trans.input_buf[0]>>4) == 0) {
|
||||
mcp355x_data = (int32_t)(
|
||||
((uint32_t)mcp355x_spi_buf[0]<<17) |
|
||||
((uint32_t)mcp355x_spi_buf[1]<<9) |
|
||||
((uint32_t)mcp355x_spi_buf[2]<<1) |
|
||||
(mcp355x_spi_buf[3]>>7));
|
||||
((uint32_t)mcp355x_spi_trans.input_buf[0]<<17) |
|
||||
((uint32_t)mcp355x_spi_trans.input_buf[1]<<9) |
|
||||
((uint32_t)mcp355x_spi_trans.input_buf[2]<<1) |
|
||||
(mcp355x_spi_trans.input_buf[3]>>7));
|
||||
mcp355x_data_available = TRUE;
|
||||
}
|
||||
mcp355x_spi_trans.status = SPITransDone;
|
||||
}
|
||||
if (mcp355x_spi_trans.status == SPITransFailed) {
|
||||
mcp355x_spi_trans.status = SPITransDone;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user