搜索
bottom↓
回复: 19

RTT 3.1 中 设置 uart2 发送为DMA方式 的问题!

[复制链接]

出0入0汤圆

发表于 2010-10-12 14:43:58 | 显示全部楼层 |阅读模式
我把USART2设置成 DMA发送方式
用一个线程执行 rt_kprintf   这个线程就卡死了 发不出任何数据(注:不改动,使用原来的 polling 方式 是没有问题的 )

是否我设置有问题

file--usart.c:

/*
* File      : usart.c
* This file is part of RT-Thread RTOS
* COPYRIGHT (C) 2009, RT-Thread Development Team
*
* The license and distribution terms for this file may be
* found in the file LICENSE in this distribution or at
* http://www.rt-thread.org/license/LICENSE
*
* Change Logs:
* Date           Author       Notes
* 2009-01-05     Bernard      the first version
* 2010-03-29     Bernard      remove interrupt Tx and DMA Rx mode
*/

#include "usart.h"
#include <serial.h>
#include <stm32f10x_dma.h>

/*
* Use UART1 as console output and finsh input
* interrupt Rx and poll Tx (stream mode)
*
* Use UART2 with interrupt Rx and poll Tx
* Use UART3 with DMA Tx and interrupt Rx -- DMA channel 2
*
* USART DMA setting on STM32
* USART1 Tx --> DMA Channel 4
* USART1 Rx --> DMA Channel 5
* USART2 Tx --> DMA Channel 7
* USART2 Rx --> DMA Channel 6
* USART3 Tx --> DMA Channel 2
* USART3 Rx --> DMA Channel 3
*/

#ifdef RT_USING_UART1
struct stm32_serial_int_rx uart1_int_rx;
struct stm32_serial_device uart1 =
{
        USART1,
        &uart1_int_rx,
        RT_NULL
};
struct rt_device uart1_device;
#endif

#ifdef RT_USING_UART2
struct stm32_serial_int_rx uart2_int_rx;
struct stm32_serial_dma_tx uart2_dma_tx; //------------ 改动处1  增加此行
struct stm32_serial_device uart2 =
{
        USART2,
        &uart2_int_rx,
        &uart2_dma_tx     //------------ 改动处2   RT_NULL -->&uart2_dma_tx
};
struct rt_device uart2_device;
#endif

#ifdef RT_USING_UART3
struct stm32_serial_int_rx uart3_int_rx;
struct stm32_serial_dma_tx uart3_dma_tx;
struct stm32_serial_device uart3 =
{
        USART3,
        &uart3_int_rx,
        &uart3_dma_tx
};
struct rt_device uart3_device;
#endif

#define USART1_DR_Base  0x40013804
#define USART2_DR_Base  0x40004404
#define USART3_DR_Base  0x40004804

/* USART1_REMAP = 0 */
#define UART1_GPIO_TX                GPIO_Pin_9
#define UART1_GPIO_RX                GPIO_Pin_10
#define UART1_GPIO                        GPIOA
#define RCC_APBPeriph_UART1        RCC_APB2Periph_USART1
#define UART1_TX_DMA                DMA1_Channel4
#define UART1_RX_DMA                DMA1_Channel5



#if defined(STM32F10X_LD) || defined(STM32F10X_MD) || defined(STM32F10X_CL)
    #define UART2_GPIO_TX            GPIO_Pin_5
    #define UART2_GPIO_RX            GPIO_Pin_6
    #define UART2_GPIO                    GPIOD
    #define RCC_APBPeriph_UART2        RCC_APB1Periph_USART2
#else /* for STM32F10X_HD */
/* USART2_REMAP = 0 */
    #define UART2_GPIO_TX                GPIO_Pin_2
    #define UART2_GPIO_RX                GPIO_Pin_3
    #define UART2_GPIO                        GPIOA
    #define RCC_APBPeriph_UART2        RCC_APB1Periph_USART2
    #define UART2_TX_DMA                DMA1_Channel7
    #define UART2_RX_DMA                DMA1_Channel6
#endif


/* USART3_REMAP[1:0] = 00 */
#define UART3_GPIO_RX                GPIO_Pin_11
#define UART3_GPIO_TX                GPIO_Pin_10
#define UART3_GPIO                        GPIOB
#define RCC_APBPeriph_UART3        RCC_APB1Periph_USART3
#define UART3_TX_DMA                DMA1_Channel2
#define UART3_RX_DMA                DMA1_Channel3


