Exemplo n.º 1
0
void spi1_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
  gpio_set_mode(GPIO_BANK_SPI1_SCK, GPIO_MODE_OUTPUT_50_MHZ,
                GPIO_CNF_OUTPUT_ALTFN_PUSHPULL,
                GPIO_SPI1_SCK | GPIO_SPI1_MOSI);

  gpio_set_mode(GPIO_BANK_SPI1_MISO, GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT,
                GPIO_SPI1_MISO);

  // 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);
  /*
   * Set NSS management to software.
   *
   * Note:
   * Setting nss high is very important, even if we are controlling the GPIO
   * ourselves this bit needs to be at least set to 1, otherwise the spi
   * peripheral will not send any data out.
   */
  spi_enable_software_slave_management(SPI1);
  spi_set_nss_high(SPI1);

  // Enable SPI_1 DMA clock
  rcc_peripheral_enable_clock(&RCC_AHBENR, RCC_AHBENR_DMA1EN);

  // Enable SPI1 periph.
  spi_enable(SPI1);

  spi_arch_int_enable(&spi1);
}
Exemplo n.º 2
0
int devspi_create(const struct spi_config *conf)
{
    struct dev_spi *spi = NULL;

    if (!conf)
        return -EINVAL;
    if (conf->base == 0)
        return -EINVAL;

    if ((conf->idx < 0) || (conf->idx > MAX_SPIS))
        return -EINVAL;

    spi = kalloc(sizeof(struct dev_spi));
    if (!spi)
        return -ENOMEM;

    /* Claim pins for SCK/MOSI/MISO */
    gpio_create(&mod_spi, &conf->pio_sck);
    gpio_create(&mod_spi, &conf->pio_mosi);
    gpio_create(&mod_spi, &conf->pio_miso);

    /* Erase spi content */
    memset(spi, 0, sizeof(struct dev_spi));

    /* Enable clocks */
    rcc_periph_clock_enable(conf->rcc);
    rcc_periph_clock_enable(conf->dma_rcc);

    /* Startup routine */
    //spi_disable(conf->base);

    /**********************************/
	/* reset SPI1 */
	spi_reset(conf->base);
	/* init SPI1 master */
	spi_init_master(conf->base,
					SPI_CR1_BAUDRATE_FPCLK_DIV_64,
					SPI_CR1_CPOL_CLK_TO_0_WHEN_IDLE,
					SPI_CR1_CPHA_CLK_TRANSITION_1,
					SPI_CR1_DFF_8BIT,
					SPI_CR1_MSBFIRST);
	/* enable SPI1 first */
	spi_enable(conf->base);
    /**********************************/

#if 0
    spi_set_master_mode(conf->base);
    spi_set_baudrate_prescaler(conf->base, SPI_CR1_BR_FPCLK_DIV_256); /* TODO: Calculate prescaler from baudrate */
    if(conf->polarity == 0) 
        spi_set_clock_polarity_0(conf->base);
    else                    
        spi_set_clock_polarity_1(conf->base);
    if(conf->phase == 0) spi_set_clock_phase_0(conf->base);
    else
        spi_set_clock_phase_1(conf->base);
    if(conf->rx_only == 0)      
        spi_set_full_duplex_mode(conf->base);
    else
        spi_set_receive_only_mode(conf->base);
    if(conf->bidir_mode == 0)      
        spi_set_unidirectional_mode(conf->base);
    else
        spi_set_bidirectional_mode(conf->base);
    if(conf->dff_16) 
        spi_set_dff_16bit(conf->base);
    else
        spi_set_dff_8bit(conf->base);
    if(conf->enable_software_slave_management) 
        spi_enable_software_slave_management(conf->base);
    else
        spi_disable_software_slave_management(conf->base);
    if(conf->send_msb_first) 
        spi_send_msb_first(conf->base);
    else
        spi_send_lsb_first(conf->base);
    spi_set_nss_high(conf->base);
#endif

    /* Set up device struct */
    spi->base = conf->base;
    spi->irq = conf->irq;
    //spi->tx_dma_config = &conf->tx_dma;
    //spi->rx_dma_config = &conf->rx_dma;
    spi->mutex = mutex_init();

    /* Store address in the DEV_SPI array. */
    DEV_SPI[conf->idx] = spi;

    /* Enable interrupts */
    //nvic_set_priority(conf->irq, 1);
    //nvic_enable_irq(conf->irq);
    return 0;
}
Exemplo n.º 3
0
/**
 * Start a new transaction with DMA.
 */
