/*
 *      Author: alexrayne <alexraynepe196@gmail.com>
  ------------------------------------------------------------------------
    Copyright (c) alexrayne

   All rights reserved.
   Redistribution and use in source and binary forms, with or without
   modification, are permitted provided that the following conditions are met:
   - Redistributions of source code must retain the above copyright
     notice, this list of conditions and the following disclaimer.
   - Redistributions in binary form must reproduce the above copyright
     notice, this list of conditions and the following disclaimer in the
     documentation and/or other materials provided with the distribution.
   - Neither the name of ARM nor the names of its contributors may be used
     to endorse or promote products derived from this software without
     specific prior written permission.
   *
   THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
   AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
   LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   POSSIBILITY OF SUCH DAMAGE. *
*/
#include "uart_device.h"
#include "gpio.h"
#include "hw.h"
#include <os_isr.h>



//---------------------------------------------------------------------------
// готовые структуры для конфигурации UART_BUF_16C650
const USART_InitTypeDef USART_1152008N1 = {
      struct_field(USART_BaudRate)      115200
    , struct_field(USART_WordLength)    UART_WordLength8b
    , struct_field(USART_StopBits)      UART_StopBits1
    , struct_field(USART_Parity)        UART_Parity_No
    , struct_field(UART_FIFOMode)       UART_FIFO_ON
    , struct_field(USART_HardwareFlowControl) UART_HardwareFlowControl_RXE | UART_HardwareFlowControl_TXE
};


const
NVIC_InitTypeDef    USART1_NVIC = {
      struct_field(NVIC_IRQChannel)                     USART1_IRQn
    , struct_field(NVIC_IRQChannelPreemptionPriority)   IRQPRIO(IRQP_SERIAL)
    , struct_field(NVIC_IRQChannelSubPriority)          IRQPRIO(IRQP_SERIAL)
    , struct_field(NVIC_IRQChannelCmd)                  ENABLE
};

const
UART_BUF_16C650::DEV_INIT USART1BBuf_init = {
    USART1,
    (USART_InitTypeDef*) &USART_1152008N1,
    (NVIC_InitTypeDef *) &USART1_NVIC,

    struct_field(RCC_Perifery)  (RST_CLK_PCLK_UART1 | RST_CLK_PCLK_PORTB)

    , struct_field(GPIOPINS)    &UART1B_GPIO

//    , struct_field(rx_dma)      &USART1rx_dma_init
//    , struct_field(tx_dma)      &USART1tx_dma_init
};


const
UART_BUF_16C650::DEV_INIT USART1ABuf_init = {
    USART1,
    (USART_InitTypeDef*) &USART_1152008N1,
    (NVIC_InitTypeDef *) &USART1_NVIC,

    struct_field(RCC_Perifery)  (RST_CLK_PCLK_UART1 | RST_CLK_PCLK_PORTA)

    , struct_field(GPIOPINS)    &UART1A_GPIO

//    , struct_field(rx_dma)      &USART1rx_dma_init
//    , struct_field(tx_dma)      &USART1tx_dma_init
};

const
UART_BUF_16C650::DEV_INIT USART1DBuf_init = {
    USART1,
    (USART_InitTypeDef*) &USART_1152008N1,
    (NVIC_InitTypeDef *) &USART1_NVIC,

    struct_field(RCC_Perifery)  (RST_CLK_PCLK_UART1 | RST_CLK_PCLK_PORTD)

    , struct_field(GPIOPINS)    &UART1D_GPIO

//    , struct_field(rx_dma)      &USART1rx_dma_init
//    , struct_field(tx_dma)      &USART1tx_dma_init
};

const
UART_BUF_16C650::DEV_INIT USART1EBuf_init = {
    USART1,
    (USART_InitTypeDef*) &USART_1152008N1,
    (NVIC_InitTypeDef *) &USART1_NVIC,

    struct_field(RCC_Perifery)  (RST_CLK_PCLK_UART1 | RST_CLK_PCLK_PORTE)

    , struct_field(GPIOPINS)    &UART1E_GPIO

//    , struct_field(rx_dma)      &USART1rx_dma_init
//    , struct_field(tx_dma)      &USART1tx_dma_init
};