static void RCC_Configuration(void)
{
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);

#ifdef RT_USING_UART1
        /* Enable USART1 and GPIOA clocks */
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);
#endif

#ifdef RT_USING_UART2

#if (defined(STM32F10X_LD) || defined(STM32F10X_MD) || defined(STM32F10X_CL))
    /* Enable AFIO and GPIOD clock */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOD, ENABLE);

    /* Enable the USART2 Pins Software Remapping */
    GPIO_PinRemapConfig(GPIO_Remap_USART2, ENABLE);

#else
    /* Enable AFIO and GPIOA clock */
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA, ENABLE);
   
    /* DMA clock enable */
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE); //------------ 改动处3   增加此行
#endif

        /* Enable USART2 clock */
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);
#endif

#ifdef RT_USING_UART3
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);
        /* Enable USART3 clock */
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);

        /* DMA clock enable */
        RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);
#endif
}

static void GPIO_Configuration(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;

#ifdef RT_USING_UART1
        /* Configure USART1 Rx (PA.10) as input floating */
        GPIO_InitStructure.GPIO_Pin = UART1_GPIO_RX;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        GPIO_Init(UART1_GPIO, &GPIO_InitStructure);

        /* Configure USART1 Tx (PA.09) as alternate function push-pull */
        GPIO_InitStructure.GPIO_Pin = UART1_GPIO_TX;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_Init(UART1_GPIO, &GPIO_InitStructure);
#endif

#ifdef RT_USING_UART2
        /* Configure USART2 Rx as input floating */
        GPIO_InitStructure.GPIO_Pin = UART2_GPIO_RX;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        GPIO_Init(UART2_GPIO, &GPIO_InitStructure);

        /* Configure USART2 Tx as alternate function push-pull */
        GPIO_InitStructure.GPIO_Pin = UART2_GPIO_TX;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(UART2_GPIO, &GPIO_InitStructure);
#endif

#ifdef RT_USING_UART3
        /* Configure USART3 Rx as input floating */
        GPIO_InitStructure.GPIO_Pin = UART3_GPIO_RX;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        GPIO_Init(UART3_GPIO, &GPIO_InitStructure);

        /* Configure USART3 Tx as alternate function push-pull */
        GPIO_InitStructure.GPIO_Pin = UART3_GPIO_TX;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(UART3_GPIO, &GPIO_InitStructure);
#endif
}

static void NVIC_Configuration(void)
{
        NVIC_InitTypeDef NVIC_InitStructure;

#ifdef RT_USING_UART1
        /* Enable the USART1 Interrupt */
        NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);
#endif

#ifdef RT_USING_UART2
        /* Enable the USART2 Interrupt */
        NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);
   
   /* Enable the DMA1 Channel7 Interrupt */                           
        NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel7_IRQn;        //------------ 改动处4   增加此段  开始
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);                                  //------------ 改动处4   增加此段  结束
#endif

#ifdef RT_USING_UART3
        /* Enable the USART3 Interrupt */
        NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);

        /* Enable the DMA1 Channel2 Interrupt */
        NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel2_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);
#endif
}

static void DMA_Configuration(void)
{
#if defined (RT_USING_UART2)                                                //------------ 改动处5   增加此段  开始
        DMA_InitTypeDef DMA_InitStructure;

        /* fill init structure */
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
        DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
        DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
        DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
        DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

        /* DMA1 Channel5 (triggered by USART2 Tx event) Config */
        DMA_DeInit(UART2_TX_DMA);
        DMA_InitStructure.DMA_PeripheralBaseAddr = USART2_DR_Base;
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
        DMA_InitStructure.DMA_MemoryBaseAddr = (u32)0;
        DMA_InitStructure.DMA_BufferSize = 0;
        DMA_Init(UART2_TX_DMA, &DMA_InitStructure);
        DMA_ITConfig(UART2_TX_DMA, DMA_IT_TC | DMA_IT_TE, ENABLE);
        DMA_ClearFlag(DMA1_FLAG_TC7);
#endif                                                                       //------------ 改动处5   增加此段  结束
#if defined (RT_USING_UART3)
        DMA_InitTypeDef DMA_InitStructure;

        /* fill init structure */
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
        DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
        DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
        DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
        DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

        /* DMA1 Channel5 (triggered by USART3 Tx event) Config */
        DMA_DeInit(UART3_TX_DMA);
        DMA_InitStructure.DMA_PeripheralBaseAddr = USART3_DR_Base;
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
        DMA_InitStructure.DMA_MemoryBaseAddr = (u32)0;
        DMA_InitStructure.DMA_BufferSize = 0;
        DMA_Init(UART3_TX_DMA, &DMA_InitStructure);
        DMA_ITConfig(UART3_TX_DMA, DMA_IT_TC | DMA_IT_TE, ENABLE);
        DMA_ClearFlag(DMA1_FLAG_TC5);
#endif
}