static void spi_start_dma_transaction(struct spi_periph* periph, struct spi_transaction* trans)
{
  struct spi_periph_dma *dma;
  uint8_t sig = 0x00;

  /* Store local copy to notify of the results */
  trans->status = SPITransRunning;
  periph->status = SPIRunning;

  dma = periph->init_struct;

  /*
   * Check if we need to reconfigure the spi peripheral for this transaction
   */
  sig = get_transaction_signature(trans);
  if (sig != dma->comm_sig) {
    /* A different config is required in this transaction... */
    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_enable_software_slave_management((uint32_t)periph->reg_addr);
    spi_set_nss_high((uint32_t)periph->reg_addr);
    spi_enable((uint32_t)periph->reg_addr);
  }

  /*
   * Select the slave after reconfiguration of the peripheral
   */
  if (trans->select == SPISelectUnselect || trans->select == SPISelect) {
    SpiSlaveSelect(trans->slave_idx);
  }

  /* Run the callback AFTER selecting the slave */
  if (trans->before_cb != 0) {
    trans->before_cb(trans);
  }

  /*
   * Receive DMA channel configuration ----------------------------------------
   *
   * We always run the receive DMA until the very end!
   * This is done so we can use the transfer complete interrupt
   * of the RX DMA to signal the end of the transaction.
   *
   * If we want to receive less than we transmit, a dummy buffer
   * for the rx DMA is used after for the remaining data.
   *
   * In the transmit only case (input_length == 0),
   * the dummy is used right from the start.
   */
  if (trans->input_length == 0) {
    /* run the dummy rx dma for the complete transaction length */
    spi_configure_dma(dma->dma, dma->rx_chan, (uint32_t)dma->spidr,
                      (uint32_t)&(dma->rx_dummy_buf), trans->output_length, trans->dss, FALSE);
  } else {
    /* run the real rx dma for input_length */
    spi_configure_dma(dma->dma, dma->rx_chan, (uint32_t)dma->spidr,
                      (uint32_t)trans->input_buf, trans->input_length, trans->dss, TRUE);
    /* use dummy rx dma for the rest */
    if (trans->output_length > trans->input_length) {
      /* Enable use of second dma transfer with dummy buffer (cleared in ISR) */
      dma->rx_extra_dummy_dma = 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 ---------------------------------------
   *
   * We always run the transmit DMA!
   * To receive data, the clock must run, so something has to be transmitted.
   * If needed, use a dummy DMA transmitting zeros for the remaining length.
   *
   * In the reveive only case (output_length == 0),
   * the dummy is used right from the start.
   */
  if (trans->output_length == 0) {
    spi_configure_dma(dma->dma, dma->tx_chan, (uint32_t)dma->spidr,
                      (uint32_t)&(dma->tx_dummy_buf), trans->input_length, trans->dss, FALSE);
  } else {
    spi_configure_dma(dma->dma, dma->tx_chan, (uint32_t)dma->spidr,
                      (uint32_t)trans->output_buf, trans->output_length, trans->dss, TRUE);
    if (trans->input_length > trans->output_length) {
      /* Enable use of second dma transfer with dummy buffer (cleared in ISR) */
      dma->tx_extra_dummy_dma = 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);
  dma_enable_transfer_complete_interrupt(dma->dma, dma->tx_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);
}
Exemplo n.º 4
0
void codecInit(void)
{
    memset(adcBuffer, 0xaa, sizeof(adcBuffer));

    // I2S2 alternate function mapping
    gpio_mode_setup(GPIOB, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO12 | GPIO13 | GPIO14 | GPIO15);
    gpio_set_af(GPIOB, GPIO_AF5, GPIO12 | GPIO13 | GPIO15);
    gpio_set_af(GPIOB, GPIO_AF6, GPIO14); // I2S2ext_SD (I2S receive)
    gpio_mode_setup(GPIOC, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO6);
    gpio_set_af(GPIOC, GPIO_AF5, GPIO6); // MCLK
    gpio_set_output_options(GPIOB, GPIO_OTYPE_PP, GPIO_OSPEED_25MHZ, GPIO12 | GPIO13 | GPIO15);
    gpio_set_output_options(GPIOC, GPIO_OTYPE_PP, GPIO_OSPEED_100MHZ, GPIO6);

    // Set up SPI1
    spi_reset(SPI1);

    spi_init_master(SPI1, SPI_CR1_BAUDRATE_FPCLK_DIV_256, SPI_CR1_CPOL_CLK_TO_1_WHEN_IDLE,
            SPI_CR1_CPHA_CLK_TRANSITION_2, SPI_CR1_DFF_16BIT, SPI_CR1_MSBFIRST);
    spi_set_nss_high(SPI1);
    spi_enable_software_slave_management(SPI1);
    spi_enable(SPI1);

    // SPI1 alternate function mapping, set CSB signal high output
    gpio_mode_setup(GPIOA, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO5 | GPIO7);
    gpio_set_af(GPIOA, GPIO_AF5, GPIO5 | GPIO7);
    gpio_set(GPIOA, GPIO4);
    gpio_mode_setup(GPIOA, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO4);

    codecConfig();

    // Set up I2S for 48kHz 16-bit stereo.
    // The input to the PLLI2S is 1MHz. Division factors are from
    // table 126 in the data sheet.
    //
    // This gives us 1.536MHz SCLK = 16 bits * 2 channels * 48000 Hz
    // and 12.288 MHz MCLK = 256 * 48000 Hz

    spi_reset(SPI2);

    RCC_PLLI2SCFGR = (3 << 28) | (258 << 6);
    RCC_CR |= RCC_CR_PLLI2SON;
    while (!(RCC_CR & RCC_CR_PLLI2SRDY));

    const unsigned i2sdiv = 3;
    SPI_I2SPR(SPI2) = SPI_I2SPR_MCKOE | SPI_I2SPR_ODD | i2sdiv;
    SPI_I2SCFGR(SPI2) |= SPI_I2SCFGR_I2SMOD | SPI_I2SCFGR_I2SE |
            (SPI_I2SCFGR_I2SCFG_MASTER_TRANSMIT << SPI_I2SCFGR_I2SCFG_LSB);
    SPI_I2SCFGR(I2S2_EXT_BASE) = SPI_I2SCFGR_I2SMOD | SPI_I2SCFGR_I2SE |
            (SPI_I2SCFGR_I2SCFG_SLAVE_RECEIVE << SPI_I2SCFGR_I2SCFG_LSB);

    // Configure the DMA engine to stream data to the DAC.
    dma_stream_reset(DMA1, DAC_DMA_STREAM);
    dma_set_peripheral_address(DMA1, DAC_DMA_STREAM, (intptr_t)&SPI_DR(SPI2));
    dma_set_memory_address(DMA1, DAC_DMA_STREAM, (intptr_t)dacBuffer[0]);
    dma_set_memory_address_1(DMA1, DAC_DMA_STREAM, (intptr_t)dacBuffer[1]);
    dma_set_number_of_data(DMA1, DAC_DMA_STREAM, BUFFER_SAMPLES);
    dma_channel_select(DMA1, DAC_DMA_STREAM, DAC_DMA_CHANNEL);
    dma_set_transfer_mode(DMA1, DAC_DMA_STREAM, DMA_SxCR_DIR_MEM_TO_PERIPHERAL);
    dma_set_memory_size(DMA1, DAC_DMA_STREAM, DMA_SxCR_MSIZE_16BIT);
    dma_set_peripheral_size(DMA1, DAC_DMA_STREAM, DMA_SxCR_PSIZE_16BIT);
    dma_enable_memory_increment_mode(DMA1, DAC_DMA_STREAM);
    dma_enable_double_buffer_mode(DMA1, DAC_DMA_STREAM);
    dma_enable_stream(DMA1, DAC_DMA_STREAM);

    // Configure the DMA engine to stream data from the ADC.
    dma_stream_reset(DMA1, ADC_DMA_STREAM);
    dma_set_peripheral_address(DMA1, ADC_DMA_STREAM, (intptr_t)&SPI_DR(I2S2_EXT_BASE));
    dma_set_memory_address(DMA1, ADC_DMA_STREAM, (intptr_t)adcBuffer[0]);
    dma_set_memory_address_1(DMA1, ADC_DMA_STREAM, (intptr_t)adcBuffer[1]);
    dma_set_number_of_data(DMA1, ADC_DMA_STREAM, BUFFER_SAMPLES);
    dma_channel_select(DMA1, ADC_DMA_STREAM, ADC_DMA_CHANNEL);
    dma_set_transfer_mode(DMA1, ADC_DMA_STREAM, DMA_SxCR_DIR_PERIPHERAL_TO_MEM);
    dma_set_memory_size(DMA1, ADC_DMA_STREAM, DMA_SxCR_MSIZE_16BIT);
    dma_set_peripheral_size(DMA1, ADC_DMA_STREAM, DMA_SxCR_PSIZE_16BIT);
    dma_enable_memory_increment_mode(DMA1, ADC_DMA_STREAM);
    dma_enable_double_buffer_mode(DMA1, ADC_DMA_STREAM);
    dma_enable_stream(DMA1, ADC_DMA_STREAM);

    // Enable interrupts on finished DMA transfers
    dma_enable_transfer_complete_interrupt(DMA1, DAC_DMA_STREAM);
    nvic_enable_irq(NVIC_DMA1_STREAM4_IRQ);

    // Start transmitting data
    spi_enable_rx_dma(I2S2_EXT_BASE);
    spi_enable_tx_dma(SPI2);
}