Esempio n. 1
0
void spi1_xfer_dma(u16 n_bytes, u8 data_in[], const u8 data_out[])
{
  /* We use a static buffer here for DMA transfers as data_in/data_out
   * often are on the stack in CCM which is not accessible by DMA.
   */
  static volatile u8 spi_dma_buf[128];

  memcpy((u8*)spi_dma_buf, data_out, n_bytes);

  /* Setup transmit stream */
  DMA_SM0AR(DMA2, 3) = spi_dma_buf;
  DMA_SNDTR(DMA2, 3) = n_bytes;

  /* Setup receive stream */
  DMA_SM0AR(DMA2, 0) = spi_dma_buf;
  DMA_SNDTR(DMA2, 0) = n_bytes;

  /* We need a memory buffer here to avoid a transfer error */
  asm volatile ("dmb");

  /* Enable the DMA RX channel. */
  DMA_SCR(DMA2, 0) |= DMA_SxCR_EN;
  /* Enable the transmit channel to begin the transaction */
  DMA_SCR(DMA2, 3) |= DMA_SxCR_EN;

  /* Yeild the CPU while we wait for the transaction to complete */
  chBSemWait(&spi_dma_sem);

  if (data_in != NULL)
    memcpy(data_in, (u8*)spi_dma_buf, n_bytes);
}
Esempio n. 2
0
void codecPeek(const int16_t** buffer, unsigned* buffersamples, unsigned* writepos)
{
    *buffersamples = 2*BUFFER_SAMPLES;
    *buffer = adcBuffer[0];

    unsigned target = dma_get_target(DMA1, ADC_DMA_STREAM);
    unsigned numberOfData = DMA_SNDTR(DMA1, ADC_DMA_STREAM);

    if (target != dma_get_target(DMA1, ADC_DMA_STREAM)) {
        target = dma_get_target(DMA1, ADC_DMA_STREAM);
        numberOfData = DMA_SNDTR(DMA1, ADC_DMA_STREAM);
    }

    *writepos = (target ? BUFFER_SAMPLES : 0) + (BUFFER_SAMPLES - numberOfData);
}
Esempio n. 3
0
/** Returns a lower bound on the number of bytes in the DMA receive buffer.
 * Also checks for buffer overrun conditions.
 * \param s The USART DMA state structure.
 */
u32 usart_n_read_dma(usart_rx_dma_state* s)
{
  s32 n_read = s->rd_wraps * USART_RX_BUFFER_LEN + s->rd;
  s32 n_written = (s->wr_wraps + 1) * USART_RX_BUFFER_LEN - \
                  DMA_SNDTR(s->dma, s->stream);
  s32 n_available = n_written - n_read;

  if (n_available < 0)
    /* This strange and rare case occurs when NDTR has rolled over but the flag
     * hasn't been raised yet and thus n_wraps hasn't been incremented in the
     * ISR. Simply return 0 this time and the next time this function is called
     * (or at some point) the interrupt will have been triggered and the number
     * of bytes available in the buffer will be a sane amount. */
    n_available = 0;
  else if (n_available > USART_RX_BUFFER_LEN) {
    /* If greater than a whole buffer then we have had an overflow. */
    printf("ERROR: DMA RX buffer overrun\n");
    n_available = 0;
    s->errors++;
    /* Disable and re-enable the DMA channel to get back to a known good
     * state */
    usart_rx_dma_disable(s);
    usart_rx_dma_setup(s, s->usart, s->dma, s->stream, s->channel);
  }

  return n_available;
}
Esempio n. 4
0
void dma_stream_reset(u32 dma, u8 stream)
{
/* Disable stream (must be done before register is otherwise changed). */
	DMA_SCR(dma, stream) &= ~DMA_SxCR_EN;
/* Reset all config bits. */
	DMA_SCR(dma, stream) = 0;
/* Reset data transfer number. */
	DMA_SNDTR(dma, stream) = 0;
/* Reset peripheral and memory addresses. */
	DMA_SPAR(dma, stream) = 0;
	DMA_SM0AR(dma, stream) = 0;
	DMA_SM1AR(dma, stream) = 0;
/* This is the default setting */
	DMA_SFCR(dma, stream) = 0x21;
/* Reset all stream interrupt flags using the interrupt flag clear register. */
	u32 mask = DMA_ISR_MASK(stream);
	if (stream < 4)
	{
		DMA_LIFCR(dma) |= mask;
	}
	else
	{
		DMA_HIFCR(dma) |= mask;
	}	
}
Esempio n. 5
0
/** Helper function that schedules a new transfer with the DMA controller if
 * needed.
 * \param s The USART DMA state structure.
 * */
