This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
额,我遇到的问题比较奇怪,我尽可能描述清楚问题。
我使用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次)会修改我栈中的数据,从而导致其它程序运行异常。
恳请各位帮助,不胜感激。
因此我在使用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) 的
按照我的理解,这样做应该是可行的。
是的,我也是这样认为的
但是偶然情况下(可能一天会出现1~2次)会修改我栈中的数据,从而导致其它程序运行异常。
能否详细说明一下?
非常感谢你的回复。
/* 此时不关心发送数据,因此禁止发送数据内存地址自增 */ __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) { /* 函数可以执行到这里,所以我严重怀疑栈数据出错!!! */ } }
建议您先参考下例程内的设置
/* --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 // --|RST XOUT|- // | | // | 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 timer SFRIE1 |= WDTIE; // Enable WDT interrupt P1OUT &= ~0x01; // Clear P1.0 P1DIR |= 0x01; // P1.0 = Output P3SEL |= 0x31; // P3.0,4,5 = USCI_A0 SPI Option UCA0CTL1 |= UCSWRST; // **Put state machine in reset** UCA0CTL0 = UCMST+UCSYNC+UCCKPL+UCMSB; // 3-pin, 8-bit SPI master // Clock polarity high, MSB UCA0CTL1 = UCSSEL_2; // SMCLK UCA0BR0 = 0x02; // /2 UCA0BR1 = 0x00; // UCA0MCTL = 0x00; // No modulation UCA0CTL1 &= ~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 address DMA0SZ = 1; // Block size DMA0CTL = 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 address DMA1SZ = 1; // Block size DMA1CTL = DMADSTINCR_3+DMASBDB+DMALEVEL; // inc dst TxString = 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 True else P1OUT &= ~0x01; // Clear P1.0 if False TxString++; // Increment TxString counter DMA1CTL |= DMAEN; // DMA1 Enable DMA0CTL |= DMAEN; // DMA0 Enable }
在msp430f5348a.h内使用的是
SFR_20BIT(DMA0SA); /* DMA Channel 0 Source Address */
所以在此使用的是 __data20_write_long
感谢你的回复。
你说的非常有道理,是应该使用20-bit地址长度的,我已改正。
但我查看内存map,我所使用的变量未超过16-bit,即我的问题应该与20-bit地址长度无关。我还需要继续查找原因。
还是非常感谢你。