diff --git a/conf/modules/gumstix_qr_code_spi_link.xml b/conf/modules/gumstix_qr_code_spi_link.xml new file mode 100644 index 0000000000..6219c94a66 --- /dev/null +++ b/conf/modules/gumstix_qr_code_spi_link.xml @@ -0,0 +1,19 @@ + + + + + QR code gumstix interface + +
+ +
+ + + + + + + + +
+ diff --git a/sw/airborne/arch/stm32/mcu_periph/spi_arch.c b/sw/airborne/arch/stm32/mcu_periph/spi_arch.c index bb5d82876c..f2b5cc79f4 100644 --- a/sw/airborne/arch/stm32/mcu_periph/spi_arch.c +++ b/sw/airborne/arch/stm32/mcu_periph/spi_arch.c @@ -1201,12 +1201,217 @@ void process_tx_dma_interrupt(struct spi_periph *periph) { /* * * SPI Slave code - * - * FIXME implement it + * Currently only for F1, SPI1 * */ #ifdef SPI_SLAVE -#warning SPI_SLAVE mode currently not implemented for STM32. +static void process_slave_rx_dma_interrupt(struct spi_periph* periph); + + +// SPI arch slave init +#if USE_SPI1_SLAVE +#warning "SPI1 slave: Untested code!" + +#ifndef STM32F1 +#error "SPI1 slave on STM32 only implemented for STM32F1" +#endif + +#if USE_SPI1 +#error "Using SPI1 as a slave and master at the same time is not possible." +#endif + +static struct spi_periph_dma spi1_dma; + +void spi1_slave_arch_init(void) { + // set dma options + spi1_dma.spidr = (uint32_t)&SPI1_DR; + spi1_dma.dma = DMA1; + spi1_dma.rx_chan = DMA_CHANNEL2; + spi1_dma.tx_chan = DMA_CHANNEL3; + spi1_dma.rx_nvic_irq = NVIC_DMA1_CHANNEL2_IRQ; + spi1_dma.tx_nvic_irq = NVIC_DMA1_CHANNEL3_IRQ; + spi1_dma.tx_dummy_buf = 0; + spi1_dma.tx_extra_dummy_dma = FALSE; + spi1_dma.rx_dummy_buf = 0; + spi1_dma.rx_extra_dummy_dma = FALSE; + + // set the default configuration + set_default_comm_config(&spi1_dma.comm); + spi1_dma.comm_sig = get_comm_signature(&spi1_dma.comm); + + // set init struct, indices and status + spi1.reg_addr = (void *)SPI1; + spi1.init_struct = &spi1_dma; + spi1.trans_insert_idx = 0; + spi1.trans_extract_idx = 0; + spi1.status = SPIIdle; + + // Enable SPI1 Periph and gpio clocks + rcc_peripheral_enable_clock(&RCC_APB2ENR, RCC_APB2ENR_SPI1EN); + + // Configure GPIOs: SCK, MISO and MOSI + // TODO configure lisa board files to use gpio_setup_pin_af function + gpio_set_mode(GPIO_BANK_SPI1_SCK, GPIO_MODE_INPUT, + GPIO_CNF_INPUT_FLOAT, + GPIO_SPI1_SCK | GPIO_SPI1_MOSI); + + gpio_set_mode(GPIO_BANK_SPI1_MISO, GPIO_MODE_OUTPUT_50_MHZ, + GPIO_CNF_OUTPUT_ALTFN_PUSHPULL, + GPIO_SPI1_MISO); + + gpio_set_mode(GPIO_BANK_SPI1_NSS, GPIO_MODE_INPUT, + GPIO_CNF_INPUT_FLOAT, + GPIO_SPI1_NSS); + + // reset SPI + spi_reset(SPI1); + + // Disable SPI peripheral + spi_disable(SPI1); + + // Force SPI mode over I2S. + SPI1_I2SCFGR = 0; + + // configure master SPI. + spi_init_master(SPI1, spi1_dma.comm.br, spi1_dma.comm.cpol, spi1_dma.comm.cpha, + spi1_dma.comm.dff, spi1_dma.comm.lsbfirst); + + spi_disable_software_slave_management(SPI1); + + spi_set_slave_mode(SPI1); + + // Enable SPI_1 DMA clock +#ifdef STM32F1 + rcc_peripheral_enable_clock(&RCC_AHBENR, RCC_AHBENR_DMA1EN); +#elif defined STM32F4 + rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_DMA2EN); +#endif + + // Enable SPI1 periph. + spi_enable(SPI1); + + spi_arch_int_enable(&spi1); +} + +/// receive transferred over DMA +void dma1_channel2_isr(void) +{ + if ((DMA1_ISR & DMA_ISR_TCIF2) != 0) { + // clear int pending bit + DMA1_IFCR |= DMA_IFCR_CTCIF2; + } + process_slave_rx_dma_interrupt(&spi1); +} + + +#endif /* USE_SPI1_SLAVE */ + + +static void spi_slave_set_config(struct spi_periph* periph, struct spi_transaction* trans) +{ + struct spi_periph_dma *dma; + + dma = periph->init_struct; + + set_comm_from_transaction(&(dma->comm), trans); + + /* remember the new conf signature */ + //dma->comm_sig = sig; + + /* apply the new configuration */ + spi_disable((uint32_t)periph->reg_addr); + spi_init_master((uint32_t)periph->reg_addr, dma->comm.br, dma->comm.cpol, + dma->comm.cpha, dma->comm.dff, dma->comm.lsbfirst); + spi_disable_software_slave_management((uint32_t)periph->reg_addr); + spi_set_slave_mode((uint32_t)periph->reg_addr); + spi_enable((uint32_t)periph->reg_addr); +} + + + +//static void spi_start_slave_dma_transaction(struct spi_periph* periph, struct spi_transaction* trans) +bool_t spi_slave_register(struct spi_periph* periph, struct spi_transaction* trans) +{ + spi_slave_set_config(periph, trans); + + struct spi_periph_dma *dma; + uint8_t sig = 0x00; + + /* Store local copy to notify of the results */ + trans->status = SPITransRunning; + periph->status = SPIRunning; + + periph->trans_insert_idx = 0; + periph->trans[periph->trans_insert_idx] = trans; + + dma = periph->init_struct; + + /* + * Receive DMA channel configuration ---------------------------------------- + */ + spi_configure_dma(dma->dma, dma->rx_chan, (uint32_t)dma->spidr, + (uint32_t)trans->input_buf, trans->input_length, trans->dss, TRUE); + + dma_set_read_from_peripheral(dma->dma, dma->rx_chan); + dma_set_priority(dma->dma, dma->rx_chan, DMA_CCR_PL_VERY_HIGH); + + + /* + * Transmit DMA channel configuration --------------------------------------- + */ + spi_configure_dma(dma->dma, dma->tx_chan, (uint32_t)dma->spidr, + (uint32_t)trans->output_buf, trans->output_length, trans->dss, TRUE); + + dma_set_read_from_memory(dma->dma, dma->tx_chan); + dma_set_priority(dma->dma, dma->tx_chan, DMA_CCR_PL_MEDIUM); + + /* Enable DMA transfer complete interrupts. */ + dma_enable_transfer_complete_interrupt(dma->dma, dma->rx_chan); + + /* Enable DMA channels */ + dma_enable_channel(dma->dma, dma->rx_chan); + dma_enable_channel(dma->dma, dma->tx_chan); + + /* Enable SPI transfers via DMA */ + spi_enable_rx_dma((uint32_t)periph->reg_addr); + spi_enable_tx_dma((uint32_t)periph->reg_addr); + + return TRUE; +} + +void process_slave_rx_dma_interrupt(struct spi_periph *periph) { + struct spi_periph_dma *dma = periph->init_struct; + struct spi_transaction *trans = periph->trans[periph->trans_extract_idx]; + + /* Disable DMA Channel */ + dma_disable_transfer_complete_interrupt(dma->dma, dma->rx_chan); + + /* Disable SPI Rx request */ + spi_disable_rx_dma((uint32_t)periph->reg_addr); + + /* Disable DMA rx channel */ + dma_disable_channel(dma->dma, dma->rx_chan); + + /* Run the callback */ + trans->status = SPITransSuccess; + //return; + if (trans->after_cb != 0) { + trans->after_cb(trans); + } + + /*dma_enable_transfer_complete_interrupt(dma->dma, dma->rx_chan); + dma_enable_channel(dma->dma, dma->rx_chan); + spi_enable_rx_dma((uint32_t)periph->reg_addr);*/ +} + + +// Slave Select / NSS pin GPIO config + + +// DMA config? + + +// SPI transaction handling #endif /* SPI_SLAVE */ diff --git a/sw/airborne/modules/gumstix_interface/qr_code_spi_link.c b/sw/airborne/modules/gumstix_interface/qr_code_spi_link.c new file mode 100644 index 0000000000..c0a1a92526 --- /dev/null +++ b/sw/airborne/modules/gumstix_interface/qr_code_spi_link.c @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2005-2013 The Paparazzi Team + * + * This file is part of paparazzi. + * + * paparazzi 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 2, or (at your option) + * any later version. + * + * paparazzi 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 paparazzi; see the file COPYING. If not, write to + * the Free Software Foundation, 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#include "qr_code_spi_link.h" + +#include "subsystems/imu.h" +#include "mcu_periph/spi.h" + +#include "mcu_periph/uart.h" +#include "messages.h" +#include "subsystems/datalink/downlink.h" + +//struct qr_code_spi_link_data qr_code_spi_link_data; +struct spi_transaction qr_code_spi_link_transaction; + +static volatile bool_t qr_code_spi_data_available = FALSE; + +uint8_t testDataOut[3] = {1,2,3}; +uint8_t testDataIn[3] = {9,9,9}; + +static void qr_code_spi_link_trans_cb( struct spi_transaction *trans ); + +void qr_code_spi_link_init(void) { + qr_code_spi_link_transaction.cpol = SPICpolIdleHigh; + qr_code_spi_link_transaction.cpha = SPICphaEdge2; + qr_code_spi_link_transaction.dss = SPIDss8bit; + qr_code_spi_link_transaction.bitorder = SPIMSBFirst; + qr_code_spi_link_transaction.output_length = 3; + qr_code_spi_link_transaction.output_buf = testDataOut; + qr_code_spi_link_transaction.input_length = 3; + qr_code_spi_link_transaction.input_buf = testDataIn; + qr_code_spi_link_transaction.after_cb = qr_code_spi_link_trans_cb; + //spi_slave_set_config(&spi1, &qr_code_spi_link_transaction); + spi_slave_register(&spi1, &qr_code_spi_link_transaction); +} + + +void qr_code_spi_link_periodic(void) { + if (qr_code_spi_data_available) { + qr_code_spi_data_available = FALSE; + uint16_t x,y; + memcpy(&x,qr_code_spi_link_transaction.input_buf,2); + memcpy(&y,qr_code_spi_link_transaction.input_buf+2,2); + DOWNLINK_SEND_VISUALTARGET(DefaultChannel, DefaultDevice, &x, &y); + spi_slave_register(&spi1, &qr_code_spi_link_transaction); + } +} + +static void qr_code_spi_link_trans_cb( struct spi_transaction *trans __attribute__ ((unused)) ) { + qr_code_spi_data_available = TRUE; +} + + diff --git a/sw/airborne/modules/gumstix_interface/qr_code_spi_link.h b/sw/airborne/modules/gumstix_interface/qr_code_spi_link.h new file mode 100644 index 0000000000..06aa237943 --- /dev/null +++ b/sw/airborne/modules/gumstix_interface/qr_code_spi_link.h @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2005-2013 The Paparazzi Team + * + * This file is part of paparazzi. + * + * paparazzi 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 2, or (at your option) + * any later version. + * + * paparazzi 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 paparazzi; see the file COPYING. If not, write to + * the Free Software Foundation, 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#ifndef QR_CODE_SPI_LINK_H_ +#define QR_CODE_SPI_LINK_H_ + +#include "std.h" + +extern void qr_code_spi_link_init(void); +extern void qr_code_spi_link_periodic(void); + +#endif /* QR_CODE_SPI_LINK_H_ */