Exemplo n.º 1
0
static u8 spi_readwrite(u32 spi, u8 data)
{
	while (!(SPI_SR(spi) & SPI_SR_TXE))
		;
	SPI_DR(spi) = data;
	while (!(SPI_SR(spi) & SPI_SR_RXNE))
		;
	return SPI_DR(spi);
}
Exemplo n.º 2
0
/**
 * send 1 byte blocking
 * return 1 on success
 */
uint8_t spi_write_byte(uint8_t data){
	while(!(SPI_SR(Current_SPI) & SPI_SR_TXE));
	SPI_DR(Current_SPI) = data;
	while(!(SPI_SR(Current_SPI) & SPI_SR_TXE));
	while(!(SPI_SR(Current_SPI) & SPI_SR_RXNE));
	(void)SPI_DR(Current_SPI);
	while(!(SPI_SR(Current_SPI) & SPI_SR_TXE));
	while(SPI_SR(Current_SPI) & SPI_SR_BSY);
	return 1;
}
Exemplo n.º 3
0
void TBlockingSpiDmaJob::Run()
{
    TaskId = TScheduler::GetCurrentTaskId();
    CurrentJob = this;

    const uint32_t spi = FLASH_SPI_CHANNEL;
    const uint32_t dma = DMA1;

    assert(SPI_SR(spi) & SPI_SR_TXE);
    assert(~SPI_SR(spi) & SPI_SR_BSY);
    assert(!(SPI_SR(spi) & SPI_SR_RXNE));

    {
        const uint32_t channel = FLASH_DMA_TX_CHANNEL;
        dma_channel_reset(dma, channel);
        dma_set_peripheral_address(dma, channel, reinterpret_cast<uint32_t>(&SPI_DR(spi)));
        dma_set_memory_address(dma, channel, reinterpret_cast<uint32_t>(Out));
        dma_set_number_of_data(dma, channel, Len);
        dma_set_read_from_memory(dma, channel);
        dma_enable_memory_increment_mode(dma, channel);
        dma_set_peripheral_size(dma, channel, DMA_CCR_PSIZE_8BIT);
        dma_set_memory_size(dma, channel, DMA_CCR_MSIZE_8BIT);
        dma_set_priority(dma, channel, DMA_CCR_PL_LOW);
        // dma_enable_transfer_complete_interrupt(dma, channel);
        dma_enable_channel(dma, channel);
    }

    {
        const uint32_t channel = FLASH_DMA_RX_CHANNEL;
        dma_channel_reset(dma, channel);
        dma_set_peripheral_address(dma, channel, reinterpret_cast<uint32_t>(&SPI_DR(spi)));
        dma_set_number_of_data(dma, channel, Len);
        if (In != 0) {
            dma_set_memory_address(dma, channel, reinterpret_cast<uint32_t>(In));
            dma_enable_memory_increment_mode(dma, channel);
        }
        else {
            dma_set_memory_address(dma, channel, reinterpret_cast<uint32_t>(&DummyPosition));
        }
        dma_set_peripheral_size(dma, channel, DMA_CCR_PSIZE_8BIT);
        dma_set_memory_size(dma, channel, DMA_CCR_MSIZE_8BIT);
        dma_set_priority(dma, channel, DMA_CCR_PL_LOW);
        dma_enable_transfer_complete_interrupt(dma, channel);
        dma_enable_channel(dma, channel);
    }

    // Kick off the transfer
    spi_enable_rx_dma(spi);
    spi_enable_tx_dma(spi);

    // Wait for completion
    TScheduler::BlockUntil(&Finished);
}
Exemplo n.º 4
0
/**
 * Blocking rite data to current SPI
 * @param data - buffer with data
 * @param len  - buffer length
 * @return 0 in case of error (or 1 in case of success)
 */
