Part Number:MSP430F5438A
额,我遇到的问题比较奇怪,我尽可能描述清楚问题。
我使用MSP430F5438a,以下使用单片机代替MSP430F5438a。
单片机与DSP通过DMA+SPI进行通讯。单片机作为SPI通讯的主机。
1、由于每次通讯单片机都是接收数据,但是标准SPI通讯要求发送同时接收,因此单片机维持着两段内存,分别是send_buf和recv_buf。send_buf是发送端缓存,而recv_buf是接收端缓存。
2、由于单片机与DSP通讯的目的是用于从DSP接收数据,单片机发送数据仅仅是为了保证SPI真正实现双端通讯,DSP端根本不关心接收到的数据是什么,会直接丢掉。
3、我使用两路DMA来保证SPI通讯双端通讯。到目前为止,一切正常。
4、由于单片机RAM紧张,我希望压缩send_buf缓存尺寸。由于发送数据DSP根本“不敢兴趣”,因此我在使用DMA发送数据时,将DMA发送端内存地址设置为地址不变,即发送端每次发送的都是固定地址的数据。
按照我的理解,这样做应该是可行的。但是,程序在大多数情况下运行是正常的,但是偶然情况下(可能一天会出现1~2次)会修改我栈中的数据,从而导致其它程序运行异常。
恳请各位帮助,不胜感激。
Susan Yang:
chang liu 说:因此我在使用DMA发送数据时,将DMA发送端内存地址设置为地址不变,即发送端每次发送的都是固定地址的数据。
能否给出相关代码?
/** Configure DMA channel 0* Use TxString as source* Increment source address after every transfer*/DMA_setSrcAddress(DMA_CHANNEL_0,(uint32_t)(uintptr_t)&TxString,DMA_DIRECTION_INCREMENT);是可以选择 #define DMA_DIRECTION_UNCHANGED (DMASRCINCR_0) 的
chang liu 说:按照我的理解,这样做应该是可行的。
是的,我也是这样认为的
chang liu 说:但是偶然情况下(可能一天会出现1~2次)会修改我栈中的数据,从而导致其它程序运行异常。
能否详细说明一下?
,
chang liu:
非常感谢你的回复。
/* 此时不关心发送数据,因此禁止发送数据内存地址自增 */__data16_write_addr((unsigned short)&DMA0SA, (unsigned long)SrcAddr);__data16_write_addr((unsigned short)&DMA0DA, (unsigned long)&UCB0TXBUF);DMA0SZ = Len;DMA0CTL = DMADT_1 + DMASRCINCR_0 + DMADSTBYTE + DMASRCBYTE + DMALEVEL;/* DMA接收 */__data16_write_addr((unsigned short)&DMA1SA, (unsigned long)&UCB0RXBUF);__data16_write_addr((unsigned short)&DMA1DA, (unsigned long)DstAddr);DMA1SZ = Len;DMA1CTL = DMADT_1 + DMADSTINCR_3 + DMADSTBYTE + DMASRCBYTE + DMALEVEL + DMAIE;break;/* 其中第5行 DMASRCINCR_0 即代表发送端内存地址保持不变 */栈中数据出错表现为:(类似现象举例如下)
void func(void) {bool flag = flase;if (flag){/* 函数可以执行到这里,所以我严重怀疑栈数据出错!!! */} }
,
Susan Yang:
建议您先参考下例程内的设置
/* --COPYRIGHT--,BSD_EX* Copyright (c) 2012, Texas Instruments Incorporated* 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 Texas Instruments Incorporated 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 THE COPYRIGHT OWNER OR* 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.**********************************************************************************MSP430 CODE EXAMPLE DISCLAIMER** MSP430 code examples are self-contained low-level programs that typically* demonstrate a single peripheral function or device feature in a highly* concise manner. For this the code may rely on the device's power-on default* register values and settings such as the clock configuration and care must* be taken when combining code from several examples to avoid potential side* effects. Also see www.ti.com/grace for a GUI- and www.ti.com/msp430ware* for an API functional library-approach to peripheral configuration.** --/COPYRIGHT--*/ //****************************************************************************** //MSP430F543xA Demo - SPI TX & RX using DMA0 & DMA1 Single Transfer in Fixed //Address Mode // //Description: This code has to be used with MSP430F543xA_uscia0_spi_10.c as //slave SPI. DMA0 is used to transfer a single byte while DMA1 is used to //RX from slave SPI at the same time. This code will set P1.0 if RX character //is correct and clears P1.0 if received character is wrong. Watchdog in //interval mode triggers block transfer every 1000ms. //ACLK = REFO = 32kHz, MCLK = SMCLK = default DCO 1048576Hz // //MSP430F5438A //----------------- ///|\|XIN|- //| || 32768Hz //--|RSTXOUT|- //|| //|P1.0|-> LED //|| //|P3.4|-> Data Out (UCA0SIMO) //|| //|P3.5|<- Data In (UCA0SOMI) //|| //|P3.0|-> Serial Clock Out (UCA0CLK) // //M. Morales //Texas Instruments Inc. //June 2009 //Built with CCE v3.1 Build 3.2.3.6.4 & IAR Embedded Workbench Version: 4.11B //******************************************************************************#include <msp430.h> #include <stdint.h>char TxString; char RxString;int main(void) {WDTCTL = WDT_ADLY_1000;// WDT 1000ms, ACLK, interval timerSFRIE1 |= WDTIE;// Enable WDT interruptP1OUT &= ~0x01;// Clear P1.0P1DIR |= 0x01;// P1.0 = OutputP3SEL |= 0x31;// P3.0,4,5 = USCI_A0 SPI OptionUCA0CTL1 |= UCSWRST;// **Put state machine in reset**UCA0CTL0 = UCMST+UCSYNC+UCCKPL+UCMSB;// 3-pin, 8-bit SPI master// Clock polarity high, MSBUCA0CTL1 = UCSSEL_2;// SMCLKUCA0BR0 = 0x02;// /2UCA0BR1 = 0x00;//UCA0MCTL = 0x00;// No modulationUCA0CTL1 &= ~UCSWRST;// **Initialize USCI state machine**DMACTL0 = DMA1TSEL_16+DMA0TSEL_17;// DMA0 - UCA0TXIFG// DMA1 - UCA0RXIFG// Setup DMA0__data20_write_long((uintptr_t) &DMA0SA,(uintptr_t) &TxString);// Source block address__data20_write_long((uintptr_t) &DMA0DA,(uintptr_t) &UCA0TXBUF);// Destination single addressDMA0SZ = 1;// Block sizeDMA0CTL = DMASRCINCR_3+DMASBDB+DMALEVEL;// inc src// Setup DMA1__data20_write_long((uintptr_t) &DMA1SA,(uintptr_t) &UCA0RXBUF);// Source block address__data20_write_long((uintptr_t) &DMA1DA,(uintptr_t) &RxString);// Destination single addressDMA1SZ = 1;// Block sizeDMA1CTL = DMADSTINCR_3+DMASBDB+DMALEVEL;// inc dstTxString = RxString = 0;// Clear TxString// Clear RxString__bis_SR_register(LPM3_bits + GIE);// Enter LPM3 w/ interrupts__no_operation();// Required only for debugger }//------------------------------------------------------------------------------ // Trigger DMA0 & DMA1 block transfer. //------------------------------------------------------------------------------ #if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector=WDT_VECTOR __interrupt void WDT_ISR(void) #elif defined(__GNUC__) void __attribute__ ((interrupt(WDT_VECTOR))) WDT_ISR (void) #else #error Compiler not supported! #endif {if(TxString-1 == RxString)P1OUT |= 0x01;// Set P1.0 if TrueelseP1OUT &= ~0x01;// Clear P1.0 if FalseTxString++;// Increment TxString counterDMA1CTL |= DMAEN;// DMA1 EnableDMA0CTL |= DMAEN;// DMA0 Enable }在msp430f5348a.h内使用的是
SFR_20BIT(DMA0SA); /* DMA Channel 0 Source Address */
所以在此使用的是 __data20_write_long
,
chang liu:
感谢你的回复。
你说的非常有道理,是应该使用20-bit地址长度的,我已改正。
但我查看内存map,我所使用的变量未超过16-bit,即我的问题应该与20-bit地址长度无关。我还需要继续查找原因。
还是非常感谢你。
,
Susan Yang:
好的,期待您的反馈
,
chang liu:
是我的代码出现问题了,与DMA和SPI无关。
望知晓,麻烦各位了。
感谢!