static void dma_schedule(usart_tx_dma_state* s)
{
    /* TODO: We shouldn't have to check for this now that we are called
     * atomically but leaving it in for now just in case. */
    if (DMA_SCR(s->dma, s->stream) & DMA_SxCR_EN)
        screaming_death("DMA TX scheduled while DMA channel running");

    DMA_SM0AR(s->dma, s->stream) = &(s->buff[s->rd]);

    /* Save the transfer length so we can increment the read index after the
     * transfer is finished. */
    if (s->rd < s->wr)
        /* DMA up until write pointer. */
        s->xfer_len = s->wr - s->rd;
    else
        /* DMA up until the end of the buffer. */
        s->xfer_len = USART_TX_BUFFER_LEN - s->rd;

    /* Set the number of datas in the DMA controller. */
    DMA_SNDTR(s->dma, s->stream) = s->xfer_len;

    /* Clear USART_TC flag */
    USART_SR(s->usart) &= ~USART_SR_TC;

    /* Enable DMA stream to start transfer. */
    DMA_SCR(s->dma, s->stream) |= DMA_SxCR_EN;
}
Esempio n. 6
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));
}
Esempio n. 7
0
/*******************************************************************************
 * void bsp_uart_start_dma(struct CB_UART* pctl);
 * @brief	: If DMA driven uart, start DMA sending if not already sending
 * @param	: pctl: control block poiner
 * @return	:
*******************************************************************************/
void bsp_uart_start_dma(struct CB_UART* pctl)
{
	if (pctl->flag != 2) return;	// Return, not DMA driven
	
	/* Are we already running? */
	// First look at the enable bit
	if ((DMA_SCR(pctl->idma, pctl->txdma_stream) & 0x1) != 0) return;	// Already running


	// Check if the counter has gone to zero
	if ( DMA_SNDTR(pctl->idma,pctl->txdma_stream) != 0) return;
	
	/* Not running.  If there are any to send, set up the DMA. */
	common_dma(pctl);

	return;
}
Esempio n. 8
0
/** Returns a lower bound on the number of bytes in the DMA receive buffer.
 * Also checks for buffer overrun conditions.
 * \param s The USART DMA state structure.
 */