uint8_t spiWrite(uint8_t *data, uint16_t len){
	uint16_t i;
	while(!(SPI_SR(Current_SPI) & SPI_SR_TXE));
	for(i = 0; i < len; ++i){
		SPI_DR(Current_SPI) = data[i];
		while(!(SPI_SR(Current_SPI) & SPI_SR_TXE));
	}
	while(!(SPI_SR(Current_SPI) & SPI_SR_RXNE));
	(void)SPI_DR(Current_SPI);
	while(!(SPI_SR(Current_SPI) & SPI_SR_TXE));
	while(SPI_SR(Current_SPI) & SPI_SR_BSY);
	return 1;
}
Exemplo n.º 5
0
int spi_transfer(spi_t spi, u16 data)
{
	u32 r;

	while (!((r = SPI_SR(base_addr(spi))) & (SPI_SR_TXE | SPI_SR_ERROR)))
		;
	if (r & SPI_SR_ERROR)
		return -SPI_TRANSFER_ERROR | r;

	SPI_DR(base_addr(spi)) = data;
	while (!((r = SPI_SR(base_addr(spi))) & (SPI_SR_RXNE | SPI_SR_ERROR)))
		;
	if (r & SPI_SR_ERROR)
		return -SPI_TRANSFER_ERROR | r;

	return SPI_DR(base_addr(spi));
}
Exemplo n.º 6
0
void spi_send(uint32_t spi, uint16_t data)
{
	/* Wait for transfer finished. */
	while (!(SPI_SR(spi) & SPI_SR_TXE));

	/* Write data (8 or 16 bits, depending on DFF) into DR. */
	SPI_DR(spi) = data;
}
Exemplo n.º 7
0
uint16_t spi_read(uint32_t spi)
{
	/* Wait for transfer finished. */
	while (!(SPI_SR(spi) & SPI_SR_RXNE));

	/* Read the data (8 or 16 bits, depending on DFF bit) from DR. */
	return SPI_DR(spi);
}
Exemplo n.º 8
0
/* Receive data using DMA. */
void rx_spi(void *data, uint16_t size){
	if(DmaCleanupNeeded)cleanup_dma_spi();

	/* This byte is sent continuously when rx_spi() receives data. */
	static const uint8_t RxSpiDummyByte = 0x00;

	spi_enable_rx_dma(SPI3);
	
	dma_channel_reset(DMA1, DMA_CHANNEL2);
	dma_disable_channel(DMA1, DMA_CHANNEL2);
	dma_set_peripheral_address(DMA1, DMA_CHANNEL2, (uint32_t) &(SPI_DR(SPI3)));
	dma_set_memory_address(DMA1, DMA_CHANNEL2, (uint32_t) data);
	dma_set_number_of_data(DMA1, DMA_CHANNEL2, size);
	dma_set_priority(DMA1, DMA_CHANNEL2, DMA_CCR_PL_HIGH);
	dma_set_memory_size(DMA1, DMA_CHANNEL2, DMA_CCR_MSIZE_8BIT);
	dma_set_peripheral_size(DMA1, DMA_CHANNEL2, DMA_CCR_PSIZE_8BIT);
	dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL2);
	dma_disable_peripheral_increment_mode(DMA1, DMA_CHANNEL2);
	dma_set_read_from_peripheral(DMA1, DMA_CHANNEL2);
	dma_enable_channel(DMA1, DMA_CHANNEL2);

	/* The SPI peripheral is driven by transmitted bytes, so dummy bytes
	 * must be sent in order to receive data. This is accomplished with DMA
	 * by simply not incrementing the memory address. */
	dma_channel_reset(DMA1, DMA_CHANNEL3);
	dma_disable_channel(DMA1, DMA_CHANNEL3);
	dma_set_peripheral_address(DMA1, DMA_CHANNEL3, (uint32_t) &(SPI_DR(SPI3)));
	dma_set_memory_address(DMA1, DMA_CHANNEL3, (uint32_t) &RxSpiDummyByte);
	dma_set_number_of_data(DMA1, DMA_CHANNEL3, size);
	dma_set_priority(DMA1, DMA_CHANNEL3, DMA_CCR_PL_HIGH);
	dma_set_memory_size(DMA1, DMA_CHANNEL3, DMA_CCR_MSIZE_8BIT);
	dma_set_peripheral_size(DMA1, DMA_CHANNEL3, DMA_CCR_PSIZE_8BIT);
	dma_disable_memory_increment_mode(DMA1, DMA_CHANNEL3);
	dma_disable_peripheral_increment_mode(DMA1, DMA_CHANNEL3);
	dma_set_read_from_memory(DMA1, DMA_CHANNEL3);
	dma_enable_channel(DMA1, DMA_CHANNEL3);
	
	spi_enable_tx_dma(SPI3);
	spi_enable(SPI3);
	DmaCleanupNeeded = true;
}
Exemplo n.º 9
0
/* Cleanup between DMA transfers. */
static void cleanup_dma_spi(void){
	/* Disable SPI without resetting the peripheral. */
	dma_disable_channel(DMA1, DMA_CHANNEL3);
	dma_disable_channel(DMA1, DMA_CHANNEL2);
	spi_disable(SPI3);
	if(TxSpi){
		/* After tx_spi() completes there will be several nonsense bytes
		 * in the RXFIFO. They must be cleared out so that they don't
		 * corrupt a subsequent SPI read. */
		uint8_t throwaway;
		throwaway = SPI_DR(SPI3);
		throwaway = SPI_DR(SPI3);
		throwaway = SPI_DR(SPI3);
		throwaway = SPI_DR(SPI3);
		throwaway = throwaway; /* Suppress compiler warnings. */
		TxSpi = false;
	}
	spi_disable_tx_dma(SPI3);
	spi_disable_rx_dma(SPI3);
	DmaCleanupNeeded = false;
}
Exemplo n.º 10
0
static void spi_dma_setup_rx(uint32_t spi, uint32_t dma, u8 stream, u8 channel)
{
  spi_enable_rx_dma(spi);

  /* Make sure stream is disabled to start. */
  DMA_SCR(dma, stream) &= ~DMA_SxCR_EN;

  /* RM0090 - 9.3.17 : Supposed to wait until enable bit reads '0' before we
   * write to registers. */
  while (DMA_SCR(dma, stream) & DMA_SxCR_EN) ;

  /* RM0090 - 9.3.17 : Supposed to clear any interrupts in DMA status register
   * before we reconfigure registers. */
  dma_clear_interrupt_flags(dma, stream, DMA_ISR_FLAGS);

  /* Configure the DMA controller. */
  DMA_SCR(dma, stream) = 0;
  DMA_SCR(dma, stream) =
    /* Error interrupts. */
    DMA_SxCR_DMEIE | DMA_SxCR_TEIE |
    DMA_SxCR_DIR_PERIPHERAL_TO_MEM |
    /* Enable DMA transfer complete interrupt */
    DMA_SxCR_TCIE |
    /* Increment the memory address after each transfer. */
    DMA_SxCR_MINC |
    /* 8 bit transfers from SPI peripheral. */
    DMA_SxCR_PSIZE_8BIT |
    /* and to memory. */
    DMA_SxCR_MSIZE_8BIT |
    /* Low priority. */
    DMA_SxCR_PL_VERY_HIGH |
    /* The channel selects which request line will trigger a transfer.
     * (see CD00225773.pdf Table 23). */
    DMA_SxCR_CHSEL(channel);

  /* Transfer up to the length of the buffer. */
  DMA_SNDTR(dma, stream) = 0;

  /* DMA from the SPI data register... */
  DMA_SPAR(dma, stream) = &SPI_DR(spi);

  /* Enable DMA interrupts for this stream with the NVIC. */
  if (dma == DMA1)
    nvicEnableVector(dma_irq_lookup[0][stream],
        CORTEX_PRIORITY_MASK(CORTEX_MAX_KERNEL_PRIORITY+2));
  else if (dma == DMA2)
    nvicEnableVector(dma_irq_lookup[1][stream],
        CORTEX_PRIORITY_MASK(CORTEX_MAX_KERNEL_PRIORITY+2));
}
Exemplo n.º 11
0
/* Simultaneously transmit and receive data using DMA. */
void rxtx_spi(void *rxdata, const void *txdata, uint16_t size){
	if(DmaCleanupNeeded)cleanup_dma_spi();

	spi_enable_rx_dma(SPI3);
	
	dma_channel_reset(DMA1, DMA_CHANNEL2);
	dma_disable_channel(DMA1, DMA_CHANNEL2);
	dma_set_peripheral_address(DMA1, DMA_CHANNEL2, (uint32_t) &(SPI_DR(SPI3)));
	dma_set_memory_address(DMA1, DMA_CHANNEL2, (uint32_t) rxdata);
	dma_set_number_of_data(DMA1, DMA_CHANNEL2, size);
	dma_set_priority(DMA1, DMA_CHANNEL2, DMA_CCR_PL_HIGH);
	dma_set_memory_size(DMA1, DMA_CHANNEL2, DMA_CCR_MSIZE_8BIT);
	dma_set_peripheral_size(DMA1, DMA_CHANNEL2, DMA_CCR_PSIZE_8BIT);
	dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL2);
	dma_disable_peripheral_increment_mode(DMA1, DMA_CHANNEL2);
	dma_set_read_from_peripheral(DMA1, DMA_CHANNEL2);
	dma_enable_channel(DMA1, DMA_CHANNEL2);

	dma_channel_reset(DMA1, DMA_CHANNEL3);
	dma_disable_channel(DMA1, DMA_CHANNEL3);
	dma_set_peripheral_address(DMA1, DMA_CHANNEL3, (uint32_t) &(SPI_DR(SPI3)));
	dma_set_memory_address(DMA1, DMA_CHANNEL3, (uint32_t) txdata);
	dma_set_number_of_data(DMA1, DMA_CHANNEL3, size);
	dma_set_priority(DMA1, DMA_CHANNEL3, DMA_CCR_PL_HIGH);
	dma_set_memory_size(DMA1, DMA_CHANNEL3, DMA_CCR_MSIZE_8BIT);
	dma_set_peripheral_size(DMA1, DMA_CHANNEL3, DMA_CCR_PSIZE_8BIT);
	dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL3);
	dma_disable_peripheral_increment_mode(DMA1, DMA_CHANNEL3);
	dma_set_read_from_memory(DMA1, DMA_CHANNEL3);
	dma_enable_channel(DMA1, DMA_CHANNEL3);
	
	spi_enable_tx_dma(SPI3);
	spi_enable(SPI3);

	DmaCleanupNeeded = true;
}
Exemplo n.º 12
0
uint16_t spi_clean_disable(uint32_t spi)
{
	/* Wait to receive last data */
	while (!(SPI_SR(spi) & SPI_SR_RXNE));

	uint16_t data = SPI_DR(spi);

	/* Wait to transmit last data */
	while (!(SPI_SR(spi) & SPI_SR_TXE));

	/* Wait until not busy */
	while (SPI_SR(spi) & SPI_SR_BSY);

	SPI_CR1(spi) &= ~SPI_CR1_SPE;

	return data;
}
Exemplo n.º 13
0
void acq_init()
{
	/* Initialize amplifier control GPIO */
	gpio_mode_setup(BANK_AMP, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_AMP);
	gpio_clear(BANK_AMP, GPIO_AMP);
	gpio_mode_setup(BANK_LED, GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_LED);
	gpio_clear(BANK_LED, GPIO_LED);

	/* Initialize SPI GPIOs */
	gpio_mode_setup(BANK_CS, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_CS);
	gpio_mode_setup(BANK_SCLK, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_SCLK);
	gpio_mode_setup(BANK_DOUT, GPIO_MODE_AF, GPIO_PUPD_NONE, GPIO_DOUT);

	gpio_set_af(BANK_CS, GPIO_AF6, GPIO_CS);
	gpio_set_af(BANK_SCLK, GPIO_AF6, GPIO_SCLK);
	gpio_set_af(BANK_DOUT, GPIO_AF6, GPIO_DOUT);

	rcc_periph_clock_enable(RCC_SPI3);

	acq_spi_init(SPI_C1);

	rcc_periph_clock_enable(RCC_DMA1);
	dma_channel_reset(DMA1, DMA_CHANNEL2);
	dma_disable_channel(DMA1, DMA_CHANNEL2);

	dma_set_peripheral_address(DMA1, DMA_CHANNEL2, (uint32_t)&SPI_DR(SPI_C1));
	dma_set_memory_address(DMA1, DMA_CHANNEL2, (uint32_t)&acq_channel.buff);
	dma_set_number_of_data(DMA1, DMA_CHANNEL2, BUFFER_SIZE);

	dma_set_priority(DMA1, DMA_CHANNEL2, DMA_CCR_PL_MEDIUM);

	dma_set_memory_size(DMA1, DMA_CHANNEL2, DMA_CCR_MSIZE_16BIT);
	dma_set_peripheral_size(DMA1, DMA_CHANNEL2, DMA_CCR_PSIZE_16BIT);
	dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL2);
	dma_set_read_from_peripheral(DMA1, DMA_CHANNEL2);
	dma_enable_circular_mode(DMA1, DMA_CHANNEL2);

	nvic_set_priority(NVIC_DMA1_CHANNEL2_IRQ, PRIO_ACQ);
}
Exemplo n.º 14
0
static void spi_dma_setup_tx(uint32_t spi, uint32_t dma, u8 stream, u8 channel)
{
  spi_enable_tx_dma(spi);

  /* Make sure stream is disabled to start. */
  DMA_SCR(dma, stream) &= ~DMA_SxCR_EN;

  /* Configure the DMA controller. */
  DMA_SCR(dma, stream) = 0;
  DMA_SCR(dma, stream) =
    /* Error interrupts. */
    DMA_SxCR_DMEIE | DMA_SxCR_TEIE |
    DMA_SxCR_DIR_MEM_TO_PERIPHERAL |
    /* Increment the memory address after each transfer. */
    DMA_SxCR_MINC |
    /* 8 bit transfers from SPI peripheral. */
    DMA_SxCR_PSIZE_8BIT |
    /* and to memory. */
    DMA_SxCR_MSIZE_8BIT |
    /* Low priority. */
    DMA_SxCR_PL_VERY_HIGH |
    /* The channel selects which request line will trigger a transfer.
     * (see CD00225773.pdf Table 23). */
    DMA_SxCR_CHSEL(channel);

  /* Transfer up to the length of the buffer. */
  DMA_SNDTR(dma, stream) = 0;

  /* DMA from the SPI data register... */
  DMA_SPAR(dma, stream) = &SPI_DR(spi);

  /* Enable DMA interrupts for this stream with the NVIC. */
  if (dma == DMA1)
    nvicEnableVector(dma_irq_lookup[0][stream],
        CORTEX_PRIORITY_MASK(CORTEX_MAX_KERNEL_PRIORITY+2));
  else if (dma == DMA2)
    nvicEnableVector(dma_irq_lookup[1][stream],
        CORTEX_PRIORITY_MASK(CORTEX_MAX_KERNEL_PRIORITY+2));
}
Exemplo n.º 15
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.
    // With this PLL configuration the actual sampling frequency
    // is nominally 47991 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);

    dma_enable_transfer_complete_interrupt(DMA1, ADC_DMA_STREAM);
    nvic_enable_irq(NVIC_DMA1_STREAM3_IRQ);
    nvic_set_priority(NVIC_DMA1_STREAM3_IRQ, 0x80); // 0 is most urgent

    // Start transmitting data
    spi_enable_rx_dma(I2S2_EXT_BASE);
    spi_enable_tx_dma(SPI2);
}
Exemplo n.º 16
0
static int spi_dma_transceive(uint8_t *tx_buf, int tx_len, uint8_t *rx_buf, int rx_len)
#endif
{
/* Check for 0 length in both tx and rx */
    if ((rx_len < 1) && (tx_len < 1)) {
/* return -1 as error */
        return -1;
    }

/* Reset DMA channels*/
    dma_channel_reset(DMA1, DMA_CHANNEL4);
    dma_channel_reset(DMA1, DMA_CHANNEL5);

/* Reset SPI data and status registers.
 * Here we assume that the SPI peripheral is NOT
 * busy any longer, i.e. the last activity was verified
 * complete elsewhere in the program.
 */
    volatile uint8_t temp_data __attribute__ ((unused));
    while (SPI_SR(SPI2) & (SPI_SR_RXNE | SPI_SR_OVR)) {
        temp_data = SPI_DR(SPI2);
    }

/* Reset status flag appropriately (both 0 case caught above) */
    transceive_status = NONE;
    if (rx_len < 1) {
        transceive_status = ONE;
    }
    if (tx_len < 1) {
        transceive_status = ONE;
    }

/* Set up rx dma, note it has higher priority to avoid overrun */
    if (rx_len > 0) {
        dma_set_peripheral_address(DMA1, DMA_CHANNEL4, (uint32_t)&SPI2_DR);
        dma_set_memory_address(DMA1, DMA_CHANNEL4, (uint32_t)rx_buf);
        dma_set_number_of_data(DMA1, DMA_CHANNEL4, rx_len);
        dma_set_read_from_peripheral(DMA1, DMA_CHANNEL4);
        dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL4);
#if USE_16BIT_TRANSFERS
        dma_set_peripheral_size(DMA1, DMA_CHANNEL4, DMA_CCR_PSIZE_16BIT);
        dma_set_memory_size(DMA1, DMA_CHANNEL4, DMA_CCR_MSIZE_16BIT);
#else
        dma_set_peripheral_size(DMA1, DMA_CHANNEL4, DMA_CCR_PSIZE_8BIT);
        dma_set_memory_size(DMA1, DMA_CHANNEL4, DMA_CCR_MSIZE_8BIT);
#endif
        dma_set_priority(DMA1, DMA_CHANNEL4, DMA_CCR_PL_VERY_HIGH);
    }