const
NVIC_InitTypeDef    USART2_NVIC = {
      struct_field(NVIC_IRQChannel)                     USART2_IRQn
    , struct_field(NVIC_IRQChannelPreemptionPriority)   IRQPRIO(IRQP_SERIAL)
    , struct_field(NVIC_IRQChannelSubPriority)          IRQPRIO(IRQP_SERIAL)
    , struct_field(NVIC_IRQChannelCmd)                  ENABLE
};



const
UART_BUF_16C650::DEV_INIT USART2DBuf_init = {
    USART2,
    (USART_InitTypeDef*) &USART_1152008N1,
    (NVIC_InitTypeDef *) &USART2_NVIC,

    struct_field(RCC_Perifery)  (RST_CLK_PCLK_UART2 | RST_CLK_PCLK_PORTD)

    , struct_field(GPIOPINS)    &UART2D_GPIO

//    , struct_field(rx_dma)      &USART1rx_dma_init
//    , struct_field(tx_dma)      &USART1tx_dma_init
};

const
UART_BUF_16C650::DEV_INIT USART2FBuf_init = {
    USART2,
    (USART_InitTypeDef*) &USART_1152008N1,
    (NVIC_InitTypeDef *) &USART2_NVIC,

    struct_field(RCC_Perifery)  (RST_CLK_PCLK_UART2 | RST_CLK_PCLK_PORTF)

    , struct_field(GPIOPINS)    &UART2F_GPIO

    // usart2 rx stream conflicts vs dac1, not use it!
//    , struct_field(rx_dma)      (UART_BUF_16C650::DMA_INIT*) NULL
//    , struct_field(tx_dma)      &USART2tx_dma_init
};





//-----------------------           UART_BUFDevice         -----------------------

UART_BUF_16C650::UART_BUF_16C650()
: inherited()
, USARTx(NULL)
, init_state(NULL)
{
  init();
}

UART_BUF_16C650::UART_BUF_16C650(const UART_BUF_16C650::DEV_INIT& usart_init)
{
  init(usart_init);
}


void UART_BUF_16C650::init(const UART_BUF_16C650::DEV_INIT& usart_init){

    init();
    this->init_state = &usart_init;
    USARTx = (USART_io*)init_state->USARTx;

    /* Enable GPIO clock */
    /* Enable USART clock */
    RST_CLK_PCLKcmd(this->init_state->RCC_Perifery , ENABLE);

    if(init_state->GPIOPINS)
        gpio_conf_func(init_state->GPIOPINS);

    /* USARTx configuration*/
    UART_BRGInit(USARTx, UART_HCLKdiv1);
    USART_Init(USARTx, (USART_InitTypeDef*)this->init_state->USART_InitStructure);

    if (init_state->USART_InitStructure->UART_FIFOMode == UART_FIFO_ON){
        // if FIFO used, make it large
        //  USARTx->IFLS = (UART_IT_FIFO_LVL_8words << 3) | UART_IT_FIFO_LVL_2words;
        UART_DMAConfig(USARTx, UART_IT_FIFO_LVL_8words, UART_IT_FIFO_LVL_2words);
    }

    /* Enable the USARTx Interrupt */
    if(this->init_state->NVIC_InitStructure)
        NVIC_Init((NVIC_InitTypeDef*)this->init_state->NVIC_InitStructure);

    /* Enable the USART Transmit interrupt: this interrupt is generated when the
     USART transmit data register is empty */
    //USART_ITConfig(this->init_state.USARTx, USART_IT_TXE, ENABLE);

    //  всегда активно прерывание по заполнению ФИФО и таймауту на прием 4х символов
    USART_ITConfig(USARTx, UART_IT_RX | UART_IT_RT, ENABLE);

    /* Enable USART */
    USART_Cmd(USARTx, ENABLE);

    setConnected(true);
}