/*
* Init all related hardware in here
* rt_hw_serial_init() will register all supported USART device
*/
void rt_hw_usart_init()
{
        USART_InitTypeDef USART_InitStructure;
        USART_ClockInitTypeDef USART_ClockInitStructure;

        RCC_Configuration();

        GPIO_Configuration();

        NVIC_Configuration();

        DMA_Configuration();

        /* uart init */
#ifdef RT_USING_UART1
        USART_InitStructure.USART_BaudRate = 115200;
        USART_InitStructure.USART_WordLength = USART_WordLength_8b;
        USART_InitStructure.USART_StopBits = USART_StopBits_1;
        USART_InitStructure.USART_Parity = USART_Parity_No;
        USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
        USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
        USART_ClockInitStructure.USART_Clock = USART_Clock_Disable;
        USART_ClockInitStructure.USART_CPOL = USART_CPOL_Low;
        USART_ClockInitStructure.USART_CPHA = USART_CPHA_2Edge;
        USART_ClockInitStructure.USART_LastBit = USART_LastBit_Disable;
        USART_Init(USART1, &USART_InitStructure);
        USART_ClockInit(USART1, &USART_ClockInitStructure);

        /* register uart1 */
        rt_hw_serial_register(&uart1_device, "uart1",
                RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_STREAM,
                &uart1);

        /* enable interrupt */
        USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
#endif

#ifdef RT_USING_UART2
        USART_InitStructure.USART_BaudRate = 115200;
        USART_InitStructure.USART_WordLength = USART_WordLength_8b;
        USART_InitStructure.USART_StopBits = USART_StopBits_1;
        USART_InitStructure.USART_Parity = USART_Parity_No;
        USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
        USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
        USART_ClockInitStructure.USART_Clock = USART_Clock_Disable;
        USART_ClockInitStructure.USART_CPOL = USART_CPOL_Low;
        USART_ClockInitStructure.USART_CPHA = USART_CPHA_2Edge;
        USART_ClockInitStructure.USART_LastBit = USART_LastBit_Disable;
        USART_Init(USART2, &USART_InitStructure);
        USART_ClockInit(USART2, &USART_ClockInitStructure);

    uart2_dma_tx.dma_channel= UART2_TX_DMA;     //------------ 改动处6   增加此行
   
        /* register uart2 */
        rt_hw_serial_register(&uart2_device, "uart2",
                RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_DMA_TX,  
                                                /* -------------改动处7 RT_DEVICE_FLAG_STREAM--->RT_DEVICE_FLAG_DMA_TX */
                &uart2);
   
    /* Enable USART2 DMA Tx request */
        USART_DMACmd(USART2, USART_DMAReq_Tx , ENABLE);  //------------ 改动处8   增加此行

        /* Enable USART2 DMA Rx request */
        USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
#endif

#ifdef RT_USING_UART3
        USART_InitStructure.USART_BaudRate = 115200;
        USART_InitStructure.USART_WordLength = USART_WordLength_8b;
        USART_InitStructure.USART_StopBits = USART_StopBits_1;
        USART_InitStructure.USART_Parity = USART_Parity_No;
        USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
        USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
        USART_ClockInitStructure.USART_Clock = USART_Clock_Disable;
        USART_ClockInitStructure.USART_CPOL = USART_CPOL_Low;
        USART_ClockInitStructure.USART_CPHA = USART_CPHA_2Edge;
        USART_ClockInitStructure.USART_LastBit = USART_LastBit_Disable;
        USART_Init(USART3, &USART_InitStructure);
        USART_ClockInit(USART3, &USART_ClockInitStructure);

        uart3_dma_tx.dma_channel= UART3_TX_DMA;

        /* register uart3 */
        rt_hw_serial_register(&uart3_device, "uart3",
                RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_DMA_TX,
                &uart3);

        /* Enable USART3 DMA Tx request */
        USART_DMACmd(USART3, USART_DMAReq_Tx , ENABLE);

        /* enable interrupt */
        USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
#endif
}