/* Set up tx dma */
    if (tx_len > 0) {
        dma_set_peripheral_address(DMA1, DMA_CHANNEL5, (uint32_t)&SPI2_DR);
        dma_set_memory_address(DMA1, DMA_CHANNEL5, (uint32_t)tx_buf);
        dma_set_number_of_data(DMA1, DMA_CHANNEL5, tx_len);
        dma_set_read_from_memory(DMA1, DMA_CHANNEL5);
        dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL5);
#if USE_16BIT_TRANSFERS
        dma_set_peripheral_size(DMA1, DMA_CHANNEL5, DMA_CCR_PSIZE_16BIT);
        dma_set_memory_size(DMA1, DMA_CHANNEL5, DMA_CCR_MSIZE_16BIT);
#else
        dma_set_peripheral_size(DMA1, DMA_CHANNEL5, DMA_CCR_PSIZE_8BIT);
        dma_set_memory_size(DMA1, DMA_CHANNEL5, DMA_CCR_MSIZE_8BIT);
#endif
        dma_set_priority(DMA1, DMA_CHANNEL5, DMA_CCR_PL_HIGH);
    }

/* Enable dma transfer complete interrupts */
    if (rx_len > 0) {
        dma_enable_transfer_complete_interrupt(DMA1, DMA_CHANNEL4);
    }
    if (tx_len > 0) {
        dma_enable_transfer_complete_interrupt(DMA1, DMA_CHANNEL5);
    }