u32 usart_n_read_dma(usart_rx_dma_state* s)
{
  s32 n_read = s->rd_wraps * USART_RX_BUFFER_LEN + s->rd;
  s32 n_written = (s->wr_wraps + 1) * USART_RX_BUFFER_LEN - \
                  DMA_SNDTR(s->dma, s->stream);
  s32 n_available = n_written - n_read;

  if (n_available < 0)
    /* This strange and rare case occurs when NDTR has rolled over but the flag
     * hasn't been raised yet and thus n_wraps hasn't been incremented in the
     * ISR. Simply return 0 this time and the next time this function is called
     * (or at some point) the interrupt will have been triggered and the number
     * of bytes available in the buffer will be a sane amount. */
    n_available = 0;
  else if (n_available > USART_RX_BUFFER_LEN)
    /* If greater than a whole buffer then we have had an overflow. */
    screaming_death("DMA RX buffer overrun");

  return n_available;
}
Esempio n. 9
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));
}
Esempio n. 10
0
/*******************************************************************************
 * int bsp_uart_getcount_ptr    (struct CB_UART* pctl);	// Select: control blk ptr
 * int bsp_uart_getcount_uartnum(int uartnum);	// Select: uart number
 * @brief	: Get the number of bytes buffered
 * @param	: pctl = pointer uart control block
 * @return	: number of chars in currently buffered.
*******************************************************************************/
int bsp_uart_getcount_ptr(struct CB_UART* pctl)
{
	int	Diff;

	if (pctl->flag == 1)
	{ // Here, interrupt driven uart
		Diff = (int)(pctl->rxbuff_in - pctl->rxbuff_out);
		if (Diff < 0)
			Diff += pctl->rxbuff_size;  // Adjust for wrap
		return Diff;
	}

	if (pctl->flag == 2)
	{ // Here, DMA driven uart
		/* Difference between where we are taking out chars, and where DMA is/was storing */
		Diff = ( pctl->rxbuff_end - DMA_SNDTR(pctl->idma,pctl->rxdma_stream) - pctl->rxbuff_out );
		if (Diff < 0)
			Diff += pctl->rxbuff_size;  // Adjust for wrap
		return Diff;
	}
	return 0;	// Something wrong if we got here.
}
Esempio n. 11
0
static void common_dma(struct CB_UART* pctl)
{
/* NOTE: This routine is entered from mainline only if the DMA is idle, and entered
   after a DMA interrupt, after it is disabled.  Therefore, the following is based on
   a given stream DMA interrupt not occuring while the mainline is mucking around in this
   routine. */
	int tmp;
	u8* ptmp;

	/* Are there bytes buffered? (Certainly yes if entered from mainline.) */  
	tmp = (pctl->txbuff_in - pctl->txbuff_out);
	if (tmp == 0) return;	

	if (tmp < 0)	// Wrap around check.
	{ // Here, there is wrap-around, so send what remains in (non-circular) buffer.
	  // (Upon the next DMA interrupt what remains after the wrap-around will be sent.)

		// Compute number of bytes remaining to the end of the buffer
		tmp = (pctl->txbuff_end - pctl->txbuff_out); 			// Remaining ct
		DMA_SM0AR(pctl->idma,pctl->txdma_stream) = pctl->txbuff_out; 	// Set TX mem address
		pctl->txbuff_dmanext = pctl->txbuff_base;				// Save new start ptr
	}
	else
	{ // Here, no wrap around, so all buffered bytes can be sent with one setting
		DMA_SM0AR(pctl->idma,pctl->txdma_stream) = pctl->txbuff_out; // Set TX mem address
// redundant	tmp = pctl->txbuff_in - pctl->txbuff_out);		// Number of bytes to send
		ptmp = tmp + pctl->txbuff_out;
		if (ptmp >= pctl->txbuff_end)
			ptmp = pctl->txbuff_base;
		pctl->txbuff_dmanext = ptmp;				// Save new start ptr
	}

	DMA_SNDTR(pctl->idma,pctl->txdma_stream)  = tmp;		// Set number of bytes
	DMA_SCR (pctl->idma,pctl->txdma_stream) |= 0x1;		// Enable DMA and away we go!

	return;	
}
Esempio n. 12
0
/** Setup the USART for receive with DMA.
 * This function sets up the DMA controller and additional USART parameters for
 * DMA receive. The USART must already be configured for normal operation.
 *
 * \param s The USART DMA state structure.
 * \oaram usart The USART base address.
 * \param dma The DMA controller base address.
 * \param stream The DMA stream number to use.
 * \param channel The DMA channel to use. The stream and channel must
 *                correspond to a USART RX channel.
 */