file--stm32f10x_it.c:
//增加中断函数
void DMA1_Channel7_IRQHandler(void)
{

}

阿莫论坛20周年了!感谢大家的支持与爱护!!

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入0汤圆

发表于 2010-10-12 14:47:47 | 显示全部楼层
file--stm32f10x_it.c:
//增加中断函数
void DMA1_Channel7_IRQHandler(void)
{
     // rt_hw_serial_dma_tx_isr ?
}

出0入0汤圆

 楼主| 发表于 2010-10-12 15:06:49 | 显示全部楼层
按楼上提示
改为:
void DMA1_Channel7_IRQHandler(void)
{
    rt_hw_serial_dma_tx_isr(_console_device);
}
这回 程序卡在:serial.c文件 RT_ASSERT(data_node != RT_NULL); 处 串口接收到错误提示:
  (data_node != RT_NULL) assert failed at rt_hw_serial_dma_tx_isr:384

出0入0汤圆

发表于 2010-10-12 15:17:51 | 显示全部楼层
* USART2 Tx --> DMA Channel 7
没设置_console_device为uart2前.你这样写不是自找麻烦?
或下次_console_device换了再让自己郁闷一回?

出0入0汤圆

发表于 2010-10-12 15:29:36 | 显示全部楼层
你要让rt_kprintf支持DMA?这不自找麻烦么,rt_kprintf不支持这种方式。要么轮询的方式发送,要么轮询等待DMA结束。不能用DMA中断结束的方式。

出0入0汤圆

 楼主| 发表于 2010-10-12 15:43:41 | 显示全部楼层
void DMA1_Channel7_IRQHandler(void)  
{  
    rt_hw_serial_dma_tx_isr(_console_device); //--这里面该怎么写 还没有领会到 问题应该是出在这里的
}




写成这样还是不行
void DMA1_Channel7_IRQHandler(void)  
{  
    rt_hw_serial_dma_tx_isr(&uart2_device);
}

出0入0汤圆

发表于 2010-10-12 15:45:23 | 显示全部楼层
rt_hw_serial_dma_tx_isr(&uart2 );

出0入0汤圆

 楼主| 发表于 2010-10-12 15:51:49 | 显示全部楼层
rt_hw_serial_dma_tx_isr(&amp;uart2 );
-----------------------------------------------------------------------
rt_hw_serial_dma_tx_isr(&uart2 );
也不对 出现参数类型不一样的错误提示
Error[Pe167]: argument of type "struct stm32_serial_device *" is incompatible with parameter of type "rt_device_t"
在usart.c 中uart2是这样定义的:
struct stm32_serial_device uart2 =
{
        USART2,
        &uart2_int_rx,
        &uart2_dma_tx
};回复【6楼】ffxz

出0入0汤圆

发表于 2010-10-12 15:54:41 | 显示全部楼层
原来的不能用DMA方式。
要改动相关驱动。

出0入0汤圆

 楼主| 发表于 2010-10-12 15:57:44 | 显示全部楼层
回复【8楼】lixun00 音乐虫子
原来的不能用dma方式。
要改动相关驱动。

-----------------------------------------------------------------------
是么?
你改过没有?让我学习学习一下!

出0入0汤圆

 楼主| 发表于 2010-10-13 13:16:28 | 显示全部楼层
回复【4楼】ffxz
你要让rt_kprintf支持dma?这不自找麻烦么,rt_kprintf不支持这种方式。要么轮询的方式发送,要么轮询等待dma结束。不能用dma中断结束的方式。
-----------------------------------------------------------------------
恩知道了 rt_kprintf 确实很难做到支持 DMA 我改了好多地方 只能发送一两次数据就卡死

还是自己写个算了

出0入0汤圆