/* Activate dma channels */
    if (rx_len > 0) {
        dma_enable_channel(DMA1, DMA_CHANNEL4);
    }
    if (tx_len > 0) {
        dma_enable_channel(DMA1, DMA_CHANNEL5);
    }

/* Enable the spi transfer via dma
 * This will immediately start the transmission,
 * after which when the receive is complete, the
 * receive dma will activate
 */
    if (rx_len > 0) {
        spi_enable_rx_dma(SPI2);
    }
    if (tx_len > 0) {
        spi_enable_tx_dma(SPI2);
    }

    return 0;
}
Exemplo n.º 17
0
/*****************************************************************************
* 函 数 名  : spiSend
*
* 功能描述  : SPI数据轮询发送
*
* 输入参数  : spiNo SPI控制器号
*                  cs:   片选号
*                  pData:   指向要发送数据地址的指针
*                  ulLen:要发送的数据的大小
* 输出参数  :
*
* 返 回 值  : OK or ERROR
*
* 其它说明  :
*
*****************************************************************************/
s32 spi_send (u32 spiNo, u32 cs, u16* pData, u32 ulLen)
{
    u16 *pSh;
    u32  i;
    u32 ulLoop = SPI_MAX_DELAY_TIMES;
    u32 ulVal;

    if (((0 != spiNo) && (1 != spiNo))
        || (0 != cs && 1 != cs)
        || (NULL == pData) || (0 == ulLen))
    {
        return ERROR;
    }

    pSh = (u16*)pData;

    /* 禁止SPI Slave*/
    writel(0, SPI_SLAVE_EN(spiNo));

    /* 禁止SPI Master*/
    writel(0, SPI_EN(spiNo));

    /* 设置成发送模式 */
    writel(((readl(SPI_CTRL0(spiNo)) & ~SPI_CTRL0_TMOD_BITMASK) | SPI_CTRL0_TMOD_SEND),SPI_CTRL0(spiNo));

    /*使能SPI Master*/
    writel(1, SPI_EN(spiNo));

    /*使能SPI Slave*/
    writel((1 << cs), SPI_SLAVE_EN(spiNo));

    /* 发送命令 */
    for(i = 0; i < ulLen; i++)
    {
        /* 等待发送FIFO非满 */
        while(!(readl(SPI_STATUS(spiNo)) & SPI_STATUS_TXNOTFULL)
            && (0 != --ulLoop))
        {
        }

        if(0 == ulLoop)
        {
            return ERROR;
        }
        writel(*pSh++, SPI_DR(spiNo));
    }

    /*将发送FIFO中的数据全部发出,且不BUSY*/
    ulLoop = SPI_MAX_DELAY_TIMES;
    ulVal = readl(SPI_STATUS(spiNo));
    while(((!(ulVal & SPI_STATUS_TXEMPTY)) || (ulVal & SPI_STATUS_BUSY))
        && (0 != --ulLoop))
    {
        ulVal = readl(SPI_STATUS(spiNo));
    }

    if(0 == ulLoop)
    {
        return ERROR;
    }

    return OK;
}
Exemplo n.º 18
0
/*****************************************************************************
* 函 数 名  : spiRecv
*
* 功能描述  : SPI数据轮询接收数据
*
* 输入参数  : spiNo SPI控制器号
*                  cs:   片选号
*                  prevData:   指向要读取数据地址的指针
*                  recvSize:要读取的数据的大小
*                  psendData: 指向要发送的命令和地址的指针
*                  sendSize:  要发送命令和地址的长度(3 或者4)
* 输出参数  :
*
* 返 回 值  : OK or ERROR
*
* 其它说明  :
*
*****************************************************************************/
s32 spi_recv (u32 spiNo, u32 cs, u16* prevData, u32 recvSize,u16* psendData,u32 sendSize )
{
    u16 *pRh;
    u16 *pSh;
    u32  i;
    u32 ulLoop = SPI_MAX_DELAY_TIMES;

    /*有2个spi控制器,每个控制器有2个片选*/
    if (((0 != spiNo) && (1 != spiNo))
        || (0 != cs && 1 != cs)
        || (NULL == psendData) || (NULL == prevData) || (0 == recvSize) || (0 == sendSize))
    {
        return ERROR;
    }

    pRh = prevData;
    pSh = psendData;

    /* 禁止SPI Slave*/
    writel(0,SPI_SLAVE_EN(spiNo));

    /* 禁止SPI Master*/
    writel(0, SPI_EN(spiNo));

    /* 设置成EEPROM读模式 */
    /*writel((readl(SPI_CTRL0(spiNo)) | SPI_CTRL0_TMOD_EEPROM_READ),SPI_CTRL0(spiNo));*/
    writel(((readl(SPI_CTRL0(spiNo)) & ~SPI_CTRL0_TMOD_BITMASK) | SPI_CTRL0_TMOD_SEND_RECV),SPI_CTRL0(spiNo));

    /* 设置接收数据的数目*/
    writel((recvSize-1),SPI_CTRL1(spiNo));

    /*使能SPI Master*/
    writel(1, SPI_EN(spiNo));

    /*使能SPI Slave*/
    writel((1 << cs), SPI_SLAVE_EN(spiNo));

    /* 发送命令 */
    for(i = 0; i < sendSize; i++)
    {
        /* 等待发送FIFO非满 */
        while(!(readl(SPI_STATUS(spiNo)) & SPI_STATUS_TXNOTFULL)
            && (0 != --ulLoop))
        {
        }

        if(0 == ulLoop)
        {
            return ERROR;
        }

        writel(*pSh++, SPI_DR(spiNo));
    }

    /*将发送FIFO中的数据全部发出*/
    while(!(readl(SPI_STATUS(spiNo)) & SPI_STATUS_TXEMPTY)
        && (0 != --ulLoop))
    {
    }

    if(0 == ulLoop)
    {
        return ERROR;
    }

    /* 接收数据 */
    for(i = 0; i < recvSize; i++)
    {
        ulLoop = SPI_MAX_DELAY_TIMES;
        /* 等待读取到数据 */
        while(!(readl(SPI_STATUS(spiNo)) & SPI_STATUS_RXNOTEMPTY)
            && (0 != --ulLoop))
        {
        }

        if(0 == ulLoop)
        {
            return ERROR;
        }

        *pRh++ = readl(SPI_DR(spiNo));

    }

/* SPI控制器会自动禁使能,这里无需软件操作 */
#if 0
    /* 禁止SPI Slave*/
    writel(0, SPI_SLAVE_EN(spiNo));

    /* 禁止SPI Master*/
    writel(0, SPI_EN(spiNo));
#endif
    return OK;
}
Exemplo n.º 19
0
bool TSpiDmaQueue::TryStartJob()
{
    // Start the next DMA job in the queue if the SPI interface is
    // available (TXE=1 and BSY=0)
    // We treat both SPI busses (flash and display) as one, so no concurrent jobs
    // are allowed.

    const uint32_t spi = LCD_SPI_CHANNEL;
    if ((SPI_SR(spi) & SPI_SR_TXE) && (~SPI_SR(spi) & SPI_SR_BSY)) {

        if (Jobs.Empty()) {
            return false;
        }

        const TSpiDmaJob& job = Jobs.First();
        const TBuffer& buffer = job.GetBuffer();

        // SPI receive register should be empty here!
        assert(!(SPI_SR(spi) & SPI_SR_RXNE));

        const uint32_t dma = DMA1;
        {
            const uint32_t channel = (job.GetChip() == TSpiDmaJob::CS_LCD) ? LCD_DMA_TX_CHANNEL : FLASH_DMA_TX_CHANNEL;
            dma_channel_reset(dma, channel);
            dma_set_peripheral_address(dma, channel, reinterpret_cast<uint32_t>(&SPI_DR(spi)));
            dma_set_memory_address(dma, channel, reinterpret_cast<uint32_t>(buffer.GetData()));
            dma_set_number_of_data(dma, channel, buffer.GetLength());
            dma_set_read_from_memory(dma, channel);
            dma_enable_memory_increment_mode(dma, channel);
            dma_set_peripheral_size(dma, channel, DMA_CCR_PSIZE_8BIT);
            dma_set_memory_size(dma, channel, DMA_CCR_MSIZE_8BIT);
            dma_set_priority(dma, channel, DMA_CCR_PL_LOW);
            //dma_enable_transfer_complete_interrupt(dma, channel);
            dma_enable_channel(dma, channel);
        }

        {
            const uint32_t channel =  (job.GetChip() == TSpiDmaJob::CS_LCD) ? LCD_DMA_RX_CHANNEL : FLASH_DMA_RX_CHANNEL;
            dma_channel_reset(dma, channel);
            dma_set_peripheral_address(dma, channel, reinterpret_cast<uint32_t>(&SPI_DR(spi)));
            dma_set_memory_address(dma, channel, reinterpret_cast<uint32_t>(buffer.GetData()));
            dma_set_number_of_data(dma, channel, buffer.GetLength());
            dma_enable_memory_increment_mode(dma, channel);
            dma_set_peripheral_size(dma, channel, DMA_CCR_PSIZE_8BIT);
            dma_set_memory_size(dma, channel, DMA_CCR_MSIZE_8BIT);
            dma_set_priority(dma, channel, DMA_CCR_PL_LOW);
            dma_enable_transfer_complete_interrupt(dma, channel);
            dma_enable_channel(dma, channel);
        }

        // Set CS and LCD_A0 lines
        Pin_lcd_cs.Clear();
        if (job.GetLcdData()) {
            Pin_lcd_a0.Set();
        } else {
            Pin_lcd_a0.Clear();
        }

        // Kick off the transfer
        spi_enable_rx_dma(spi);
        spi_enable_tx_dma(spi);

        return true;
    }

    return false;
}
Exemplo n.º 20
0
u16 spi_recv(spi_t spi)
{

	return SPI_DR(base_addr(spi));
}
Exemplo n.º 21
0
void spi_send(spi_t spi, u16 data)
{
	SPI_DR(base_addr(spi)) = data;
}
Exemplo n.º 22
0
static int spi_dma_transceive(uint8_t *tx_buf, int tx_len, uint8_t *rx_buf, int rx_len)
#endif
{	

	/* Check for 0 length in both tx and rx */
	if ((rx_len < 1) && (tx_len < 1)) {
		/* return -1 as error */
		return -1;
	}

	/* Reset DMA channels*/
	dma_channel_reset(DMA1, DMA_CHANNEL2);
	dma_channel_reset(DMA1, DMA_CHANNEL3);

	/* Reset SPI data and status registers.
	 * Here we assume that the SPI peripheral is NOT
	 * busy any longer, i.e. the last activity was verified
	 * complete elsewhere in the program.
	 */
	volatile uint8_t temp_data __attribute__ ((unused));
	while (SPI_SR(SPI1) & (SPI_SR_RXNE | SPI_SR_OVR)) {
		temp_data = SPI_DR(SPI1);
	}

	/* Reset status flag appropriately (both 0 case caught above) */
	transceive_status = NONE;
	if (rx_len < 1) {
		transceive_status = ONE;
	}

	/* Determine tx length case to change behaviour
	 * If tx_len >= rx_len, then normal case, run both DMAs with normal settings
	 * If rx_len == 0, just don't run the rx DMA at all
	 * If tx_len == 0, use a dummy buf and set the tx dma to transfer the same
	 *    amount as the rx_len, to ensure everything is clocked in
	 * If 0 < tx_len < rx_len, first do a normal case, then on the tx finished
	 *    interrupt, set up a new dummyy buf tx dma transfer for the remaining
	 *    required clock cycles (handled in tx dma complete interrupt)
	 */
	if ((tx_len > 0) && (tx_len < rx_len)) {
		rx_buf_remainder = rx_len - tx_len;
	}

	/* Set up rx dma, note it has higher priority to avoid overrun */
	if (rx_len > 0) {
		dma_set_peripheral_address(DMA1, DMA_CHANNEL2, (uint32_t)&SPI1_DR);
		dma_set_memory_address(DMA1, DMA_CHANNEL2, (uint32_t)rx_buf);
		dma_set_number_of_data(DMA1, DMA_CHANNEL2, rx_len);
		dma_set_read_from_peripheral(DMA1, DMA_CHANNEL2);
		dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL2);
#if USE_16BIT_TRANSFERS
		dma_set_peripheral_size(DMA1, DMA_CHANNEL2, DMA_CCR_PSIZE_16BIT);
		dma_set_memory_size(DMA1, DMA_CHANNEL2, DMA_CCR_MSIZE_16BIT);
#else
		dma_set_peripheral_size(DMA1, DMA_CHANNEL2, DMA_CCR_PSIZE_8BIT);
		dma_set_memory_size(DMA1, DMA_CHANNEL2, DMA_CCR_MSIZE_8BIT);
#endif
		dma_set_priority(DMA1, DMA_CHANNEL2, DMA_CCR_PL_VERY_HIGH);
	}

	/* Set up tx dma (must always run tx to get clock signal) */
	if (tx_len > 0) {
		/* Here we have a regular tx transfer */
		dma_set_peripheral_address(DMA1, DMA_CHANNEL3, (uint32_t)&SPI1_DR);
		dma_set_memory_address(DMA1, DMA_CHANNEL3, (uint32_t)tx_buf);
		dma_set_number_of_data(DMA1, DMA_CHANNEL3, tx_len);
		dma_set_read_from_memory(DMA1, DMA_CHANNEL3);
		dma_enable_memory_increment_mode(DMA1, DMA_CHANNEL3);
#if USE_16BIT_TRANSFERS
		dma_set_peripheral_size(DMA1, DMA_CHANNEL3, DMA_CCR_PSIZE_16BIT);
		dma_set_memory_size(DMA1, DMA_CHANNEL3, DMA_CCR_MSIZE_16BIT);
#else
		dma_set_peripheral_size(DMA1, DMA_CHANNEL3, DMA_CCR_PSIZE_8BIT);
		dma_set_memory_size(DMA1, DMA_CHANNEL3, DMA_CCR_MSIZE_8BIT);
#endif
		dma_set_priority(DMA1, DMA_CHANNEL3, DMA_CCR_PL_HIGH);
	} else {
		/* Here we aren't transmitting any real data, use the dummy buffer
		 * and set the length to the rx_len to get all rx data in, while
		 * not incrementing the memory pointer
		 */
		dma_set_peripheral_address(DMA1, DMA_CHANNEL3, (uint32_t)&SPI1_DR);
		dma_set_memory_address(DMA1, DMA_CHANNEL3, (uint32_t)(&dummy_tx_buf)); // Change here
		dma_set_number_of_data(DMA1, DMA_CHANNEL3, rx_len); // Change here
		dma_set_read_from_memory(DMA1, DMA_CHANNEL3);
		dma_disable_memory_increment_mode(DMA1, DMA_CHANNEL3); // Change here
#if USE_16BIT_TRANSFERS
		dma_set_peripheral_size(DMA1, DMA_CHANNEL3, DMA_CCR_PSIZE_16BIT);
		dma_set_memory_size(DMA1, DMA_CHANNEL3, DMA_CCR_MSIZE_16BIT);
#else
		dma_set_peripheral_size(DMA1, DMA_CHANNEL3, DMA_CCR_PSIZE_8BIT);
		dma_set_memory_size(DMA1, DMA_CHANNEL3, DMA_CCR_MSIZE_8BIT);
#endif
		dma_set_priority(DMA1, DMA_CHANNEL3, DMA_CCR_PL_HIGH);
	}

	/* Enable dma transfer complete interrupts */
	if (rx_len > 0) {
		dma_enable_transfer_complete_interrupt(DMA1, DMA_CHANNEL2);
	}
	dma_enable_transfer_complete_interrupt(DMA1, DMA_CHANNEL3);

	/* Activate dma channels */
	if (rx_len > 0) {
		dma_enable_channel(DMA1, DMA_CHANNEL2);
	}
	dma_enable_channel(DMA1, DMA_CHANNEL3);

	/* Enable the spi transfer via dma
	 * This will immediately start the transmission,
	 * after which when the receive is complete, the
	 * receive dma will activate
	 */
	if (rx_len > 0) {
    	spi_enable_rx_dma(SPI1);
    }
    spi_enable_tx_dma(SPI1);

    return 0;
}
Exemplo n.º 23
0
void spi_write(uint32_t spi, uint16_t data)
{
	/* Write data (8 or 16 bits, depending on DFF) into DR. */
	SPI_DR(spi) = data;
}