// переключение УАРТ на соответствующие пины
void UART_BUF_16C650::connect_gpio(const DEV_INIT& usart_init){ //const GPIOFUNC_INIT*  GPIOPINS
    if(init_state->GPIOPINS == NULL)
        return;

    setConnected(false);
    USART_Cmd(USARTx, DISABLE);
    if (init_state->GPIOPINS != usart_init.GPIOPINS) {
        gpio_conf_pin(init_state->GPIOPINS);
    }
    init_state = &usart_init;
    gpio_set_func(init_state->GPIOPINS);
    USART_Cmd(USARTx, ENABLE);
    setConnected(true);

}

void UART_BUF_16C650::deinit(void){
  USART_Cmd(USARTx, DISABLE);
  if(init_state->GPIOPINS){
    gpio_conf_pin(init_state->GPIOPINS);
  }
}

int UART_BUF_16C650::SendData(const void *data, const u32 data_size) {
    if(USARTx == 0 || !connected) {
        return -1;
    }

    int result = 0;
    if (data_size > 0)
        result = tx.WriteData_len(data, data_size);
    EnterCS();
    if (!tx.isEmpty()){
        if (!tx_send_full())
            tx_empty.give();
    }
    ExitCS();

    return result;
}

int UART_BUF_16C650::send_char(int x) {
  EnterCS();
  bool was_empty = tx.isEmpty();
  int res = tx.push_char(x);
  if (was_empty){
      if (!tx_send_full())
          tx_empty.give();
  }
  ExitCS();
  return res;
}



void UART_BUF_16C650::IRQ(){
    USART_io*  io = USARTx;
    uint32_t mis = io->MIS;
    IRQrx();
    IRQtx();

    if ((mis & UART_MIS_RTMIS) != 0){
        // случился таймаут приема. поэтому просигналю ожидающим приема.
        rx_avail.give_isr();
    }

    io->ICR = mis;
}

void UART_BUF_16C650::IRQrx(){
    int ch = 0;
    USART_io*  io = USARTx;
    bool was_empty = rx.isEmpty();

    // RX have some chars
    while(( io->FR & UART_FLAG_RXFE) == 0){
        ch = USART_ReceiveData(USARTx);
        //u32 isf = EnterCS_ISR();
        if (rx.push_char(ch) > 0)
            {;}
        else
            on_rx_over(ch);
        //ExitCS_ISR(isf);
        if (was_empty)
            rx_sigcount = 0;
        if (rx_sigcount > 0)
            rx_sigcount--;
    }
    if (rx_sigcount <= 0) {
      rx_avail.give_isr();
      rx_sigcount = rx_sig_force_to;
    }
}

void UART_BUF_16C650::IRQtx(){
    USART_io*  io = USARTx;
    bool enabled =  (io->IMSC & UART_IT_TX) != 0;
    if (!tx_send_full())
        tx_empty.give_isr();
}

// \return true - IRQ enabled
bool UART_BUF_16C650::tx_send_full(){
    USART_io*  io = USARTx;
    int ch = 0;
    while (!tx.isEmpty() && ( io->FR & UART_FLAG_TXFF) == 0){
        ch = tx.pop_char();
        if(ch >= 0){
            USART_SendData(io, (uint16_t)ch);
        }
    }
    if (tx.isEmpty()){
        //UART_ITConfig(io, UART_IT_TX, DISABLE);
        io->IMSC &= ~UART_IT_TX;
        return false;
    }
    else{
        //UART_ITConfig(io, UART_IT_TX, ENABLE);
        io->IMSC |= UART_IT_TX;
        return true;
    }
}



//  use wait_fast()
#include <system.h>

//  invokes wait until tx is done and inactive
//virtual
UART_BUF_16C650::WaitResult UART_BUF_16C650::tx_wait(){
    if (tx_busy()){
        wait_fast();
        return 0;
    }
    if (!tx.isEmpty())
    {
        // чтото пошло не так - передатчик ничего не шлет, а буфер ждет отправки
        EnterCS();
        if (!tx.isEmpty()){
            if (!tx_send_full())
                tx_empty.give();
        }
        ExitCS();
    }
    return 1;
}