发表于 2010-10-13 13:27:37 | 显示全部楼层
我估计rt_kprintf()函数是阻塞型的,即只有要发送完数据后,函数才返回。

    在改写了DMA方式,可以使用信号量。先初始化DMA1_CH7(源地址、目的地址、数量、地址增长方向、传输宽度、设置完成中断等),使能USART2,启动DMA1_CH7,然后在此等待信号量有效。在DMA1_CH7的中断处理中,给该信号量设为有效,即可。

出0入0汤圆

发表于 2010-10-13 13:47:43 | 显示全部楼层
如果在中断服务程序中来个rt_kprintf,阻塞谁去?所以,rt_kprintf必须要这么设计

出0入0汤圆

发表于 2010-10-13 13:47:58 | 显示全部楼层
一般printf底层都是一个字节一个字节输出的.DMA没意义.
再加上printf经常用来调试用.所以.搞复杂反而不好.

出0入0汤圆

发表于 2010-10-13 14:08:41 | 显示全部楼层
回复【12楼】ffxz  
如果在中断服务程序中来个rt_kprintf,阻塞谁去?所以,rt_kprintf必须要这么设计
-----------------------------------------------------------------------

    做为一个不管是在内核态,还是用户态都能用的函数,这样设计倒是正常的。如果只是在线程中调用,采用DMA方式也是可行的。

出0入0汤圆

发表于 2010-10-14 10:44:56 | 显示全部楼层
驱动要检测内核是否已经运行,如果没运行就用查询方式

出0入0汤圆

 楼主| 发表于 2010-10-15 21:16:33 | 显示全部楼层
回复【14楼】wuzhujian 吴助建
回复【12楼】ffxz   
如果在中断服务程序中来个rt_kprintf,阻塞谁去?所以,rt_kprintf必须要这么设计
-----------------------------------------------------------------------
    做为一个不管是在内核态,还是用户态都能用的函数,这样设计倒是正常的。如果只是在线程中调用,采用dma方式也是可行的。
-----------------------------------------------------------------------


确实是这样的原因,
rt_kprintf 在用于串口信息传输还是很不错的,如果是大量数据快速传输,有点用不习惯,还是用DMA好

我还是刚刚在学习RTT 觉得很不错的、慢慢摸索

出0入0汤圆

 楼主| 发表于 2010-10-20 14:32:43 | 显示全部楼层
自己写了一个 已经测试!
/*
* File      : usart.h
*/

#ifndef __USART_H__
#define __USART_H__

#include <rthw.h>
#include <rtthread.h>
#include <stm32f10x_dma.h>
#include <serial.h>

#define USING_DMA1
//#define USING_DMA1_Channel2
//#define USING_DMA1_Channel3
//#define USING_DMA1_Channel4
//#define USING_DMA1_Channel5
//#define USING_DMA1_Channel6
#define USING_DMA1_Channel7

#define USART1_DR_Base      0x40013804
#define USART2_DR_Base      0x40004404
#define USART3_DR_Base      0x40004804

#define UART1_TX_DMA        DMA1_Channel4
#define UART1_RX_DMA        DMA1_Channel5
#define UART2_TX_DMA        DMA1_Channel7
#define UART2_RX_DMA        DMA1_Channel6
#define UART3_TX_DMA        DMA1_Channel2
#define UART3_RX_DMA        DMA1_Channel3

#define RCC_APBPeriph_UART1     RCC_APB2Periph_USART1
#define RCC_APBPeriph_UART2     RCC_APB1Periph_USART2
#define RCC_APBPeriph_UART3     RCC_APB1Periph_USART3


/* USART1_REMAP = 0 */
#define UART1_GPIO_TX                GPIO_Pin_9
#define UART1_GPIO_RX                GPIO_Pin_10
#define UART1_GPIO                        GPIOA
/* USART2_REMAP = 0 */
#if (defined(STM32F10X_LD) || defined(STM32F10X_MD) || defined(STM32F10X_CL))
    #define UART2_GPIO_TX            GPIO_Pin_5
    #define UART2_GPIO_RX            GPIO_Pin_6
    #define UART2_GPIO                    GPIOD
#endif
#ifdef STM32F10X_HD
    #define UART2_GPIO_TX                GPIO_Pin_2
    #define UART2_GPIO_RX                GPIO_Pin_3
    #define UART2_GPIO                        GPIOA