void usart_rx_dma_setup(usart_rx_dma_state* s, u32 usart,
                        u32 dma, u8 stream, u8 channel)
{
  s->dma = dma;
  s->usart = usart;
  s->stream = stream;
  s->channel = channel;
  chBSemInit(&s->ready_sem, TRUE);

  s->byte_counter = 0;
  s->last_byte_ticks = chTimeNow();

  /* Enable clock to DMA peripheral. */
  if (dma == DMA1)
    RCC_AHB1ENR |= RCC_AHB1ENR_DMA1EN;
  else if (dma == DMA2)
    RCC_AHB1ENR |= RCC_AHB1ENR_DMA2EN;

  /* Enable RX DMA on the USART. */
  usart_enable_rx_dma(usart);

  /* 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 |
    /* Transfer complete interrupt. */
    DMA_SxCR_TCIE |
    /* Enable circular buffer mode. */
    DMA_SxCR_CIRC |
    DMA_SxCR_DIR_PERIPHERAL_TO_MEM |
    /* Increment the memory address after each transfer. */
    DMA_SxCR_MINC |
    /* 8 bit transfers from USART peripheral. */
    DMA_SxCR_PSIZE_8BIT |
    /* and to memory. */
    DMA_SxCR_MSIZE_8BIT |
    /* Low priority. */
    DMA_SxCR_PL_LOW |
    /* 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) = USART_RX_BUFFER_LEN;

  /* DMA from the USART data register... */
  DMA_SPAR(dma, stream) = &USART_DR(usart);
  /* ...to the RX buffer. */
  DMA_SM0AR(dma, stream) = s->buff;

  /* Buffer is empty to begin with. */
  s->rd = 0;
  s->rd_wraps = s->wr_wraps = 0;

  /* Enable DMA interrupts for this stream with the NVIC. */
  if (dma == DMA1)
    nvicEnableVector(dma_irq_lookup[0][stream],
        CORTEX_PRIORITY_MASK(USART_DMA_ISR_PRIORITY));
  else if (dma == DMA2)
    nvicEnableVector(dma_irq_lookup[1][stream],
        CORTEX_PRIORITY_MASK(USART_DMA_ISR_PRIORITY));

  /* These reads clear error flags before enabling DMA */
  (void)USART_SR(usart);
  (void)USART_DR(usart);

  /* Enable the DMA channel. */
  DMA_SCR(dma, stream) |= DMA_SxCR_EN;
}
Esempio n. 13
0
/** Setup the USART for transmission with DMA.
 * This function sets up the DMA controller and additional USART parameters for
 * DMA transmit. The USART must already be configured for normal operation.
 *
 * \param s The USART DMA state structure.
 * \oaram usart The USART base address.
 * \param dma The DMA controller base address.
 * \param stream The DMA stream number to use.
 * \param channel The DMA channel to use. The stream and channel must
 *                correspond to a USART RX channel.
 */
