各位大侠,小弟遇到一个十分让人困惑的问题。在如下的main函数中将BspInit();前面的#if 0改为#if 1之后,也就是将BspInit();到main结尾部分的代码编译进来之后,串口无法正常发数,原因在于DMA使能失败;在#if 0的情况下,也就是不将BspInit();到main结尾部分的代码编译进来,则串口能够正常工作。按道理来说,后面的代码还未运行,怎么会影响到前面代码的执行呢?不应该啊。于是考虑是不是栈溢出导致的问题,然后仔细想了一下,发现说不通,栈的空间是在函数被调用的时候才会被占用,因为串口测试代码放在了main函数的最开始,而且运行到for循环的时候,栈的空间才被占用不到60个字节,在启动代码里面分配的栈的大小是1K字节。小弟我想了各种办法,做了各种尝试,试了各种初始化以及使能顺序,依然没有能够解决这个问题。想请各位前辈大侠高手们帮忙给支支招,小弟先谢谢
论坛里的各位前辈大侠高手们了。
main函数如下
int main(void)
{
int ret;
struct PlcJDIRT *jdirt;
char *memory;
char *r_memory;
/*串口测试*/
uint32_t i=0;
uint8_t b[16] = {1,3, 0,0,0,2,0xFF,0xFF};
delay_init(168);
ret = OpenUart(PLC_
STM32_UART_COM1);
for(i=0; i<5; i++)
{
ret = WriteToUart(PLC_STM32_UART_COM1, b, 8);
delay_ms(1000);
}
/*串口测试*/
/*-------------init all board device---------------*/
//NVIC config 0-15 prio
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);
#if 0
BspInit();
//InitDrac200MConfig();
ret = InitPlcSys();
assert(ret == PLC_RTSUCCESS);
ret = InitPSocketSystem();
assert(ret == PLC_RTSUCCESS);
ret = InitPlcCommonFW();
assert(ret == PLC_RTSUCCESS);
Ini
tialDRAC200MIOBoard();
InitialModbusSlave();
InitialModbusMaster();
memory = pv_EXT_PortMalloc(SIZE_OF_MEMORY);
assert(memory != NULL);
r_memory = pv_EXT_PortMalloc(SIZE_OF_R_MEMORY);
assert(r_memory != NULL);
jdirt = InitPlcJDIRT(memory, SIZE_OF_MEMORY,
r_memory, SIZE_OF_R_MEMORY);
assert(jdirt != NULL);
xTaskCreate(led_task,"TASK_1",256,NULL,20,NULL);
xTaskCreate(StartUDPServer,"UDPServer",1000, jdirt, 5, NULL);
vTaskStartScheduler();
#endif
}
OpenUart(PLC_STM32_UART_COM1);调用顺序如下
/*Initialize UART5*/
PLC_STM32_UART_COM1_Config(PLC_UART_485, PLC_BAUDRATE_115200, PLC_PARITY_NO, PLC_DATABIT_8, PLC_STOPBIT_1);
/*Enable UART5*/
/*Configure DMA1_Stream0 for UART5_RX*/
DMAConfig(DMA1_Stream0,
BUF_SIZE_MAX,
DMA_DIR_PeripheralToMemory,
(uint32_t)g_buf_rx[COM1],
DMA_Mode_Circular,
(uint32_t)&UART5->DR,
DMA_Priority_Medium);
NVICConfig(DMA1_Stream0_IRQn, 12, 0);
/*Configure DMA1_Stream7 for UART5_TX*/
DMAConfig(DMA1_Stream7,
0,
DMA_DIR_MemoryToPeripheral,
(uint32_t)g_buf_tx[COM1],
DMA_Mode_Normal,
(uint32_t)&UART5->DR,
DMA_Priority_High);
NVICConfig(UART5_IRQn, 12, 0);
/*Start to receive data through COM1*/
DMAEnable(DMA1_Stream0, UART5, USART_DMAReq_Rx, BUF_SIZE_MAX);
/*Enable UART5*/
USART_Cmd(UART5, ENABLE);
WriteToUart(PLC_STM32_UART_COM2, b, 8);中会调用WriteData(DMA1_Stream7, UART5, COM1, buf, length);
WriteData(DMA1_Stream7, UART5, COM1, buf, length);中会调用DMAEnable(DMAy_Streamx, USARTx, USART_DMAReq_Tx, (uint16_t)length);
DMAEnable(DMAy_Streamx, USARTx, USART_DMAReq_Tx, (uint16_t)length);程序如下
/*
*********************************************************************************************************
* @brief Enable DMA transfer
* @param DMAy_Streamx: where y can be 1 or 2 to select the DMA and x
* can be 0 to 7 to select the DMA Stream.
* @param USARTx: where x can be 1, 2, 3, 4, 5, 6, 7 or 8 to select the USART or UART peripheral.
* @param USART_DMAReq: Specifies the DMA request.
* This parameter can be any combination of the following values:
* USART_DMAReq_Tx: USART DMA transmit request
* USART_DMAReq_Rx: USART DMA receive request
* @param counter: Specifies the number of data items need to be transfered.
* @retval None
*********************************************************************************************************
*/
static void DMAEnable(DMA_Stream_TypeDef * DMAy_Streamx, USART_TypeDef * USARTx, uint16_t USART_DMAReq, uint16_t counter)
{
USART_DMACmd(USARTx, USART_DMAReq, DISABLE);
DMA_Cmd(DMAy_Streamx, DISABLE);
while (DMA_GetCmdStatus(DMAy_Streamx) != DISABLE){}
DMA_SetCurrDataCounter(DMAy_Streamx, counter);
USART_DMACmd(USARTx, USART_DMAReq, ENABLE);
DMA_Cmd(DMAy_Streamx, ENABLE);
}
GPIO初始化代码如下
/*
*********************************************************************************************************
* @brief Configure the PLC_STM32_UART_COM1 according to the specified
* parameters, referenced by SetSTM32UartConfig.
* @param mode: Select RS485 or RS232.
* @param baud: Set baud rate.
* @param parity: Set parity mode.
* @param data_bit: Set word length.
* @param stop_bit: Set number of stop bits.
* @retval None
*********************************************************************************************************
*/
static void PLC_STM32_UART_COM1_Config(char mode, char baud, char parity, char data_bit, char stop_bit)
{
GPIO_InitTypeDef GPIO_InitStructure;
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOD | RCC_AHB1Periph_GPIOG, ENABLE);//Enable clock of GPIOB, GPIOC, GPIOD, GPIOG
RCC_APB1PeriphClockCmd(RCC_APB1Periph_UART5, ENABLE);//Enable clock of UART5
/*Alternate function PC12->UART5_TX, PD2->UART5_RX*/
GPIO_PinAFConfig(GPIOC, GPIO_PinSource12, GPIO_AF_UART5);//AF, GPIOC12->UART5
GPIO_PinAFConfig(GPIOD, GPIO_PinSource2, GPIO_AF_UART5);//AF, GPIOD2->UART5
/*Configure Pin_12 of GPIOC as AF UART5_TX*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;//GPIOC12
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;//Alternate function
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//Speed 50MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//Push & pull
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;//No pull
GPIO_Init(GPIOC, &GPIO_InitStructure);//Initialize GPIOC
/*Configure Pin_2 of GPIOD as AF UART5_RX*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;//GPIOD2
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;// Alternate function
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//Speed 50MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//Push & pull
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;//No pull
GPIO_Init(GPIOD, &GPIO_InitStructure);//Initialize GPIOD
/*Configure Pin_5 of GPIOB to select RS232 or RS485 in main board*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5;//GPIOB5
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//Out put
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//Speed 50MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//Push & pull
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;//No pull
GPIO_Init(GPIOB, &GPIO_InitStructure);//Initialize GPIOB
/*Configure Pin_9 of GPIOG to select RS232 or RS485 in core board*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;//GPIOG9
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//Out put
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//Speed 50MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//Push & pull
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;//No pull
GPIO_Init(GPIOG, &GPIO_InitStructure);//Initialize GPIOG
/*Configure Pin_7 of GPIOD to select TX or RX of RS485*/
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;//GPIOD7
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;//Out put
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;//Speed 50MHz
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;//Push & pull
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL;//No pull
GPIO_Init(GPIOD, &GPIO_InitStructure);//Initialize GPIOD
/*Initialize UART5*/
USART_Config(UART5, baud, parity);
/*Select RS485 or RS232*/
UART5_485OR232 = mode;//Select RS485 or RS232 in core board
UART5_MB485OR232 = mode;//Select RS485 or RS232 in main board
/*Set default mode of RS485*/
UART5_485 = RS485_RX_CONTROL;//Default Rx
}
串口初始化代码如下
/*
*********************************************************************************************************
* @brief Configure the USART according to the specified parameters.
* @param USARTx: where x can be 1, 2, 3, 4, 5, 6, 7 or 8 to select the USART or UART peripheral.
* @param baud: Set baud rate.
* @param parity: Set parity mode.
* @retval None
*********************************************************************************************************
*/
static void USART_Config(USART_TypeDef * USARTx, char baud, char parity)
{
USART_InitTypeDef USART_InitStructure;
switch (baud){
case PLC_BAUDRATE_300:
USART_InitStructure.USART_BaudRate = 300;//Set baud rate to 300
break;
case PLC_BAUDRATE_9600:
USART_InitStructure.USART_BaudRate = 9600;//Set baud rate to 9600
break;
case PLC_BAUDRATE_38400:
USART_InitStructure.USART_BaudRate = 38400;//Set baud rate to 38400
break;
case PLC_BAUDRATE_115200:
USART_InitStructure.USART_BaudRate = 115200;//Set baud rate to 115200
break;
}
switch (parity){
case PLC_PARITY_NO:
USART_InitStructure.USART_Parity = USART_Parity_No;//No parity
USART_InitStructure.USART_WordLength = USART_WordLength_8b;//Set word length to 8
break;
case PLC_PARITY_EVEN:
USART_InitStructure.USART_Parity = USART_Parity_Even;//Even parity
USART_InitStructure.USART_WordLength = USART_WordLength_9b;//Set word length to 9
break;
case PLC_PARITY_ODD:
USART_InitStructure.USART_Parity = USART_Parity_Odd;//Odd parity
USART_InitStructure.USART_WordLength = USART_WordLength_9b;//Set word length to 9
break;
}
USART_InitStructure.USART_StopBits = USART_StopBits_1;//1 stop bit
USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//No hardware control
USART_InitStructure.USART_Mode = USART_Mode_Rx | USART_Mode_Tx; //Tx & Rx are both enabled
USART_Init(USARTx, &USART_InitStructure);//Initialize USARTx
/*Clear TC bit in USART_SR*/
while(USART_GetFlagStatus(USARTx, USART_FLAG_TC) == SET){
USART_ClearFlag(USARTx, USART_FLAG_TC);
}
/*Enable transmission complete interrupt*/
USART_ITConfig(USARTx, USART_IT_TC, ENABLE);//for test
}
NVIC初始化代码如下
/*
*********************************************************************************************************
* @brief Configure DMA or USART interrupt.
* @retval None
*********************************************************************************************************
*/
static void NVICConfig(uint8_t NVIC_IRQChannel,
uint8_t NVIC_IRQChannelPreemptionPriority,
uint8_t NVIC_IRQChannelSubPriority)
{
NVIC_InitTypeDef NVIC_InitStructure;
/*Enable DMA TC interrupt*/
NVIC_InitStructure.NVIC_IRQChannel = NVIC_IRQChannel;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = NVIC_IRQChannelPreemptionPriority;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = NVIC_IRQChannelSubPriority;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
DMA初始化代码如下
/*
*********************************************************************************************************
* @brief Configure the DMA according to the specified parameters,
* referenced by ReadFromUart & WriteToUart.
* @param DMAy_Streamx: where y can be 1 or 2 to select the DMA and x
* can be 0 to 7 to select the DMA Stream.
* @param DMA_DIR: Specifies if the data will be transferred from memory to peripheral,
* from memory to memory or from peripheral to memory.
* @param DMA_Memory0BaseAddr: Specifies the memory 0 base address for DMAy Streamx.
* @param DMA_PeripheralBaseAddr: Specifies the peripheral base address for DMAy Streamx.
* @param DMA_Priority: Specifies whether the Peripheral address register
* should be incremented or not.
* @retval None
*********************************************************************************************************
*/
static void DMAConfig( DMA_Stream_TypeDef * DMAy_Streamx,
uint32_t DMA_BufferSize,
uint32_t DMA_DIR,
uint32_t DMA_Memory0BaseAddr,
uint32_t Mode,
uint32_t DMA_PeripheralBaseAddr,
uint32_t DMA_Priority )
{
DMA_InitTypeDef DMA_InitStructure;
/*Enable the clock of DMA*/
if((uint32_t)DMAy_Streamx<(uint32_t)DMA2)//Determin the current stream belongs to DMA1 or DMA2
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA1, ENABLE);//Enable the clock of DMA1
else
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_DMA2, ENABLE);//Enable the clock of DMA2
DMA_DeInit(DMAy_Streamx);
/*Waiting for the EN bit in DMA_SxCR become reset*/
DMA_Cmd(DMAy_Streamx, DISABLE);
while (DMA_GetCmdStatus(DMAy_Streamx) != DISABLE){}
/*Configure DMA stream*/
DMA_InitStructure.DMA_BufferSize = DMA_BufferSize;//need to be configured
DMA_InitStructure.DMA_Channel = DMA_Channel_4;
DMA_InitStructure.DMA_DIR = DMA_DIR;//need to be configured
DMA_InitStructure.DMA_FIFOMode = DMA_FIFOMode_Disable;//changed
DMA_InitStructure.DMA_FIFOThreshold = DMA_FIFOThreshold_Full;
DMA_InitStructure.DMA_Memory0BaseAddr = DMA_Memory0BaseAddr;//need to be configured
DMA_InitStructure.DMA_MemoryBurst = DMA_MemoryBurst_Single;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_Mode = Mode;//need to be configured
DMA_InitStructure.DMA_PeripheralBaseAddr = DMA_PeripheralBaseAddr;//need to be configured
DMA_InitStructure.DMA_PeripheralBurst = DMA_PeripheralBurst_Single;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_Priority = DMA_Priority;//need to be configured
DMA_Init(DMAy_Streamx, &DMA_InitStructure);
/*Enable DMA TCIF if the stream is used for receiving*/
if((DMAy_Streamx == DMA1_Stream0) || (DMAy_Streamx == DMA1_Stream1) || (DMAy_Streamx == DMA1_Stream2))//for test
DMA_ITConfig(DMAy_Streamx, DMA_IT_TC, ENABLE);
}
http://www.stmcu.com.cn/Designre ... b7562f11b9bbd82d0df
--------------------------------------------------------
STM32家族中基于ARM Cortex M4内核的STM32F3与STM32F4系列芯片内有一块特殊的SRAM存储区---内核耦合存储器[CCM RAM],为CPU所专享访问。主要是为了实现最高系统时钟频率下执行代码,同时避免出现等待状态。因此,与从闪存里执行代码相比,就大大减少了关键任务的执行时间。
CCM RAM一般用于实时性高或计算密集型程序,比如:
* 数字电源的控制环(开关电源,照明)
* 3相矢量电机控制
* 实时DSP 任务
当程序代码位于CCM RAM且数据保存在常规SRAM时,M4内核便处于最优的哈佛结构配置,让指令零等待执行从而实现速度最大化。如果中断服务程序位于CCM RAM中,可以确保最短的时延,提高响应速度。
当CCM RAM不用来存放执行代码时,也可当做常规SRAM使用。不过它不能被DMA访问。另外,也不推荐在CCM中同时存放指令代码和数据,不然内核访问CCM里的数据和指令时可能会出现冲突,影响CPU的处理性能。
-------------------------------------------------------------
从资料看,如何使用CCM内存,需要工程做相应配置。
一周热门 更多>