#endif
/* USART3_REMAP[1:0] = 00 */
#define UART3_GPIO_RX                GPIO_Pin_11
#define UART3_GPIO_TX                GPIO_Pin_10
#define UART3_GPIO                        GPIOB

#define ExSRAM_AddrBase         ((u32)0x68000000)
#define USART_TxBuf_AddrBase    (ExSRAM_AddrBase + (u32)0x00)   
#define USART_TxBuf             ((u16*)USART_TxBuf_AddrBase)
#define USART_TxBuf_Len         0x400  /*缓存长度 (双字节)*/

#define USART_RxBuf_AddrBase    (ExSRAM_AddrBase + (u32)USART_TxBuf_Len)   
#define USART_RxBuf             ((u8*)USART_RxBuf_AddrBase)
#define USART_RxBuf_Len         0x10 /*缓存长度 (字节)*/


extern DMA_InitTypeDef DMA_InitStructure;
extern vu32 is_USART2_DMA_READY;


extern void rt_hw_usart_init(void);
extern void USART_Tx_DMA(u32 AddrBase,u32 len);

#endif

出0入0汤圆

 楼主| 发表于 2010-10-20 14:33:22 | 显示全部楼层
/*
* File      : usart.c
*/

#include "usart.h"

DMA_InitTypeDef DMA_InitStructure;
vu32    is_USART2_DMA_READY=0;

/*****************************************************************************/
//                 RT-Thread 的 rt_kprintf 串口驱动
/*****************************************************************************/

#ifdef RT_USING_UART1
    struct stm32_serial_int_rx uart1_int_rx;
    struct stm32_serial_device uart1 =
    {
            USART1,
            &uart1_int_rx,
            RT_NULL
    };
    struct rt_device uart1_device;
#endif


#ifdef RT_USING_UART2
    struct stm32_serial_int_rx uart2_int_rx;
    struct stm32_serial_device uart2 =
    {
        USART2,
        &uart2_int_rx,
        RT_NULL
    };
    struct rt_device uart2_device;
#endif


#ifdef RT_USING_UART3
    struct stm32_serial_int_rx uart3_int_rx;
    struct stm32_serial_dma_tx uart3_dma_tx;
    struct stm32_serial_device uart3 =
    {
        USART3,
        &uart3_int_rx,
        &uart3_dma_tx
    };
    struct rt_device uart3_device;
#endif
   
/*****************************************************************************/
//                  RT-Thread  rt_kprintf ---------end
/*****************************************************************************/



//------------------------------------------
// USARTx AFIO GPIO 和 DMA 时钟开启
//------------------------------------------
static void RCC_Configuration(void)
{
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);    // 开启 AFIO 时钟

#ifdef RT_USING_UART1       
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1 | RCC_APB2Periph_GPIOA, ENABLE);       // 开启 USART1 和 GPIOA 时钟
#endif

#ifdef RT_USING_UART2
    #if (defined(STM32F10X_LD) || defined(STM32F10X_MD) || defined(STM32F10X_CL))   
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOD, ENABLE);     // 开启 GPIOD 时钟
        GPIO_PinRemapConfig(GPIO_Remap_USART2, ENABLE);     // 使能 USART2 引脚 重映射
    #else   
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO | RCC_APB2Periph_GPIOA, ENABLE);     // 开启 GPIOA 时钟
    #endif       
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2, ENABLE);  // 开启 USART2 时钟
#endif

#ifdef RT_USING_UART3
        RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);   // 开启 GPIOB 时钟       
        RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART3, ENABLE);  // 开启 USART3 时钟
#endif  
   
#ifdef USING_DMA1
    RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA1, ENABLE);      // 开启 DMA 时钟
#endif
}


//------------------------------------------
//          设置 GPIO
//------------------------------------------
static void GPIO_Configuration(void)
{
        GPIO_InitTypeDef GPIO_InitStructure;

#ifdef RT_USING_UART1
        GPIO_InitStructure.GPIO_Pin = UART1_GPIO_RX;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        GPIO_Init(UART1_GPIO, &GPIO_InitStructure);

        GPIO_InitStructure.GPIO_Pin = UART1_GPIO_TX;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_Init(UART1_GPIO, &GPIO_InitStructure);
#endif

#ifdef RT_USING_UART2
        GPIO_InitStructure.GPIO_Pin = UART2_GPIO_RX;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        GPIO_Init(UART2_GPIO, &GPIO_InitStructure);

        GPIO_InitStructure.GPIO_Pin = UART2_GPIO_TX;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(UART2_GPIO, &GPIO_InitStructure);
#endif

#ifdef RT_USING_UART3
        GPIO_InitStructure.GPIO_Pin = UART3_GPIO_RX;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING;
        GPIO_Init(UART3_GPIO, &GPIO_InitStructure);

        GPIO_InitStructure.GPIO_Pin = UART3_GPIO_TX;
        GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
        GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
        GPIO_Init(UART3_GPIO, &GPIO_InitStructure);
#endif
}