void usart_tx_dma_setup(usart_tx_dma_state* s, u32 usart,
                        u32 dma, u8 stream, u8 channel)
{
    s->dma = dma;
    s->usart = usart;
    s->stream = stream;
    s->channel = channel;

    s->byte_counter = 0;
    s->last_byte_ticks = chTimeNow();

    /* Enable clock to DMA peripheral. */
    if (dma == DMA1)
        RCC_AHB1ENR |= RCC_AHB1ENR_DMA1EN;
    else if (dma == DMA2)
        RCC_AHB1ENR |= RCC_AHB1ENR_DMA2EN;

    /* Enable TX DMA on the USART. */
    usart_enable_tx_dma(usart);

    /* 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 |
        /* Transfer complete interrupt. */
        DMA_SxCR_TCIE |
        DMA_SxCR_DIR_MEM_TO_PERIPHERAL |
        /* Increment the memory address after each transfer. */
        DMA_SxCR_MINC |
        /* 4 bytes written to the FIFO from memory at a time */
        DMA_SxCR_MBURST_INCR4 |
        /* 8 bit transfers from USART peripheral. */
        DMA_SxCR_PSIZE_8BIT |
        /* and to memory. */
        DMA_SxCR_MSIZE_8BIT |
        /* TODO: what priority level is necessary? */
        /* Very high 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);

    /* For now, don't transfer any number of datas
     * (will be set in the initiating function). */
    DMA_SNDTR(dma, stream) = 0;

    /* DMA into the USART data register... */
    DMA_SPAR(dma, stream) = &USART_DR(usart);
    /* ...from the TX buffer. */
    DMA_SM0AR(dma, stream) = s->buff;

    /* TODO: Investigate more about the best FIFO settings. */
    DMA_SFCR(dma, stream) =
        DMA_SxFCR_DMDIS |         /* Enable DMA stream FIFO. */
        DMA_SxFCR_FTH_2_4_FULL |  /* Trigger level 2/4 full. */
        DMA_SxFCR_FEIE;           /* Enable FIFO error interrupt. */

    s->wr = s->rd = 0;  /* Buffer is empty to begin with. */

    /* Enable DMA interrupts for this stream with the NVIC. */
    if (dma == DMA1)
        nvicEnableVector(dma_irq_lookup[0][stream],
                         CORTEX_PRIORITY_MASK(USART_DMA_ISR_PRIORITY));
    else if (dma == DMA2)
        nvicEnableVector(dma_irq_lookup[1][stream],
                         CORTEX_PRIORITY_MASK(USART_DMA_ISR_PRIORITY));
}
Esempio n. 14
0
void dma_set_number_of_data(u32 dma, u8 stream, u16 number)
{
	DMA_SNDTR(dma, stream) = number;
}
Esempio n. 15
0
/*******************************************************************************
 * int bsp_uart_dma_init(u32 iuart, u32 baud, u32 rxbuffsize, u32 txbuffsize, u32 dmastreamrx, u32 dmastreamtx, u32 dma_tx_int_priority);
 * @brief	: Initialize USART/UART for DMA transfers
 * @param	: iuart: pointer to UART base, e.g. 'USART1'
 * @param	: baud: name says it all, e.g. '921600'
 * @param	: rxbuffsize: number of bytes in a circular tx buffer
 * @param	: txbuffsize" number of bytes in a circular rx buffer
 * @param	: dmastreamrx: DMA stream number for RX (0 - 7)
 * @param	: dmastreamtx: DMA stream number for TX (0 - 7)
 * @param	: dma_tx_int_priority: interrupt priority, (0x00 - 0xf0) e.g. 0xc0, low 4 bits zero
 * @return	: 0 = success; fail traps to 'panic_leds'
*******************************************************************************/
int bsp_uart_dma_init(u32 iuart, u32 baud, u32 rxbuffsize, u32 txbuffsize, u32 dmastreamrx, u32 dmastreamtx, u32 dma_tx_int_priority)
{
	u32 cb_Idx;	// Used "everywhere" to index into the control block array

	int tmp;
	struct UARTPINS uartpins;

	struct IRQNUM dma_irq_number_tx;
	struct IRQNUM dma_irq_number_rx;
	u32 dma_x;

	u32 dma_channel_number_rx = 4;	// Initialize to prevent compiler warning
	u32 dma_channel_number_tx = 5;	


	/* Be sure arguments passed are within range */
	if (dmastreamrx > 7) bsp_panic(-1);
	if (dmastreamtx > 7) bsp_panic(-2);
	if ((dma_tx_int_priority & 0xffffff0f) != 0) bsp_panic(-3); // Bogus priority
	
	cb_Idx = mapindex(iuart);	// Map usart/uart register base to control block index

	/* Convert dma stream to dma base and irq number */
	dma_irq_number_tx = irq_given_datastream(iuart, dmastreamtx); // TX
	dma_irq_number_rx = irq_given_datastream(iuart, dmastreamrx); // RX
	
	/* The DMA determined should be the same...mostly a debugging issue. */
	if (dma_irq_number_tx.dma != dma_irq_number_rx.dma) bsp_panic(-333);
	dma_x = dma_irq_number_tx.dma;	// Lazy way of dealing with it later

	/* Set dma stream interrupt to revector to this routine; check if dma is in use. */
	tmp = nvic_dma_stream_vector_add( (void(*)(u32*))&DMA_UART_IRQHandler, (u32*)&cb_uart[cb_Idx], dma_irq_number_tx.num, dmastreamtx);
	if (tmp != 0) bsp_panic(-30 + tmp);

	/* RX doesn't interrupt, but we need to show that the stream has been taken */
	tmp = nvic_dma_stream_vector_add( (void(*)(u32*))&DMA_UART_IRQHandler, (u32*)&cb_uart[cb_Idx], dma_irq_number_rx.num, dmastreamrx);
	if (tmp != 0) bsp_panic(-130 + tmp);


	/* Load some parameters that might be important. */
	cb_uart[cb_Idx].idma = dma_x;	// Save dma register base address
	cb_uart[cb_Idx].rxdma_stream = dmastreamrx; // Save stream number
	cb_uart[cb_Idx].txdma_stream = dmastreamtx; // Save stream number
	cb_uart[cb_Idx].iuart = iuart;	// Save uart register base address
	cb_uart[cb_Idx].flag = 2;	// Show this setup for dma driven

	/* Find DMA channel numbers for RX and TX, given stream number */
	switch (dma_x)
	{
	case DMA1_BASE:
		if (dma1_rxstreamtbl_4[dmastreamrx & 0x7] == iuart) {dma_channel_number_rx = 4; break;}
		if (dma1_rxstreamtbl_5[dmastreamrx & 0x7] == iuart) {dma_channel_number_rx = 5; break;}
		bsp_panic(-6);	// RX stream specified is not compatible with UART/DMA1

	case DMA2_BASE:
		if (dma2_rxstreamtbl_4[dmastreamrx & 0x7] == iuart) {dma_channel_number_rx = 4; break;}
		if (dma2_rxstreamtbl_5[dmastreamrx & 0x7] == iuart) {dma_channel_number_rx = 5; break;}
		bsp_panic(-7);	// RX stream specified is not compatible with UART/DMA2
	default:
		bsp_panic(-8);	// Something seriously wrong here!

	}

	switch (dma_x)
	{
	case DMA1_BASE:
		if (dma1_txstreamtbl_4[dmastreamtx & 0x7] == iuart) {dma_channel_number_tx = 4; break;}
		if (dma1_txstreamtbl_5[dmastreamtx & 0x7] == iuart) {dma_channel_number_tx = 5; break;}
		if (dma1_txstreamtbl_7[dmastreamtx & 0x7] == iuart) {dma_channel_number_tx = 7; break;}
		bsp_panic(-9);	// TX stream specified is not compatible with UART/DMA1

	case DMA2_BASE:
		if (dma2_txstreamtbl_4[dmastreamtx & 0x7] == iuart) {dma_channel_number_tx = 4; break;}
		if (dma2_txstreamtbl_5[dmastreamtx & 0x7] == iuart) {dma_channel_number_tx = 5; break;}
		bsp_panic(-10);	// TX stream specified is not compatible with UART/DMA2
	default:
		bsp_panic(-11);	// Something seriously wrong here!

	}
static u32 qqq;
	qqq = dma_channel_number_rx;
/* At this point we (should!) have a good DMA channel and stream that associates with the UART. */

	/* Set up UART pins, port & uart clockings.  THIS IS BOARD SPECIFIC */
	if (uart_pins(iuart, &uartpins) != 0) bsp_panic(-15);

	/* Setup baud rate */
	usartx_setbaud (iuart, uartpins.pclk, baud);

	/* Obtain some buffer space */
	getbuff(cb_Idx, rxbuffsize, txbuffsize);

	/* ---------- Set up UART ----------------------------------------------------------------------------------- */

	/* Set up CR1 ---------------------------------------------------- */
	USART_CR1(iuart) |= (1<<13) | (1<<3) | (1<<2);// Set Usart enable, tx enable, rx enable

	/* Hook up usart tx and rx to dma channels */
	USART_CR3(iuart) |= (1<<7) | (1<<6);


	/* Setup CR2 ------------------------------------------------------------------- */
	/* After reset CR2 is 0x0000 and this is just fine */

	/* --------- Set up the DMA channels ------------------------------------------------------------------------ */

	/* Set peripheral address for RX */
	DMA_SPAR(dma_x,dmastreamrx) = (u32*)(iuart + 0x04); // Address of uart DR register

	/* Set peripheral address for TX */
	DMA_SPAR(dma_x,dmastreamtx) = (u32*)(iuart + 0x04); // Address of uart DR register

	/* DMA stream configuration register--RX p 325 */
	//                                       Channel number     | MINC    | CIRC   | Per->Mem 
	DMA_SCR(dma_x,dmastreamrx) = ( (dma_channel_number_rx<< 25) | (1<<10) | (1<<8) | (0x0<<6) );   

	/* DMA stream configuration register--TX */
	//                                       Channel number     | MINC    | CIRC   | Mem->per | priority
	DMA_SCR(dma_x,dmastreamtx) = ( (dma_channel_number_tx<< 25) | (1<<10) | (0<<8) | (0x1<<6) | (1<<16));

	/* Set RX memory address (stays forever) */
	DMA_SM0AR(dma_x,dmastreamrx) = cb_uart[cb_Idx].rxbuff_base;

	/* Set the number of bytes in the RX buff */
	DMA_SNDTR(dma_x,dmastreamrx) = cb_uart[cb_Idx].rxbuff_size;

	/* DMA for TX interrupts */
	NVICIPR (dma_irq_number_tx.num,dma_tx_int_priority);	// Set dma interrupt priority (tx)
	NVICISER(dma_irq_number_tx.num);			// Enable dma interrupt (tx)

	/* Final enabling of DMA */
	DMA_SCR(dma_x,dmastreamrx) |= (0x1);		// Enable rx stream
	DMA_SCR(dma_x,dmastreamtx) |= ((1<<4));	// TCIE (xfer complete interrupt), not enable stream

	return 0;	// SUCCESS!
}