/*
//------------------     UART_DMADevice          -----------------------
void UART_DMADevice::init(const UART_DMADevice::DEVDMA_INIT& usart_init)
{
    inherited::init(*((inherited::DEV_INIT)&usart_init));

    if (init_state()->rx_dma != NULL){
        init_rx(*(init_state()->rx_dma));
    }
    if (init_state()->tx_dma != NULL){
        init_tx(*(init_state()->tx_dma));
    }
}

void UART_DMADevice::init_rx(const DMA_INIT& hdma){
    RCC_AHB1PeriphClockCmd(hdma.rcc, ENABLE);

    dmarx_stop();
    rx.Clear();
    dma_rx = hdma.stream;

    DMA_InitTypeDef DMA_INIT;
    DMA_INIT.DMA_Channel            = hdma.ch; //DMA_Channel_7;
    DMA_INIT.DMA_PeripheralBaseAddr = (uint32_t)(&(USARTx->DR));
    DMA_INIT.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    DMA_INIT.DMA_MemoryDataSize     = DMA_MemoryDataSize_Byte;
  DMA_INIT.DMA_Memory0BaseAddr    = (uint32_t)(rx.Store());
  DMA_INIT.DMA_DIR                = DMA_DIR_PeripheralToMemory;
  DMA_INIT.DMA_BufferSize         = rx.StoreSize();
  DMA_INIT.DMA_PeripheralInc      = DMA_PeripheralInc_Disable;
  DMA_INIT.DMA_MemoryInc          = DMA_MemoryInc_Enable;
  DMA_INIT.DMA_Mode               = DMA_Mode_Normal;
  DMA_INIT.DMA_Priority           = DMA_Priority_High;
  DMA_INIT.DMA_FIFOMode           = DMA_FIFOMode_Disable;
  DMA_INIT.DMA_FIFOThreshold      = DMA_FIFOThreshold_HalfFull;
  DMA_INIT.DMA_MemoryBurst        = DMA_MemoryBurst_Single;
  DMA_INIT.DMA_PeripheralBurst    = DMA_PeripheralBurst_Single;
  DMA_Init(hdma.stream, &DMA_INIT);

  DMA_ITConfig(hdma.stream, DMA_IT_TC | DMA_IT_HT, ENABLE);
  //DMA_ITConfig(DAC_DMA_STREAM, DMA_IT_HT, ENABLE);

  DMA_DoubleBufferModeConfig(hdma.stream, (uint32_t)(rx.Store()), DMA_Memory_0 );
  DMA_DoubleBufferModeCmd(hdma.stream, ENABLE);

    // disable usart rx irq, since DMA handles receiving
    USART_ITConfig(USARTx, USART_IT_RXNE, DISABLE);

// Enable the DMA Interrupt
    NVIC_InitTypeDef NVIC_InitStructure;

    NVIC_InitStructure.NVIC_IRQChannel = hdma.IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = IRQPRIO(hdma.prio); //10
    NVIC_InitStructure.NVIC_IRQChannelSubPriority        = IRQPRIO(hdma.prio); //5
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    DMA_Cmd(hdma.stream, ENABLE);
    USART_DMACmd(USARTx, USART_DMAReq_Rx, ENABLE);

}


UART_DMADevice::UART_DMADevice()
: inherited()
, dma_tx_len(0)
, dma_tx_tcif(0)
{
    dma_rx  = NULL;
    dma_tx  = NULL;
}

UART_DMADevice::UART_DMADevice(const UART_DMADevice::DEV_INIT& usart_init)
:inherited(usart_init)
, dma_tx_len(0)
, dma_tx_tcif(0)
{
    dma_rx  = NULL;
    dma_tx  = NULL;
};

UART_DMADevice::~UART_DMADevice(){
    dma_stop();
}

void UART_DMADevice::deinit(void){
    inherited::deinit();
    dma_stop();
}

void UART_DMADevice::dmarx_stop(){
    if (dma_rx == NULL)
        return;
    DMA_ITConfig(dma_rx, DMA_IT_TC | DMA_IT_HT, DISABLE);
    USART_DMACmd(USARTx, USART_DMAReq_Rx, DISABLE);
}

void UART_DMADevice::init_tx(const DMA_INIT& hdma){
    RCC_AHB1PeriphClockCmd(hdma.rcc, ENABLE);

    dmatx_stop();
    dma_tx = hdma.stream;
    dma_tx_len = 0;
    dma_tx_tcif = hdma.tcif;

    DMA_InitTypeDef DMA_INIT;
    DMA_INIT.DMA_Channel            = hdma.ch;
    DMA_INIT.DMA_PeripheralBaseAddr = (uint32_t)(&(USARTx->DR));
    DMA_INIT.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
    DMA_INIT.DMA_MemoryDataSize     = DMA_MemoryDataSize_Byte;
  DMA_INIT.DMA_Memory0BaseAddr    = (uint32_t)(rx.Store());
  DMA_INIT.DMA_DIR                = DMA_DIR_MemoryToPeripheral;
  DMA_INIT.DMA_BufferSize         = tx.StoreSize();
  DMA_INIT.DMA_PeripheralInc      = DMA_PeripheralInc_Disable;
  DMA_INIT.DMA_MemoryInc          = DMA_MemoryInc_Enable;
  DMA_INIT.DMA_Mode               = DMA_Mode_Normal;
  DMA_INIT.DMA_Priority           = DMA_Priority_High;
  DMA_INIT.DMA_FIFOMode           = DMA_FIFOMode_Disable;
  DMA_INIT.DMA_FIFOThreshold      = DMA_FIFOThreshold_HalfFull;
  DMA_INIT.DMA_MemoryBurst        = DMA_MemoryBurst_Single;
  DMA_INIT.DMA_PeripheralBurst    = DMA_PeripheralBurst_Single;
  DMA_Init(hdma.stream, &DMA_INIT);

    // disable usart rx irq, since DMA handles receiving
    //USART_ITConfig(init_state.USARTx, USART_IT_TXE, DISABLE);

// Enable the DMA Interrupt
    NVIC_InitTypeDef NVIC_InitStructure;

    NVIC_InitStructure.NVIC_IRQChannel = hdma.IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = IRQPRIO(hdma.prio); //10
    NVIC_InitStructure.NVIC_IRQChannelSubPriority        = IRQPRIO(hdma.prio); //5
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

}

void UART_DMADevice::dmatx_start(uint32_t src, unsigned size){
    dma_tx->M0AR = src;
    dma_tx->NDTR = size;
    dma_tx_len   = size;
    DMA_ITConfig(dma_tx, DMA_IT_TC, ENABLE);
    USART_DMACmd(USARTx, USART_DMAReq_Tx, ENABLE);
    DMA_Cmd(dma_tx, ENABLE);
}

void UART_DMADevice::dmatx_stop(){
    if (dma_tx == NULL)
        return;
    DMA_ITConfig(dma_tx, DMA_IT_TC | DMA_IT_HT, DISABLE);
    USART_DMACmd(USARTx, USART_DMAReq_Tx, DISABLE);
}

void UART_DMADevice::dma_stop(){
    dmarx_stop();
    dmatx_stop();
}



bool UART_DMADevice::dmarx_poll(){
    if (dma_rx == NULL)
        return false;
    DMA_ClearITPendingBit(dma_rx, init_state->rx_dma->tcif);
    unsigned rx_free = DMA_GetCurrDataCounter(dma_rx);
    u8* pdma = rx.Store() + (rx.StoreSize() - rx_free);
    bool changes = ( pdma != rx.FreeBuf());
    if (changes)
        rx.FreeBufAssign( pdma );
    return changes;
}

//  вызов dmarx_poll вне контекста прерывания
bool UART_DMADevice::dmarx_online_poll(){
    if (dma_rx == NULL)
        return false;
    EnterCS();
    bool change = dmarx_poll();
    ExitCS();
    return change;
}

//virtual
bool UART_DMADevice::rx_wait(unsigned to){
    bool ok = rx_avail.take(to);
    dmarx_online_poll();
    return ok;
}

bool UART_DMADevice::dmatx_poll(){
    if (dma_tx == NULL)
        return false;
    FlagStatus txstat = DMA_GetITStatus(dma_tx, dma_tx_tcif);
    DMA_ClearITPendingBit(dma_tx, init_state->tx_dma->tcif);
    if ((txstat & DMA_IT_TC) == 0)
        return false;
    //if (DMA_GetCurrDataCounter(dma_tx) != 0)
    //    return true;
    tx.DeleteData(dma_tx_len);
    dma_tx_len = 0;
    if (tx.isEmpty()){
        dmatx_stop();
        return true;
    }
    dma_tx_len = tx.DataBufSize();
    dma_tx_len = dma_tx_limit( dma_tx_len );
    dmatx_start((uintptr_t)tx.DataBuf(), dma_tx_len);
    return true;
}


void UART_DMADevice::IRQ(){
    IRQrx();
    IRQtx();
}

void UART_DMADevice::IRQrx(){
    int ch = 0;

    if (dma_rx != NULL){
        if (dmarx_poll()){
            rx_avail.give_isr();
        }
        return;
    }

    if(USART_GetITStatus(USARTx, USART_IT_RXNE) != RESET){
        ch = USART_ReceiveData(USARTx);
        //u32 isf = EnterCS_ISR();
        bool was_empty = rx.isEmpty();
        rx.push_char(ch);
        //ExitCS_ISR(isf);
        rx_sigcount--;
        if ((was_empty) || (rx_sigcount <= 0)) {
          rx_avail.give_isr();
          rx_sigcount = rx_sig_force_to;
        }
    }
}

void UART_DMADevice::IRQtx(){
    int ch = 0;
    if (dma_tx != NULL){
        if (dmatx_poll()){
            if (tx.isEmpty()){
                tx_empty.give_isr();
            }
        }
        //return;
    }

    if(USART_GetITStatus(USARTx, USART_IT_TXE) != RESET){
        // u32 isf = EnterCS_ISR();
        ch = tx.pop_char();
        //ExitCS_ISR(isf);
        if(ch >= 0){
            //ch = 'A';
            USART_SendData(USARTx, (uint16_t)ch);
        }
        if (tx.isEmpty()){
          USART_ITConfig(USARTx, USART_IT_TXE, DISABLE);
          tx_empty.give_isr();
        }
    }
    else {
      if (!tx.isEmpty())
      if ( USART_GetFlagStatus(USARTx, USART_FLAG_TXE) != RESET )
        // неавозможно?
      if ( USART_GetITStatus(USARTx, USART_IT_TXE) == RESET)
      {
        //u32 isf = EnterCS_ISR();
        ch = tx.pop_char();
        //ExitCS_ISR(isf);
        if(ch >= 0){
          USART_SendData(USARTx, (uint16_t)ch);
          USART_ITConfig(USARTx, USART_IT_TXE, ENABLE);
        }
      }
    }
}

const
UART_BUF_16C650::DMA_INIT USART1rx_dma_init = {
        DMA2_Stream5, RCC_AHB1Periph_DMA2, DMA_Channel_4
        , DMA_IT_TCIF5 | DMA_IT_HTIF5
        , DMA2_Stream5_IRQn, IRQP_SERIAL
};

const
UART_BUF_16C650::DMA_INIT USART1tx_dma_init = {
          DMA2_Stream7, RCC_AHB1Periph_DMA2, DMA_Channel_4
        , DMA_IT_TCIF7
        , DMA2_Stream7_IRQn, IRQP_SERIAL
};

const
UART_BUF_16C650::DMA_INIT USART2tx_dma_init = {
          DMA1_Stream6, RCC_AHB1Periph_DMA1, DMA_Channel_4
        , DMA_IT_TCIF6
        , DMA1_Stream6_IRQn, IRQP_SERIAL
};

*/