//------------------------------------------
//          设置 中断
//------------------------------------------
static void NVIC_Configuration(void)
{
        NVIC_InitTypeDef NVIC_InitStructure;

#ifdef RT_USING_UART1
        NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);
#endif

#ifdef RT_USING_UART2
        NVIC_InitStructure.NVIC_IRQChannel = USART2_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);
#endif

#ifdef RT_USING_UART3
        /* Enable the USART3 Interrupt */
        NVIC_InitStructure.NVIC_IRQChannel = USART3_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);


#endif
  
#ifdef  USING_DMA1_Channel2                           
        NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel2_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);
#endif     
#ifdef  USING_DMA1_Channel7                           
        NVIC_InitStructure.NVIC_IRQChannel = DMA1_Channel7_IRQn;
        NVIC_InitStructure.NVIC_IRQChannelSubPriority = 2;
        NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
        NVIC_Init(&NVIC_InitStructure);
#endif
}


//------------------------------------------
//          设置 DMA
//------------------------------------------
static void DMA_Configuration(void)
{
#if (defined(RT_USING_UART2) && defined(USING_DMA1))                                       
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
        DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
        DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
        DMA_InitStructure.DMA_Priority = DMA_Priority_Low;//DMA_Priority_VeryHigh;
        DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

        DMA_InitStructure.DMA_PeripheralBaseAddr = USART2_DR_Base;
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
        DMA_InitStructure.DMA_MemoryBaseAddr = (u32)USART_TxBuf_AddrBase;
        DMA_InitStructure.DMA_BufferSize = USART_TxBuf_Len *2;
   
    DMA_DeInit(UART2_TX_DMA);
        DMA_Init(UART2_TX_DMA, &DMA_InitStructure);   
        DMA_ITConfig(UART2_TX_DMA, DMA_IT_TC | DMA_IT_TE, ENABLE);                                                                  
        DMA_ClearFlag(DMA1_FLAG_TC7);
   
    USART_DMACmd(USART2, USART_DMAReq_Tx , ENABLE);
   
    is_USART2_DMA_READY=1;
#endif   
   
#if (defined(RT_USING_UART3) && defined(USING_DMA1))
        DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
        DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
        DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
        DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
        DMA_InitStructure.DMA_Mode = DMA_Mode_Normal;
        DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
        DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;

        DMA_InitStructure.DMA_PeripheralBaseAddr = USART3_DR_Base;
        DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
        DMA_InitStructure.DMA_MemoryBaseAddr = (u32)0;
        DMA_InitStructure.DMA_BufferSize = 0;
   
    DMA_DeInit(UART3_TX_DMA);
        DMA_Init(UART3_TX_DMA, &DMA_InitStructure);
        DMA_ITConfig(UART3_TX_DMA, DMA_IT_TC | DMA_IT_TE, ENABLE);
        DMA_ClearFlag(DMA1_FLAG_TC5);
   
    USART_DMACmd(USART3, USART_DMAReq_Tx , ENABLE);
#endif
}



//------------------------------------------
//         初始化 USARTx
//------------------------------------------
void rt_hw_usart_init()
{
    USART_InitTypeDef       USART_InitStructure;
    USART_ClockInitTypeDef  USART_ClockInitStructure;

    RCC_Configuration();

    GPIO_Configuration();

    NVIC_Configuration();

#ifdef RT_USING_UART1
        USART_InitStructure.USART_BaudRate = 115200;
        USART_InitStructure.USART_WordLength = USART_WordLength_8b;
        USART_InitStructure.USART_StopBits = USART_StopBits_1;
        USART_InitStructure.USART_Parity = USART_Parity_No;
        USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_RTS_CTS;//USART_HardwareFlowControl_None;
        USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
        USART_ClockInitStructure.USART_Clock = USART_Clock_Disable;
        USART_ClockInitStructure.USART_CPOL = USART_CPOL_Low;
        USART_ClockInitStructure.USART_CPHA = USART_CPHA_2Edge;
        USART_ClockInitStructure.USART_LastBit = USART_LastBit_Disable;
        USART_Init(USART1, &USART_InitStructure);
        USART_ClockInit(USART1, &USART_ClockInitStructure);

//-------------在 RT-Thread 中注_册 USART1 设备---------------------------------
        rt_hw_serial_register(&uart1_device, "uart1",
                RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_STREAM,
                &uart1);
//-----------------------------------------------------------------------------

        USART_ITConfig(USART1, USART_IT_RXNE, ENABLE);
#endif

#ifdef RT_USING_UART2
        USART_InitStructure.USART_BaudRate = 128000;//115200;
        USART_InitStructure.USART_WordLength = USART_WordLength_8b;
        USART_InitStructure.USART_StopBits = USART_StopBits_1;
        USART_InitStructure.USART_Parity = USART_Parity_No;
        USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
        USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
        USART_ClockInitStructure.USART_Clock = USART_Clock_Disable;
        USART_ClockInitStructure.USART_CPOL = USART_CPOL_Low;
        USART_ClockInitStructure.USART_CPHA = USART_CPHA_2Edge;
        USART_ClockInitStructure.USART_LastBit = USART_LastBit_Disable;
        USART_Init(USART2, &USART_InitStructure);
        USART_ClockInit(USART2, &USART_ClockInitStructure);

  
//-------------在 RT-Thread 中注_册 USART2 设备---------------------------------
        rt_hw_serial_register(&uart2_device, "uart2",
                RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_STREAM,  
                &uart2);
//-----------------------------------------------------------------------------
        USART_ITConfig(USART2, USART_IT_RXNE, ENABLE);
#endif

#ifdef RT_USING_UART3
        USART_InitStructure.USART_BaudRate = 115200;
        USART_InitStructure.USART_WordLength = USART_WordLength_8b;
        USART_InitStructure.USART_StopBits = USART_StopBits_1;
        USART_InitStructure.USART_Parity = USART_Parity_No;
        USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;
        USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx;
        USART_ClockInitStructure.USART_Clock = USART_Clock_Disable;
        USART_ClockInitStructure.USART_CPOL = USART_CPOL_Low;
        USART_ClockInitStructure.USART_CPHA = USART_CPHA_2Edge;
        USART_ClockInitStructure.USART_LastBit = USART_LastBit_Disable;
        USART_Init(USART3, &USART_InitStructure);
        USART_ClockInit(USART3, &USART_ClockInitStructure);

        uart3_dma_tx.dma_channel= UART3_TX_DMA;

//-------------在 RT-Thread 中注_册 USART2 设备---------------------------------
        rt_hw_serial_register(&uart3_device, "uart3",
                RT_DEVICE_FLAG_RDWR | RT_DEVICE_FLAG_INT_RX | RT_DEVICE_FLAG_DMA_TX,
                &uart3);
//-----------------------------------------------------------------------------
        USART_ITConfig(USART3, USART_IT_RXNE, ENABLE);
#endif
   
    DMA_Configuration();


}


//------------------------------------------
//       USARTx DMA方式 发送大量数据
//------------------------------------------
void USART_Tx_DMA(u32 AddrBase,u32 len)
{
    while(!is_USART2_DMA_READY)
    {
        rt_thread_delay(10);
    }

    UART2_TX_DMA->CNDTR = len;
    UART2_TX_DMA->CMAR = AddrBase;            
    DMA_Cmd(UART2_TX_DMA,ENABLE);
    is_USART2_DMA_READY=0;
}

出0入0汤圆

 楼主| 发表于 2010-10-20 14:34:48 | 显示全部楼层
/*
*  stm32f10x_it.c
*/
void DMA1_Channel7_IRQHandler(void)
{   
    if(DMA_GetITStatus(DMA1_IT_TC7))
    {
        DMA_ClearITPendingBit(DMA1_IT_GL7);
        DMA_Cmd(DMA1_Channel7,DISABLE);
        is_USART2_DMA_READY=1;
  }
   
}
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-6-10 06:44

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表