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.
Part Number: MSP432P401R
Tool/software: Code Composer Studio
Hello!,
I am working with the MSP432 to collect data from an accelerometer through the DMA and send it through serial (UART) to my PC. It has been working well so far, until I added the EUSCI interrupt so that the MSP432 could read a byte sent from my PC. Since that moment, I cant read anything from the serial port at my PC and when I debug the code I have notice that after entering the EUSCI interrupt (when a byte is sent from my PC) the DMA interrupt stops working and there is no refreashing of data to buffer_1 and buffer_2 (refer to the code).
I am attaching the code below.
#include <ti/devices/msp432p4xx/inc/msp.h> #include <ti/devices/msp432p4xx/driverlib/driverlib.h> #include <ti/grlib/grlib.h> #include <stdio.h> #include <arm_math.h> #include <arm_const_structs.h> static DMA_ControlTable MSP_EXP432P401RLP_DMAControlTable[32]; /* DMA Control Table */ #if defined(__TI_COMPILER_VERSION__) #pragma DATA_ALIGN(MSP_EXP432P401RLP_DMAControlTable, 1024) #elif defined(__IAR_SYSTEMS_ICC__) #pragma data_alignment=1024 #elif defined(__GNUC__) __attribute__ ((aligned (1024))) #elif defined(__CC_ARM) __align(1024) #endif // ---------- Variables generales----------- // const char digits[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; #define SAMPLE_FREQUENCY 1000 #define SMCLK_FREQUENCY 48000000 static volatile uint16_t DMA_counter = 0; static volatile uint16_t ADC_counter = 0; static volatile uint16_t UART_counter = 0; volatile int mode = 1; volatile int flag = 0; volatile int size = 0; volatile int change_array = 0; volatile int UART_flag = 0; // ---------- FFT Parámetros ----------- // #define N_MUESTRAS 1024 uint32_t fftSize = N_MUESTRAS*4; uint32_t ifftFlag = 0; uint32_t BitReverse = 1; uint32_t max_freq_bin = 0; volatile arm_status status; // ---------- Inicialización de BUFFERS ----------- // float hanning[N_MUESTRAS*2]; int16_t data_buffer1[N_MUESTRAS]; int16_t data_buffer2[N_MUESTRAS]; int16_t data_fft[N_MUESTRAS*8]; int16_t data_out[N_MUESTRAS*4]; int16_t buffer4096[N_MUESTRAS*4]; //------ FIR -------// //#define N_TAPS 25 #define N_TAPS 38 int16_t filter_sum[1]; int16_t filter[1]; float coeff[N_TAPS] = { 0.0006f, 0.0005f, -0.0002f, -0.0016f, -0.0037f, -0.0065f, -0.0092f, -0.0110f, -0.0110f, -0.0082f, -0.0015f, 0.0093f, 0.0243f, 0.0424f, 0.0624f, 0.0821f, 0.0995f, 0.1124f, 0.1193f, 0.1193f, 0.1124f, 0.0995f, 0.0821f, 0.0624f, 0.0424f, 0.0243f, 0.0093f, -0.0015f, -0.0082f, -0.0110f, -0.0110f, -0.0092f, -0.0065f, -0.0037f, -0.0016f, -0.0002f, 0.0005f, 0.0006f }; //Para configurar los siguientes elementos se utilizará la libreria "driverlib". //Las referencias a MAP de esta libreria están en: dev.ti.com/.../rom__map_8h.html void CLOCK_Config(void) { // --------------------------- Configuración del CLOCK --------------------------- // //Elejimos la frecuencia de reloj SMCLK en DC0=48MHz con un prescalador igual a 1. MAP_PCM_setCoreVoltageLevel(PCM_VCORE1); MAP_FlashCtl_setWaitState(FLASH_BANK0, 2); MAP_FlashCtl_setWaitState(FLASH_BANK1, 2); //Elejimos la frecuencia de reloj general DCO en 48MHz. MAP_CS_setDCOCenteredFrequency(CS_DCO_FREQUENCY_48); //Elejimos la frecuencia de reloj SMCLK en DC0=48MHz con un prescalador igual a 1. MAP_CS_initClockSignal(CS_SMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1); //Elejimos la frecuencia de reloj MCLK en DC0=48MHz con un prescalador igual a 1. MAP_CS_initClockSignal(CS_MCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1); //Elejimos la frecuencia de reloj HSMCLK en DC0=48MHz con un prescalador igual a 1. MAP_CS_initClockSignal(CS_HSMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1); //Elejimos la frecuencia de reloj MCLK en REFOCLOCK=36.6KHz con un prescalador igual a 1. MAP_CS_initClockSignal(CS_ACLK, CS_REFOCLK_SELECT, CS_CLOCK_DIVIDER_1); } void GPIO_Config(void) { // --------------------------- Configuración de GPIO --------------------------- // //Para configurar el ADC de la Tarjeta 1 los puertos de entrada del ADC son P4.0 con canal A13. P4->SEL1 |= BIT0; P4->SEL0 |= BIT0; //Para configurar el ADC de la Tarjeta 2 los puertos de entrada del ADC son P6.0 con canal A15. P6->SEL1 |= BIT0; P6->SEL0 |= BIT0; //Para probar la frecuencia de salida de las interrupciones del ADC, se utiliza el pin P1.0 con salida digital. P1OUT &= ~BIT0; P1DIR |= BIT0; //Para transmitir los datos de forma serial, se elijen los pines P1.2 y P1.3 como TX Y RX respectivamente del UART. P1SEL0 |= BIT2 | BIT3; } const eUSCI_UART_Config uartConfig = { //57600 bps: EUSCI_A_UART_CLOCKSOURCE_SMCLK, // SMCLK Clock Source 52, // BRDIV = 52 1, // UCxBRF = 1 0, // UCxBRS = 0 EUSCI_A_UART_NO_PARITY, // No Parity EUSCI_A_UART_LSB_FIRST, // LSB First EUSCI_A_UART_ONE_STOP_BIT, // One stop bit EUSCI_A_UART_MODE, // UART mode EUSCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION // Oversampling }; void TIMER_Config(void) { // --------------------------- Configuración del TIMER --------------------------- // // Se configura el Timer para que tenga la señal de reloj como SMCLK de referencia, con un escalador de 1, modo de operación UP // Salida tipo SET-RESET y un periodo de cuenta igual a SMLCK/Frecuencia_de_Muestreo_Deseada. Timer_A_PWMConfig pwmConfig = {TIMER_A_CLOCKSOURCE_SMCLK, TIMER_A_CLOCKSOURCE_DIVIDER_1, (SMCLK_FREQUENCY/SAMPLE_FREQUENCY), TIMER_A_CAPTURECOMPARE_REGISTER_1, TIMER_A_OUTPUTMODE_SET_RESET, (SMCLK_FREQUENCY/SAMPLE_FREQUENCY)/2}; Timer_A_generatePWM(TIMER_A0_BASE, &pwmConfig); } void ADC_Config(void) { // --------------------------- Configuración del ADC --------------------------- // //Permite las operaciones de configuración en el ADC. ADC14_enableModule(); //Inicializa el ADC con el DCO=48MHz como reloj de referencia, con un prescalador igual a 1 y escalador igual a 1. ADC14_initModule(ADC_CLOCKSOURCE_MCLK, ADC_PREDIVIDER_1, ADC_DIVIDER_1, 0); //Se selecciona la salida del TIMER A0 como referencia de disparo para iniciar el muestreo, false = sin invertir la señal de entrada. ADC14_setSampleHoldTrigger(ADC_TRIGGER_SOURCE1, false); //Se selecciona el modo de operación de una sola muestra. Esto se debe a que el ADC iterará la adquisición de datos segun la señal externa de disparo de referencia. //Se escoge el espacio de memoria MEM0 para almacenar cada muestra del ADC, true = se repetirá la conversión al mismo espacio de memoria MEM0. ADC14_configureSingleSampleMode(ADC_MEM0, true); //Se configura el canal A13 del ADC que será muestreado y del cual se almacenará la información en MEM0, false = no se trabaja el ADC en modo diferencial. ADC14_configureConversionMemory(ADC_MEM0, ADC_VREFPOS_AVCC_VREFNEG_VSS, ADC_INPUT_A15, ADC_NONDIFFERENTIAL_INPUTS); //Se configura la resolución del ADC en 14 bits, esto implica que cada periodo de muestreo son 16 ciclos de reloj de clock. ADC14_setResolution(ADC_14BIT); } void DMA_Config(void) { // --------------------------- Configuración del DMA --------------------------- // //Permite las operaciones de configuración en el DMA. DMA_enableModule(); //Define la estructura de control del DMA. Esta tabla se encuentra en memoria. DMA_setControlBase(MSP_EXP432P401RLP_DMAControlTable); //Define la estructura de control del DMA. Esta tabla se encuentra en memoria. DMA_disableChannelAttribute(DMA_CH7_ADC14, UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK); MAP_DMA_setChannelControl(UDMA_PRI_SELECT | DMA_CH7_ADC14, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1); MAP_DMA_setChannelTransfer(UDMA_PRI_SELECT | DMA_CH7_ADC14, UDMA_MODE_PINGPONG, (void*) &ADC14->MEM[0], data_buffer1, N_MUESTRAS); MAP_DMA_setChannelControl(UDMA_ALT_SELECT | DMA_CH7_ADC14, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1); MAP_DMA_setChannelTransfer(UDMA_ALT_SELECT | DMA_CH7_ADC14, UDMA_MODE_PINGPONG, (void*) &ADC14->MEM[0], data_buffer2, N_MUESTRAS); //Configurar e inicializar interrupciones. MAP_DMA_assignInterrupt(DMA_INT1, 7); MAP_Interrupt_enableInterrupt(INT_DMA_INT1); MAP_DMA_assignChannel(DMA_CH7_ADC14); MAP_DMA_clearInterruptFlag(7); } void TransmitirDatos() { int j=0; for (j=0;j < size; j++) { while(!(UCA0IFG & UCTXIFG)); UCA0TXBUF = digits[(data_out[j])>>12]; while(!(UCA0IFG & UCTXIFG)); UCA0TXBUF = digits[0xF & ((data_out[j])>>8)]; while(!(UCA0IFG & UCTXIFG)); UCA0TXBUF = digits[0xF & ((data_out[j])>>4)]; while(!(UCA0IFG & UCTXIFG)); UCA0TXBUF = digits[0xF & ((data_out[j]))]; while(!(UCA0IFG & UCTXIFG)); UCA0TXBUF = '\n'; UART_counter++; } } int main(void) { // ---------- Funciones de configuración e inicialización del sistema ---------- // //Parar el reloj WDT. MAP_WDT_A_holdTimer(); MAP_Interrupt_disableMaster(); CLOCK_Config(); GPIO_Config(); TIMER_Config(); ADC_Config(); DMA_Config(); MAP_Interrupt_enableMaster(); MAP_DMA_enableChannel(7); MAP_ADC14_enableConversion(); MAP_UART_initModule(EUSCI_A0_BASE, &uartConfig); MAP_UART_enableModule(EUSCI_A0_BASE); MAP_UART_enableInterrupt(EUSCI_A0_BASE, EUSCI_A_UART_RECEIVE_INTERRUPT); MAP_Interrupt_enableInterrupt(INT_EUSCIA0); MAP_Interrupt_enableSleepOnIsrExit(); MAP_Interrupt_enableMaster(); //Inicializar Filtro FIR de tipo Hamming Window: //Referencia:www.allaboutcircuits.com/.../ int n; for(n = 0; n < N_MUESTRAS*2; n++) { hanning[n] = 0.5 - 0.5 * cosf((2 * PI * n) / ((N_MUESTRAS*2) - 1)); } while(1) { //Duerme hasta la interrupción del DMA. //Medido con el Ociloscoipo: Se envía el buffer de datos cada 1000ms. //P1->OUT = BIT0; MAP_PCM_gotoLPM0(); //P1->OUT &= ~BIT0; int i = 0; int j = 0; int z = 0; if (UART_flag == 1) { switch (mode) { case 1: { size = N_MUESTRAS; if(change_array & 1) { for(i = 0; i < N_MUESTRAS; i++) { data_out[i] = data_buffer1[i]; } TransmitirDatos(); } else { for(i = 0; i < N_MUESTRAS; i++) { data_out[i] = data_buffer2[i]; } TransmitirDatos(); } break; } case 2: { size = N_MUESTRAS; if(change_array & 1) { P1->OUT = BIT0; //81ms for(i=0; i < N_MUESTRAS; i++) { filter_sum[0] = 0; for(j=0; j < N_TAPS; j++) { if ((i-j)<0) { filter_sum[0]=data_buffer1[i]; } else { filter[0] = (int16_t)(coeff[j] * data_buffer1[i-j]); filter_sum[0] = filter_sum[0] + filter[0]; } } data_out[i] = filter_sum[0]; } P1->OUT &= ~BIT0; TransmitirDatos(); } else { //P1->OUT = BIT0; for(i=0; i < N_MUESTRAS; i++) { filter_sum[0] = 0; for(j=0; j < N_TAPS; j++) { if ((i-j)<0) { filter_sum[0]=data_buffer2[i]; } else { filter[0] = (int16_t)(coeff[j] * data_buffer2[i-j]); filter_sum[0] = filter_sum[0] + filter[0]; } } data_out[i] = filter_sum[0]; } //P1->OUT &= ~BIT0; TransmitirDatos(); } break; } case 3: { if(change_array & 1) { for(i=0; i < N_MUESTRAS; i++) { filter_sum[0] = 0; for(j=0; j < N_TAPS; j++) { if ((i-j)<0) { filter_sum[0]=data_buffer1[i]; } else { filter[0] = (int16_t)(coeff[j] * data_buffer1[i-j]); filter_sum[0] = filter_sum[0] + filter[0]; } } buffer4096[i] = filter_sum[0]; } } else { z=N_MUESTRAS; flag=1; for(i=0; i < N_MUESTRAS; i++) { filter_sum[0] = 0; for(j=0; j < N_TAPS; j++) { if ((i-j)<0) { filter_sum[0]=data_buffer2[i]; } else { filter[0] = (int16_t)(coeff[j] * data_buffer2[i-j]); filter_sum[0] = filter_sum[0] + filter[0]; } } buffer4096[z] = filter_sum[0]; z++; } } if (flag==1) { for(i = 0; i < N_MUESTRAS*2; i++) { buffer4096[i] = (int16_t)(hanning[i] * buffer4096[i]); } for(i = (N_MUESTRAS*2); i < N_MUESTRAS*4; i++) { buffer4096[i] = 0; } arm_rfft_instance_q15 instance; status = arm_rfft_init_q15(&instance, fftSize, ifftFlag, BitReverse); arm_rfft_q15(&instance, buffer4096, data_fft); for(i = 0; i < (N_MUESTRAS*4); i = i+2) { data_out[i/2] = (int16_t)(sqrtf((data_fft[i] * data_fft[i]) + (data_fft[i+1] * data_fft[i+1]))); } data_out[0]=15; data_out[1]=15; data_out[2]=15; data_out[3]=15; size = 205; TransmitirDatos(); flag=0; } break; } } } } } /* Completar una interrupción para ADC14 MEM0 */ void DMA_INT1_IRQHandler(void) { DMA_counter++; if(DMA_getChannelAttribute(7) & UDMA_ATTR_ALTSELECT) { change_array = 1; DMA_setChannelControl(UDMA_PRI_SELECT | DMA_CH7_ADC14, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1); DMA_setChannelTransfer(UDMA_PRI_SELECT | DMA_CH7_ADC14, UDMA_MODE_PINGPONG, (void*)&ADC14->MEM[0], data_buffer1, N_MUESTRAS); } else { change_array = 0; DMA_setChannelControl(UDMA_ALT_SELECT | DMA_CH7_ADC14, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1); DMA_setChannelTransfer(UDMA_ALT_SELECT | DMA_CH7_ADC14, UDMA_MODE_PINGPONG, (void*)&ADC14->MEM[0], data_buffer2, N_MUESTRAS); } } /* Completar una interrupción para EUSCIA0 */ void EUSCIA0_IRQHandler(void) { uint32_t status = MAP_UART_getEnabledInterruptStatus(EUSCI_A0_BASE); MAP_UART_clearInterruptFlag(EUSCI_A0_BASE, status); if(status & EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG) { //MAP_UART_transmitData(EUSCI_A0_BASE, MAP_UART_receiveData(EUSCI_A0_BASE)); if (MAP_UART_receiveData(EUSCI_A0_BASE)==65) { P1->OUT = BIT0; UART_flag=1; } else { P1->OUT &=~BIT0; UART_flag=0; } } }
I think it has to do with the order I am entering the interrupts configuration, but I am not sure.
Thanks a lot in advance.
David.
Thanks Bruce!,
I removed those lines but the problem still remains. I know now for sure that the UART interrupt is invalidating my DMA interrupt.
Is it because of the order of the interrupt initialization commands or is there another thing I am doing wrong?
Thanks for the help!
David.
David,
Can you provide some more details regarding what you mean by invalidating? Looking at your code I see some mistakes which I will comment on later, but nothing specific to your issue related to the interrupts. My suspicion is that the UART interrupt is continuously re-entered and that the DMA interrupt is never allowed to be serviced. The usage of the API, MAP_UART_clearInterruptFlag, within the uart isr is consistent with the example. I do have some concerns, which I think Bruce may have been alluding to with the transmit function which also checks the interrupt flags before loading the TXBUF. I think this would be more of an issue of overwriting the TX buffer and not related to the DMA isr.
Other comments:
(1) Flash wait states of 1 can be used with revision C and D silicon up to 48Mhz. Revision B silicon requires 2 wait states. Do not use revision B.
(2) Peripherals support a maximum frequency of 24Mhz (with the ADC actually supporting 25Mhz).
Chris
Hi Chris,
Thanks for the reply!
So, everything was working fine before I added the UART interrupt rutine to read a serial byte sent from my PC. At the begining The DMA interrupt works for a period of time and then after the UART interrupt it just stops working. Also, it shows me to a piece of code from the driverlib (picture).
What do you mean by overwriting the TX buffer? Right now I am getting non coherent values at my PC serial port.
This is my code so far:
#include <ti/devices/msp432p4xx/inc/msp.h> #include <ti/devices/msp432p4xx/driverlib/driverlib.h> #include <ti/grlib/grlib.h> #include <stdio.h> #include <arm_math.h> #include <arm_const_structs.h> static DMA_ControlTable MSP_EXP432P401RLP_DMAControlTable[32]; /* DMA Control Table */ #if defined(__TI_COMPILER_VERSION__) #pragma DATA_ALIGN(MSP_EXP432P401RLP_DMAControlTable, 1024) #elif defined(__IAR_SYSTEMS_ICC__) #pragma data_alignment=1024 #elif defined(__GNUC__) __attribute__ ((aligned (1024))) #elif defined(__CC_ARM) __align(1024) #endif // ---------- Variables generales----------- // const char digits[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; #define SAMPLE_FREQUENCY 1000 #define SMCLK_FREQUENCY 48000000 static volatile uint16_t DMA_counter = 0; static volatile uint16_t ADC_counter = 0; static volatile uint16_t UART_counter = 0; volatile int mode = 1; volatile int flag = 0; volatile int count_1 = 0; volatile int count_2 = 0; volatile int size = 0; volatile int change_array = 0; volatile int UART_flag = 0; // ---------- FFT Parámetros ----------- // #define N_MUESTRAS 1024 uint32_t fftSize = N_MUESTRAS*4; uint32_t ifftFlag = 0; uint32_t BitReverse = 1; uint32_t max_freq_bin = 0; volatile arm_status status; // ---------- Inicialización de BUFFERS ----------- // float hanning[N_MUESTRAS*2]; int16_t data_buffer1[N_MUESTRAS]; int16_t data_buffer2[N_MUESTRAS]; int16_t data_fft[N_MUESTRAS*8]; int16_t data_out[N_MUESTRAS*4]; int16_t buffer4096[N_MUESTRAS*4]; //------ FIR -------// //#define N_TAPS 25 #define N_TAPS 38 int16_t filter_sum[1]; int16_t filter[1]; float coeff[N_TAPS] = { 0.0006f, 0.0005f, -0.0002f, -0.0016f, -0.0037f, -0.0065f, -0.0092f, -0.0110f, -0.0110f, -0.0082f, -0.0015f, 0.0093f, 0.0243f, 0.0424f, 0.0624f, 0.0821f, 0.0995f, 0.1124f, 0.1193f, 0.1193f, 0.1124f, 0.0995f, 0.0821f, 0.0624f, 0.0424f, 0.0243f, 0.0093f, -0.0015f, -0.0082f, -0.0110f, -0.0110f, -0.0092f, -0.0065f, -0.0037f, -0.0016f, -0.0002f, 0.0005f, 0.0006f }; //Para configurar los siguientes elementos se utilizará la libreria "driverlib". //Las referencias a MAP de esta libreria están en: dev.ti.com/.../rom__map_8h.html void CLOCK_Config(void) { // --------------------------- Configuración del CLOCK --------------------------- // //Elejimos la frecuencia de reloj SMCLK en DC0=48MHz con un prescalador igual a 1. MAP_PCM_setCoreVoltageLevel(PCM_VCORE1); MAP_FlashCtl_setWaitState(FLASH_BANK0, 2); MAP_FlashCtl_setWaitState(FLASH_BANK1, 2); //Elejimos la frecuencia de reloj general DCO en 48MHz. MAP_CS_setDCOCenteredFrequency(CS_DCO_FREQUENCY_48); //Elejimos la frecuencia de reloj SMCLK en DC0=48MHz con un prescalador igual a 1. MAP_CS_initClockSignal(CS_SMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1); //Elejimos la frecuencia de reloj MCLK en DC0=48MHz con un prescalador igual a 1. MAP_CS_initClockSignal(CS_MCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1); //Elejimos la frecuencia de reloj HSMCLK en DC0=48MHz con un prescalador igual a 1. MAP_CS_initClockSignal(CS_HSMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1); //Elejimos la frecuencia de reloj MCLK en REFOCLOCK=36.6KHz con un prescalador igual a 1. MAP_CS_initClockSignal(CS_ACLK, CS_REFOCLK_SELECT, CS_CLOCK_DIVIDER_1); } void GPIO_Config(void) { // --------------------------- Configuración de GPIO --------------------------- // //Para configurar el ADC de la Tarjeta 1 los puertos de entrada del ADC son P4.0 con canal A13. P4->SEL1 |= BIT0; P4->SEL0 |= BIT0; //Para configurar el ADC de la Tarjeta 2 los puertos de entrada del ADC son P6.0 con canal A15. P6->SEL1 |= BIT0; P6->SEL0 |= BIT0; //Para probar la frecuencia de salida de las interrupciones del ADC, se utiliza el pin P1.0 con salida digital. P1OUT &= ~BIT0; P1DIR |= BIT0; //Para transmitir los datos de forma serial, se elijen los pines P1.2 y P1.3 como TX Y RX respectivamente del UART. P1SEL0 |= BIT2 | BIT3; } const eUSCI_UART_Config uartConfig = { //57600 bps: EUSCI_A_UART_CLOCKSOURCE_SMCLK, // SMCLK Clock Source 52, // BRDIV = 52 1, // UCxBRF = 1 0, // UCxBRS = 0 EUSCI_A_UART_NO_PARITY, // No Parity EUSCI_A_UART_LSB_FIRST, // LSB First EUSCI_A_UART_ONE_STOP_BIT, // One stop bit EUSCI_A_UART_MODE, // UART mode EUSCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION // Oversampling }; void TIMER_Config(void) { // --------------------------- Configuración del TIMER --------------------------- // // Se configura el Timer para que tenga la señal de reloj como SMCLK de referencia, con un escalador de 1, modo de operación UP // Salida tipo SET-RESET y un periodo de cuenta igual a SMLCK/Frecuencia_de_Muestreo_Deseada. Timer_A_PWMConfig pwmConfig = {TIMER_A_CLOCKSOURCE_SMCLK, TIMER_A_CLOCKSOURCE_DIVIDER_1, (SMCLK_FREQUENCY/SAMPLE_FREQUENCY), TIMER_A_CAPTURECOMPARE_REGISTER_1, TIMER_A_OUTPUTMODE_SET_RESET, (SMCLK_FREQUENCY/SAMPLE_FREQUENCY)/2}; Timer_A_generatePWM(TIMER_A0_BASE, &pwmConfig); } void ADC_Config(void) { // --------------------------- Configuración del ADC --------------------------- // //Permite las operaciones de configuración en el ADC. ADC14_enableModule(); //Inicializa el ADC con el DCO=48MHz como reloj de referencia, con un prescalador igual a 1 y escalador igual a 1. ADC14_initModule(ADC_CLOCKSOURCE_MCLK, ADC_PREDIVIDER_1, ADC_DIVIDER_1, 0); //Se selecciona la salida del TIMER A0 como referencia de disparo para iniciar el muestreo, false = sin invertir la señal de entrada. ADC14_setSampleHoldTrigger(ADC_TRIGGER_SOURCE1, false); //Se selecciona el modo de operación de una sola muestra. Esto se debe a que el ADC iterará la adquisición de datos segun la señal externa de disparo de referencia. //Se escoge el espacio de memoria MEM0 para almacenar cada muestra del ADC, true = se repetirá la conversión al mismo espacio de memoria MEM0. ADC14_configureSingleSampleMode(ADC_MEM0, true); //Se configura el canal A13 del ADC que será muestreado y del cual se almacenará la información en MEM0, false = no se trabaja el ADC en modo diferencial. ADC14_configureConversionMemory(ADC_MEM0, ADC_VREFPOS_AVCC_VREFNEG_VSS, ADC_INPUT_A15, ADC_NONDIFFERENTIAL_INPUTS); //Se configura la resolución del ADC en 14 bits, esto implica que cada periodo de muestreo son 16 ciclos de reloj de clock. ADC14_setResolution(ADC_14BIT); } void DMA_Config(void) { // --------------------------- Configuración del DMA --------------------------- // //Permite las operaciones de configuración en el DMA. DMA_enableModule(); //Define la estructura de control del DMA. Esta tabla se encuentra en memoria. DMA_setControlBase(MSP_EXP432P401RLP_DMAControlTable); //Define la estructura de control del DMA. Esta tabla se encuentra en memoria. DMA_disableChannelAttribute(DMA_CH7_ADC14, UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK); MAP_DMA_setChannelControl(UDMA_PRI_SELECT | DMA_CH7_ADC14, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1); MAP_DMA_setChannelTransfer(UDMA_PRI_SELECT | DMA_CH7_ADC14, UDMA_MODE_PINGPONG, (void*) &ADC14->MEM[0], data_buffer1, N_MUESTRAS); MAP_DMA_setChannelControl(UDMA_ALT_SELECT | DMA_CH7_ADC14, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1); MAP_DMA_setChannelTransfer(UDMA_ALT_SELECT | DMA_CH7_ADC14, UDMA_MODE_PINGPONG, (void*) &ADC14->MEM[0], data_buffer2, N_MUESTRAS); //Configurar e inicializar interrupciones. MAP_DMA_assignInterrupt(DMA_INT1, 7); MAP_Interrupt_enableInterrupt(INT_DMA_INT1); MAP_DMA_assignChannel(DMA_CH7_ADC14); MAP_DMA_clearInterruptFlag(7); } void TransmitirDatos() { int j=0; for (j=0;j < size; j++) { while(!(UCA0IFG & UCTXIFG)); UCA0TXBUF = digits[(data_out[j])>>12]; while(!(UCA0IFG & UCTXIFG)); UCA0TXBUF = digits[0xF & ((data_out[j])>>8)]; while(!(UCA0IFG & UCTXIFG)); UCA0TXBUF = digits[0xF & ((data_out[j])>>4)]; while(!(UCA0IFG & UCTXIFG)); UCA0TXBUF = digits[0xF & ((data_out[j]))]; while(!(UCA0IFG & UCTXIFG)); UCA0TXBUF = '\n'; UART_counter++; } } int main(void) { // ---------- Funciones de configuración e inicialización del sistema ---------- // //Parar el reloj WDT. MAP_WDT_A_holdTimer(); MAP_Interrupt_disableMaster(); CLOCK_Config(); GPIO_Config(); TIMER_Config(); ADC_Config(); DMA_Config(); MAP_Interrupt_enableMaster(); MAP_DMA_enableChannel(7); MAP_ADC14_enableConversion(); MAP_UART_initModule(EUSCI_A0_BASE, &uartConfig); MAP_UART_enableModule(EUSCI_A0_BASE); MAP_UART_enableInterrupt(EUSCI_A0_BASE, EUSCI_A_UART_RECEIVE_INTERRUPT); MAP_Interrupt_enableInterrupt(INT_EUSCIA0); //Inicializar Filtro FIR de tipo Hamming Window: //Referencia:www.allaboutcircuits.com/.../ int n; for(n = 0; n < N_MUESTRAS*2; n++) { hanning[n] = 0.5 - 0.5 * cosf((2 * PI * n) / ((N_MUESTRAS*2) - 1)); } while(1) { //Duerme hasta la interrupción del DMA. //Medido con el Ociloscoipo: Se envía el buffer de datos cada 1000ms. //P1->OUT = BIT0; MAP_PCM_gotoLPM0(); //P1->OUT &= ~BIT0; int i = 0; int j = 0; int z = 0; if (UART_flag == 1) { switch (mode) { case 1: { size = N_MUESTRAS; if(change_array & 1) { for(i = 0; i < N_MUESTRAS; i++) { data_out[i] = data_buffer1[i]; } count_1++; TransmitirDatos(); } else { for(i = 0; i < N_MUESTRAS; i++) { data_out[i] = data_buffer2[i]; } count_2++; TransmitirDatos(); } break; } case 2: { size = N_MUESTRAS; if(change_array & 1) { P1->OUT = BIT0; //81ms for(i=0; i < N_MUESTRAS; i++) { filter_sum[0] = 0; for(j=0; j < N_TAPS; j++) { if ((i-j)<0) { filter_sum[0]=data_buffer1[i]; } else { filter[0] = (int16_t)(coeff[j] * data_buffer1[i-j]); filter_sum[0] = filter_sum[0] + filter[0]; } } data_out[i] = filter_sum[0]; } P1->OUT &= ~BIT0; TransmitirDatos(); } else { //P1->OUT = BIT0; for(i=0; i < N_MUESTRAS; i++) { filter_sum[0] = 0; for(j=0; j < N_TAPS; j++) { if ((i-j)<0) { filter_sum[0]=data_buffer2[i]; } else { filter[0] = (int16_t)(coeff[j] * data_buffer2[i-j]); filter_sum[0] = filter_sum[0] + filter[0]; } } data_out[i] = filter_sum[0]; } //P1->OUT &= ~BIT0; TransmitirDatos(); } break; } case 3: { if(change_array & 1) { for(i=0; i < N_MUESTRAS; i++) { filter_sum[0] = 0; for(j=0; j < N_TAPS; j++) { if ((i-j)<0) { filter_sum[0]=data_buffer1[i]; } else { filter[0] = (int16_t)(coeff[j] * data_buffer1[i-j]); filter_sum[0] = filter_sum[0] + filter[0]; } } buffer4096[i] = filter_sum[0]; } } else { z=N_MUESTRAS; flag=1; for(i=0; i < N_MUESTRAS; i++) { filter_sum[0] = 0; for(j=0; j < N_TAPS; j++) { if ((i-j)<0) { filter_sum[0]=data_buffer2[i]; } else { filter[0] = (int16_t)(coeff[j] * data_buffer2[i-j]); filter_sum[0] = filter_sum[0] + filter[0]; } } buffer4096[z] = filter_sum[0]; z++; } } if (flag==1) { for(i = 0; i < N_MUESTRAS*2; i++) { buffer4096[i] = (int16_t)(hanning[i] * buffer4096[i]); } for(i = (N_MUESTRAS*2); i < N_MUESTRAS*4; i++) { buffer4096[i] = 0; } arm_rfft_instance_q15 instance; status = arm_rfft_init_q15(&instance, fftSize, ifftFlag, BitReverse); arm_rfft_q15(&instance, buffer4096, data_fft); for(i = 0; i < (N_MUESTRAS*4); i = i+2) { data_out[i/2] = (int16_t)(sqrtf((data_fft[i] * data_fft[i]) + (data_fft[i+1] * data_fft[i+1]))); } data_out[0]=15; data_out[1]=15; data_out[2]=15; data_out[3]=15; size = 205; TransmitirDatos(); flag=0; } break; } } } } } /* Completar una interrupción para ADC14 MEM0 */ void DMA_INT1_IRQHandler(void) { DMA_counter++; if(DMA_getChannelAttribute(7) & UDMA_ATTR_ALTSELECT) { change_array = 1; DMA_setChannelControl(UDMA_PRI_SELECT | DMA_CH7_ADC14, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1); DMA_setChannelTransfer(UDMA_PRI_SELECT | DMA_CH7_ADC14, UDMA_MODE_PINGPONG, (void*)&ADC14->MEM[0], data_buffer1, N_MUESTRAS); } else { change_array = 0; DMA_setChannelControl(UDMA_ALT_SELECT | DMA_CH7_ADC14, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1); DMA_setChannelTransfer(UDMA_ALT_SELECT | DMA_CH7_ADC14, UDMA_MODE_PINGPONG, (void*)&ADC14->MEM[0], data_buffer2, N_MUESTRAS); } } /* Completar una interrupción para EUSCIA0 */ void EUSCIA0_IRQHandler(void) { uint32_t status = MAP_UART_getEnabledInterruptStatus(EUSCI_A0_BASE); MAP_UART_clearInterruptFlag(EUSCI_A0_BASE, status); if(status & EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG) { //MAP_UART_transmitData(EUSCI_A0_BASE, MAP_UART_receiveData(EUSCI_A0_BASE)); if (MAP_UART_receiveData(EUSCI_A0_BASE)==65) { P1->OUT = BIT0; UART_flag=1; } else { P1->OUT &=~BIT0; UART_flag=0; } } }
Thanks for the help.
David.
Hi Chris,
Thanks for the reply!
So, everything was working fine before I added the UART interrupt rutine to read a serial byte sent from my PC. At the begining The DMA interrupt works for a period of time and then after the UART interrupt it just stops working. Also, it shows me to a piece of code from the driverlib (picture).
What do you mean by overwriting the TX buffer? Right now I am getting non coherent values at my PC serial port.
This is my code so far:
#include <ti/devices/msp432p4xx/inc/msp.h> #include <ti/devices/msp432p4xx/driverlib/driverlib.h> #include <ti/grlib/grlib.h> #include <stdio.h> #include <arm_math.h> #include <arm_const_structs.h> static DMA_ControlTable MSP_EXP432P401RLP_DMAControlTable[32]; /* DMA Control Table */ #if defined(__TI_COMPILER_VERSION__) #pragma DATA_ALIGN(MSP_EXP432P401RLP_DMAControlTable, 1024) #elif defined(__IAR_SYSTEMS_ICC__) #pragma data_alignment=1024 #elif defined(__GNUC__) __attribute__ ((aligned (1024))) #elif defined(__CC_ARM) __align(1024) #endif // ---------- Variables generales----------- // const char digits[]={'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; #define SAMPLE_FREQUENCY 1000 #define SMCLK_FREQUENCY 48000000 static volatile uint16_t DMA_counter = 0; static volatile uint16_t ADC_counter = 0; static volatile uint16_t UART_counter = 0; volatile int mode = 1; volatile int flag = 0; volatile int count_1 = 0; volatile int count_2 = 0; volatile int size = 0; volatile int change_array = 0; volatile int UART_flag = 0; // ---------- FFT Parámetros ----------- // #define N_MUESTRAS 1024 uint32_t fftSize = N_MUESTRAS*4; uint32_t ifftFlag = 0; uint32_t BitReverse = 1; uint32_t max_freq_bin = 0; volatile arm_status status; // ---------- Inicialización de BUFFERS ----------- // float hanning[N_MUESTRAS*2]; int16_t data_buffer1[N_MUESTRAS]; int16_t data_buffer2[N_MUESTRAS]; int16_t data_fft[N_MUESTRAS*8]; int16_t data_out[N_MUESTRAS*4]; int16_t buffer4096[N_MUESTRAS*4]; //------ FIR -------// //#define N_TAPS 25 #define N_TAPS 38 int16_t filter_sum[1]; int16_t filter[1]; float coeff[N_TAPS] = { 0.0006f, 0.0005f, -0.0002f, -0.0016f, -0.0037f, -0.0065f, -0.0092f, -0.0110f, -0.0110f, -0.0082f, -0.0015f, 0.0093f, 0.0243f, 0.0424f, 0.0624f, 0.0821f, 0.0995f, 0.1124f, 0.1193f, 0.1193f, 0.1124f, 0.0995f, 0.0821f, 0.0624f, 0.0424f, 0.0243f, 0.0093f, -0.0015f, -0.0082f, -0.0110f, -0.0110f, -0.0092f, -0.0065f, -0.0037f, -0.0016f, -0.0002f, 0.0005f, 0.0006f }; //Para configurar los siguientes elementos se utilizará la libreria "driverlib". //Las referencias a MAP de esta libreria están en: dev.ti.com/.../rom__map_8h.html void CLOCK_Config(void) { // --------------------------- Configuración del CLOCK --------------------------- // //Elejimos la frecuencia de reloj SMCLK en DC0=48MHz con un prescalador igual a 1. MAP_PCM_setCoreVoltageLevel(PCM_VCORE1); MAP_FlashCtl_setWaitState(FLASH_BANK0, 2); MAP_FlashCtl_setWaitState(FLASH_BANK1, 2); //Elejimos la frecuencia de reloj general DCO en 48MHz. MAP_CS_setDCOCenteredFrequency(CS_DCO_FREQUENCY_48); //Elejimos la frecuencia de reloj SMCLK en DC0=48MHz con un prescalador igual a 1. MAP_CS_initClockSignal(CS_SMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1); //Elejimos la frecuencia de reloj MCLK en DC0=48MHz con un prescalador igual a 1. MAP_CS_initClockSignal(CS_MCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1); //Elejimos la frecuencia de reloj HSMCLK en DC0=48MHz con un prescalador igual a 1. MAP_CS_initClockSignal(CS_HSMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1); //Elejimos la frecuencia de reloj MCLK en REFOCLOCK=36.6KHz con un prescalador igual a 1. MAP_CS_initClockSignal(CS_ACLK, CS_REFOCLK_SELECT, CS_CLOCK_DIVIDER_1); } void GPIO_Config(void) { // --------------------------- Configuración de GPIO --------------------------- // //Para configurar el ADC de la Tarjeta 1 los puertos de entrada del ADC son P4.0 con canal A13. P4->SEL1 |= BIT0; P4->SEL0 |= BIT0; //Para configurar el ADC de la Tarjeta 2 los puertos de entrada del ADC son P6.0 con canal A15. P6->SEL1 |= BIT0; P6->SEL0 |= BIT0; //Para probar la frecuencia de salida de las interrupciones del ADC, se utiliza el pin P1.0 con salida digital. P1OUT &= ~BIT0; P1DIR |= BIT0; //Para transmitir los datos de forma serial, se elijen los pines P1.2 y P1.3 como TX Y RX respectivamente del UART. P1SEL0 |= BIT2 | BIT3; } const eUSCI_UART_Config uartConfig = { //57600 bps: EUSCI_A_UART_CLOCKSOURCE_SMCLK, // SMCLK Clock Source 52, // BRDIV = 52 1, // UCxBRF = 1 0, // UCxBRS = 0 EUSCI_A_UART_NO_PARITY, // No Parity EUSCI_A_UART_LSB_FIRST, // LSB First EUSCI_A_UART_ONE_STOP_BIT, // One stop bit EUSCI_A_UART_MODE, // UART mode EUSCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION // Oversampling }; void TIMER_Config(void) { // --------------------------- Configuración del TIMER --------------------------- // // Se configura el Timer para que tenga la señal de reloj como SMCLK de referencia, con un escalador de 1, modo de operación UP // Salida tipo SET-RESET y un periodo de cuenta igual a SMLCK/Frecuencia_de_Muestreo_Deseada. Timer_A_PWMConfig pwmConfig = {TIMER_A_CLOCKSOURCE_SMCLK, TIMER_A_CLOCKSOURCE_DIVIDER_1, (SMCLK_FREQUENCY/SAMPLE_FREQUENCY), TIMER_A_CAPTURECOMPARE_REGISTER_1, TIMER_A_OUTPUTMODE_SET_RESET, (SMCLK_FREQUENCY/SAMPLE_FREQUENCY)/2}; Timer_A_generatePWM(TIMER_A0_BASE, &pwmConfig); } void ADC_Config(void) { // --------------------------- Configuración del ADC --------------------------- // //Permite las operaciones de configuración en el ADC. ADC14_enableModule(); //Inicializa el ADC con el DCO=48MHz como reloj de referencia, con un prescalador igual a 1 y escalador igual a 1. ADC14_initModule(ADC_CLOCKSOURCE_MCLK, ADC_PREDIVIDER_1, ADC_DIVIDER_1, 0); //Se selecciona la salida del TIMER A0 como referencia de disparo para iniciar el muestreo, false = sin invertir la señal de entrada. ADC14_setSampleHoldTrigger(ADC_TRIGGER_SOURCE1, false); //Se selecciona el modo de operación de una sola muestra. Esto se debe a que el ADC iterará la adquisición de datos segun la señal externa de disparo de referencia. //Se escoge el espacio de memoria MEM0 para almacenar cada muestra del ADC, true = se repetirá la conversión al mismo espacio de memoria MEM0. ADC14_configureSingleSampleMode(ADC_MEM0, true); //Se configura el canal A13 del ADC que será muestreado y del cual se almacenará la información en MEM0, false = no se trabaja el ADC en modo diferencial. ADC14_configureConversionMemory(ADC_MEM0, ADC_VREFPOS_AVCC_VREFNEG_VSS, ADC_INPUT_A15, ADC_NONDIFFERENTIAL_INPUTS); //Se configura la resolución del ADC en 14 bits, esto implica que cada periodo de muestreo son 16 ciclos de reloj de clock. ADC14_setResolution(ADC_14BIT); } void DMA_Config(void) { // --------------------------- Configuración del DMA --------------------------- // //Permite las operaciones de configuración en el DMA. DMA_enableModule(); //Define la estructura de control del DMA. Esta tabla se encuentra en memoria. DMA_setControlBase(MSP_EXP432P401RLP_DMAControlTable); //Define la estructura de control del DMA. Esta tabla se encuentra en memoria. DMA_disableChannelAttribute(DMA_CH7_ADC14, UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK); MAP_DMA_setChannelControl(UDMA_PRI_SELECT | DMA_CH7_ADC14, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1); MAP_DMA_setChannelTransfer(UDMA_PRI_SELECT | DMA_CH7_ADC14, UDMA_MODE_PINGPONG, (void*) &ADC14->MEM[0], data_buffer1, N_MUESTRAS); MAP_DMA_setChannelControl(UDMA_ALT_SELECT | DMA_CH7_ADC14, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1); MAP_DMA_setChannelTransfer(UDMA_ALT_SELECT | DMA_CH7_ADC14, UDMA_MODE_PINGPONG, (void*) &ADC14->MEM[0], data_buffer2, N_MUESTRAS); //Configurar e inicializar interrupciones. MAP_DMA_assignInterrupt(DMA_INT1, 7); MAP_Interrupt_enableInterrupt(INT_DMA_INT1); MAP_DMA_assignChannel(DMA_CH7_ADC14); MAP_DMA_clearInterruptFlag(7); } void TransmitirDatos() { int j=0; for (j=0;j < size; j++) { while(!(UCA0IFG & UCTXIFG)); UCA0TXBUF = digits[(data_out[j])>>12]; while(!(UCA0IFG & UCTXIFG)); UCA0TXBUF = digits[0xF & ((data_out[j])>>8)]; while(!(UCA0IFG & UCTXIFG)); UCA0TXBUF = digits[0xF & ((data_out[j])>>4)]; while(!(UCA0IFG & UCTXIFG)); UCA0TXBUF = digits[0xF & ((data_out[j]))]; while(!(UCA0IFG & UCTXIFG)); UCA0TXBUF = '\n'; UART_counter++; } } int main(void) { // ---------- Funciones de configuración e inicialización del sistema ---------- // //Parar el reloj WDT. MAP_WDT_A_holdTimer(); MAP_Interrupt_disableMaster(); CLOCK_Config(); GPIO_Config(); TIMER_Config(); ADC_Config(); DMA_Config(); MAP_Interrupt_enableMaster(); MAP_DMA_enableChannel(7); MAP_ADC14_enableConversion(); MAP_UART_initModule(EUSCI_A0_BASE, &uartConfig); MAP_UART_enableModule(EUSCI_A0_BASE); MAP_UART_enableInterrupt(EUSCI_A0_BASE, EUSCI_A_UART_RECEIVE_INTERRUPT); MAP_Interrupt_enableInterrupt(INT_EUSCIA0); //Inicializar Filtro FIR de tipo Hamming Window: //Referencia:www.allaboutcircuits.com/.../ int n; for(n = 0; n < N_MUESTRAS*2; n++) { hanning[n] = 0.5 - 0.5 * cosf((2 * PI * n) / ((N_MUESTRAS*2) - 1)); } while(1) { //Duerme hasta la interrupción del DMA. //Medido con el Ociloscoipo: Se envía el buffer de datos cada 1000ms. //P1->OUT = BIT0; MAP_PCM_gotoLPM0(); //P1->OUT &= ~BIT0; int i = 0; int j = 0; int z = 0; if (UART_flag == 1) { switch (mode) { case 1: { size = N_MUESTRAS; if(change_array & 1) { for(i = 0; i < N_MUESTRAS; i++) { data_out[i] = data_buffer1[i]; } count_1++; TransmitirDatos(); } else { for(i = 0; i < N_MUESTRAS; i++) { data_out[i] = data_buffer2[i]; } count_2++; TransmitirDatos(); } break; } case 2: { size = N_MUESTRAS; if(change_array & 1) { P1->OUT = BIT0; //81ms for(i=0; i < N_MUESTRAS; i++) { filter_sum[0] = 0; for(j=0; j < N_TAPS; j++) { if ((i-j)<0) { filter_sum[0]=data_buffer1[i]; } else { filter[0] = (int16_t)(coeff[j] * data_buffer1[i-j]); filter_sum[0] = filter_sum[0] + filter[0]; } } data_out[i] = filter_sum[0]; } P1->OUT &= ~BIT0; TransmitirDatos(); } else { //P1->OUT = BIT0; for(i=0; i < N_MUESTRAS; i++) { filter_sum[0] = 0; for(j=0; j < N_TAPS; j++) { if ((i-j)<0) { filter_sum[0]=data_buffer2[i]; } else { filter[0] = (int16_t)(coeff[j] * data_buffer2[i-j]); filter_sum[0] = filter_sum[0] + filter[0]; } } data_out[i] = filter_sum[0]; } //P1->OUT &= ~BIT0; TransmitirDatos(); } break; } case 3: { if(change_array & 1) { for(i=0; i < N_MUESTRAS; i++) { filter_sum[0] = 0; for(j=0; j < N_TAPS; j++) { if ((i-j)<0) { filter_sum[0]=data_buffer1[i]; } else { filter[0] = (int16_t)(coeff[j] * data_buffer1[i-j]); filter_sum[0] = filter_sum[0] + filter[0]; } } buffer4096[i] = filter_sum[0]; } } else { z=N_MUESTRAS; flag=1; for(i=0; i < N_MUESTRAS; i++) { filter_sum[0] = 0; for(j=0; j < N_TAPS; j++) { if ((i-j)<0) { filter_sum[0]=data_buffer2[i]; } else { filter[0] = (int16_t)(coeff[j] * data_buffer2[i-j]); filter_sum[0] = filter_sum[0] + filter[0]; } } buffer4096[z] = filter_sum[0]; z++; } } if (flag==1) { for(i = 0; i < N_MUESTRAS*2; i++) { buffer4096[i] = (int16_t)(hanning[i] * buffer4096[i]); } for(i = (N_MUESTRAS*2); i < N_MUESTRAS*4; i++) { buffer4096[i] = 0; } arm_rfft_instance_q15 instance; status = arm_rfft_init_q15(&instance, fftSize, ifftFlag, BitReverse); arm_rfft_q15(&instance, buffer4096, data_fft); for(i = 0; i < (N_MUESTRAS*4); i = i+2) { data_out[i/2] = (int16_t)(sqrtf((data_fft[i] * data_fft[i]) + (data_fft[i+1] * data_fft[i+1]))); } data_out[0]=15; data_out[1]=15; data_out[2]=15; data_out[3]=15; size = 205; TransmitirDatos(); flag=0; } break; } } } } } /* Completar una interrupción para ADC14 MEM0 */ void DMA_INT1_IRQHandler(void) { DMA_counter++; if(DMA_getChannelAttribute(7) & UDMA_ATTR_ALTSELECT) { change_array = 1; DMA_setChannelControl(UDMA_PRI_SELECT | DMA_CH7_ADC14, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1); DMA_setChannelTransfer(UDMA_PRI_SELECT | DMA_CH7_ADC14, UDMA_MODE_PINGPONG, (void*)&ADC14->MEM[0], data_buffer1, N_MUESTRAS); } else { change_array = 0; DMA_setChannelControl(UDMA_ALT_SELECT | DMA_CH7_ADC14, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1); DMA_setChannelTransfer(UDMA_ALT_SELECT | DMA_CH7_ADC14, UDMA_MODE_PINGPONG, (void*)&ADC14->MEM[0], data_buffer2, N_MUESTRAS); } } /* Completar una interrupción para EUSCIA0 */ void EUSCIA0_IRQHandler(void) { uint32_t status = MAP_UART_getEnabledInterruptStatus(EUSCI_A0_BASE); MAP_UART_clearInterruptFlag(EUSCI_A0_BASE, status); if(status & EUSCI_A_UART_RECEIVE_INTERRUPT_FLAG) { //MAP_UART_transmitData(EUSCI_A0_BASE, MAP_UART_receiveData(EUSCI_A0_BASE)); if (MAP_UART_receiveData(EUSCI_A0_BASE)==65) { P1->OUT = BIT0; UART_flag=1; } else { P1->OUT &=~BIT0; UART_flag=0; } } }
Thanks for the help.
David.
/****************************************************************************** * * Copyright (C) 2012 - 2017 Texas Instruments Incorporated - http://www.ti.com/ * * 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. * * MSP432 SimpleLink C:\ti\simplelink_msp432p4_sdk_1_50_00_12 * *****************************************************************************/ /******************************************************************************* * MSP432 ADC14 - Single Channel Continuous Sample w/ Timer_A Trigger * * Description: In this ADC14 code example, a single input channel is sampled * using the standard reference specified in the reference definition and * configuration variable. The ADC is setup to continuously sample/convert * from A10. The sample-and hold time and the source of the sample trigger is * provided by Timer_A0. Capture Compare Register 0 (CCR0) defines the sample * period while CCR1 defines the sample-hold time. The CCR0 value is 23 and * CCR1 is set to 19, resulting in a sample period of 1us. * The ADC is setup to perform repeated single-channel measurements of channel * A10. * The DMA moves the results from the ADC to the resultsBuffer and * destination pointer is maintained in the DMA ISR. * * Timer_A0 is started once the GPIO interrupt for P1.4 is serviced. Upon * completion the array resultsBuffer is transmitted via UART. * * MSP-EXP432P401 * ------------------ * /|\| | * | | |<--- P5.6 (Veref+) * | | |<--- P5.7 (Veref-) * | | | * --|RST P4.2 |<--- A11 (Analog Input) * | P4.3 |<--- A10 (Analog Input) * | | * | P1.4 |<--- GPIO trigger to Start conversions * | | * | P1.0 |---> Debug port to show GPIO ISR * | P1.2 |<--- UART Rx * | P1.3 |---> UART Tx * | P2.0 |---> Debug port to show DMA ISR * | P2.4 |---> Debug TA0.1, ADC trigger * | | * * Author: Timothy Logan/ C. Sterzik ******************************************************************************/ /* DriverLib Includes */ #include <ti/devices/msp432p4xx/driverlib/driverlib.h> #include <arm_math.h> /* Standard Includes */ #include <stdint.h> #include <stdbool.h> #include <testConfig.h> //#define DEBUG //#define ARRAY_LENGTH 8192 #define ARRAY_LENGTH 16384 //#define NUMBER_OF_DMA_PING_PONGS 7 // ARRAY_LENGTH/1024 -1 #define NUMBER_OF_DMA_PING_PONGS 15 // ARRAY_LENGTH/1024 -1 #define REMAINDER ARRAY_LENGTH-(1024*NUMBER_OF_DMA_PING_PONGS) #define ADC_REFERENCE_VALUE 2.5 //#define ADC_REFERENCE_VALUE 1.45 //#define ADC_REFERENCE_VALUE 1.2 //#define ADC_REFERENCE_VALUE 3.3 const ADC_test_Config tstConfiguration = { // .selectClkConfig = ADCOSC_SMCLK_MCLK_DCO, // .selectClkConfig = SMCLK_SMCLK_MCLK_DCO, .selectClkConfig = SMCLK_SMCLK_MCLK_HFXT, // .selectRefConfig = VREF_AVCC .selectRefConfig = VREF_EXT // .selectRefConfig = VREF_INT_2_5 // .selectRefConfig = VREF_INT_1_45 // .selectRefConfig = VREF_INT_1_2 }; /* * UART Config * * SMCLK = 24Mhz * Baud = 9600 */ const eUSCI_UART_Config uartConfig = { EUSCI_A_UART_CLOCKSOURCE_SMCLK, // SMCLK Clock Source 156, // BRDIV = 6 4, // UCxBRF = 8 0, // UCxBRS = 0x20 EUSCI_A_UART_NO_PARITY, // No Parity EUSCI_A_UART_LSB_FIRST, // LSB First EUSCI_A_UART_ONE_STOP_BIT, // One stop bit EUSCI_A_UART_MODE, // UART mode EUSCI_A_UART_OVERSAMPLING_BAUDRATE_GENERATION // Oversampling }; /* * Timer_A Compare Configuration Parameter * CCR1 is used to trigger the ADC14, conversion time * is defined by the resolution * 14bit -> 16 cycles + 1 cycle (SLAU356d, 20.2.8.3) * * In this example, 14-bit resolution at 24Mhz ~708ns conversion time * Sample time is defined by 5 ADC clocks, pulse sample mode * Sample period is 24/24Mhz = 1us */ const Timer_A_PWMConfig timerA_PWM = { .clockSource = TIMER_A_CLOCKSOURCE_SMCLK, .clockSourceDivider = TIMER_A_CLOCKSOURCE_DIVIDER_1, .timerPeriod = 23, .compareRegister = TIMER_A_CAPTURECOMPARE_REGISTER_1, .compareOutputMode = TIMER_A_OUTPUTMODE_SET_RESET, .dutyCycle = 19 }; /* DMA Control Table */ #if defined(__TI_COMPILER_VERSION__) #pragma DATA_ALIGN(MSP_EXP432P401RLP_DMAControlTable, 1024) #elif defined(__IAR_SYSTEMS_ICC__) #pragma data_alignment=1024 #elif defined(__GNUC__) __attribute__ ((aligned (1024))) #elif defined(__CC_ARM) __align(1024) #endif static DMA_ControlTable MSP_EXP432P401RLP_DMAControlTable[16]; void configure_UART(void); /* Statics */ q15_t resultsBuffer[ARRAY_LENGTH]; uint8_t pingPongCounter; uint16_t arrayOffset; uint32_t arraySize, arrayMode; int main(void) { bool hfxtResult; /* Halting WDT */ MAP_WDT_A_holdTimer(); MAP_Interrupt_enableSleepOnIsrExit(); /* Terminating all remaining pins to minimize power consumption. This is done by register accesses for simplicity and to minimize branching API calls */ MAP_GPIO_setAsOutputPin(GPIO_PORT_P1, PIN_ALL8); MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, PIN_ALL8); MAP_GPIO_setAsOutputPin(GPIO_PORT_PB, PIN_ALL16); MAP_GPIO_setAsOutputPin(GPIO_PORT_PC, PIN_ALL16); MAP_GPIO_setAsOutputPin(GPIO_PORT_PD, PIN_ALL16); MAP_GPIO_setAsOutputPin(GPIO_PORT_PE, PIN_ALL16); MAP_GPIO_setAsOutputPin(GPIO_PORT_PJ, GPIO_PIN0 | GPIO_PIN1); MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P1, PIN_ALL8); MAP_GPIO_setOutputLowOnPin(GPIO_PORT_P2, PIN_ALL8); MAP_GPIO_setOutputLowOnPin(GPIO_PORT_PB, PIN_ALL16); MAP_GPIO_setOutputLowOnPin(GPIO_PORT_PC, PIN_ALL16); MAP_GPIO_setOutputLowOnPin(GPIO_PORT_PD, PIN_ALL16); MAP_GPIO_setOutputLowOnPin(GPIO_PORT_PE, PIN_ALL16); MAP_GPIO_setOutputLowOnPin(GPIO_PORT_PJ, GPIO_PIN0 | GPIO_PIN1); /* Configuring pins for peripheral/crystal usage and LED for output */ MAP_GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_PJ, GPIO_PIN3 | GPIO_PIN2, GPIO_PRIMARY_MODULE_FUNCTION); /* * Revision C silicon supports wait states of 1 at 48Mhz */ MAP_PCM_setCoreVoltageLevel(PCM_VCORE1); MAP_PCM_setPowerMode(PCM_DCDC_MODE); MAP_FlashCtl_setWaitState(FLASH_BANK0, 1); MAP_FlashCtl_setWaitState(FLASH_BANK1, 1); /* * Setting up clocks * MCLK = MCLK = 48MHz * SMCLK = MCLK/2 = 24Mhz * ACLK = REFO = 32Khz * */ if(tstConfiguration.selectClkConfig == SMCLK_SMCLK_MCLK_HFXT) { CS_setExternalClockSourceFrequency(32000,48000000); hfxtResult = CS_startHFXTWithTimeout(false,100000); if(hfxtResult == true) { /* Initializing MCLK to HFXT (effectively 48MHz) */ MAP_CS_initClockSignal(CS_ACLK, CS_REFOCLK_SELECT, CS_CLOCK_DIVIDER_1); MAP_CS_initClockSignal(CS_SMCLK, CS_HFXTCLK_SELECT, CS_CLOCK_DIVIDER_2); MAP_CS_initClockSignal(CS_MCLK, CS_HFXTCLK_SELECT, CS_CLOCK_DIVIDER_1); //![Simple CS Config] } else { while(1); // HFXT failed } } else { MAP_CS_setDCOFrequency(48000000); /* Initializing MCLK to HFXT (effectively 48MHz) */ MAP_CS_initClockSignal(CS_ACLK, CS_REFOCLK_SELECT, CS_CLOCK_DIVIDER_1); MAP_CS_initClockSignal(CS_SMCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_2); MAP_CS_initClockSignal(CS_MCLK, CS_DCOCLK_SELECT, CS_CLOCK_DIVIDER_1); //![Simple CS Config] } #ifdef DEBUG /* * Debug * Configuring P1.0, P2.0, and P2.1 as outputs */ P1OUT &= ~BIT0; MAP_GPIO_setAsOutputPin(GPIO_PORT_P1, GPIO_PIN0); P2OUT &= ~(BIT0+BIT1); MAP_GPIO_setAsOutputPin(GPIO_PORT_P2, GPIO_PIN0 | GPIO_PIN1); #endif /* * Configuring GPIOs (P4.2 A11) * P4.3 is A10, A10+ * P4.2 is A11, A10- * * Dedicated Pins * P4.6 is A7 A6- * P4.7 is A6 A6+ * */ MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P4, GPIO_PIN2 | GPIO_PIN3, GPIO_TERTIARY_MODULE_FUNCTION); // MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P4, GPIO_PIN6 | GPIO_PIN7, // GPIO_TERTIARY_MODULE_FUNCTION); /* * Debug: set TA0.1 as output to see ADC trigger signal */ #ifdef DEBUG MAP_GPIO_setAsPeripheralModuleFunctionOutputPin(GPIO_PORT_P2, GPIO_PIN4, GPIO_PRIMARY_MODULE_FUNCTION); #endif /* * Configuring P1.4 as an input and enabling interrupt, the timer is started from * GPIO ISR. */ MAP_GPIO_setAsInputPinWithPullUpResistor(GPIO_PORT_P1, GPIO_PIN4); MAP_GPIO_interruptEdgeSelect(GPIO_PORT_P1,GPIO_PIN4,GPIO_HIGH_TO_LOW_TRANSITION); MAP_GPIO_clearInterruptFlag(GPIO_PORT_P1, GPIO_PIN4); MAP_GPIO_enableInterrupt(GPIO_PORT_P1, GPIO_PIN4); configure_UART(); if(tstConfiguration.selectRefConfig > VREF_EXT) { if(tstConfiguration.selectRefConfig == VREF_INT_1_2) { MAP_REF_A_setReferenceVoltage(REF_A_VREF1_2V); } if(tstConfiguration.selectRefConfig == VREF_INT_1_45) { MAP_REF_A_setReferenceVoltage(REF_A_VREF1_45V); } if(tstConfiguration.selectRefConfig == VREF_INT_2_5) { MAP_REF_A_setReferenceVoltage(REF_A_VREF2_5V); } MAP_REF_A_enableReferenceVoltage(); } /* * Initializing ADC * Clock source either 25Mhz ADCOSC or 24Mhs SMCLK (sources from either DCO or HFXT) * 14-bit mode by default * Conversion mode is differential signed binary and treated as q15_t. * Result is placed into memory location ADC14MEM0 * Reference selectable from Internal (AVcc, Vref_A) or external */ MAP_ADC14_enableModule(); if(tstConfiguration.selectClkConfig == ADCOSC_SMCLK_MCLK_DCO) { MAP_ADC14_initModule(ADC_CLOCKSOURCE_ADCOSC, ADC_PREDIVIDER_1, ADC_DIVIDER_1, 0); } else { MAP_ADC14_initModule(ADC_CLOCKSOURCE_SMCLK, ADC_PREDIVIDER_1, ADC_DIVIDER_1, 0); } /* * Configuring ADC Memory, repeat-single-channel, A0 */ MAP_ADC14_configureSingleSampleMode(ADC_MEM0, true); /* * Configuring ADC Memory, reference, and differential conversion * A10 goes to mem0 */ if(tstConfiguration.selectRefConfig == VREF_EXT) { /* * Configure GPIO. P5.6 (Veref+) and P5.7 (Veref-) */ MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P5, GPIO_PIN6 | GPIO_PIN7, GPIO_TERTIARY_MODULE_FUNCTION); MAP_ADC14_configureConversionMemory(ADC_MEM0,ADC_VREFPOS_EXTPOS_VREFNEG_EXTNEG, ADC_INPUT_A10, ADC_DIFFERENTIAL_INPUTS); // MAP_ADC14_configureConversionMemory(ADC_MEM0,ADC_VREFPOS_EXTPOS_VREFNEG_EXTNEG, // ADC_INPUT_A6, ADC_DIFFERENTIAL_INPUTS); } else if(tstConfiguration.selectRefConfig == VREF_AVCC) { MAP_ADC14_configureConversionMemory(ADC_MEM0,ADC_VREFPOS_AVCC_VREFNEG_VSS, ADC_INPUT_A10, ADC_DIFFERENTIAL_INPUTS); // MAP_ADC14_configureConversionMemory(ADC_MEM0,ADC_VREFPOS_AVCC_VREFNEG_VSS, // ADC_INPUT_A6, ADC_DIFFERENTIAL_INPUTS); } else { MAP_ADC14_configureConversionMemory(ADC_MEM0,ADC_VREFPOS_INTBUF_VREFNEG_VSS, ADC_INPUT_A10, ADC_DIFFERENTIAL_INPUTS); // MAP_ADC14_configureConversionMemory(ADC_MEM0,ADC_VREFPOS_INTBUF_VREFNEG_VSS, // ADC_INPUT_A6, ADC_DIFFERENTIAL_INPUTS); } MAP_ADC14_setResultFormat(ADC_SIGNED_BINARY); /* * Configuring the sample trigger to be sourced from Timer_A0 CCR1 and on the * rising edge, default samplemode is extended (SHP=0) */ MAP_ADC14_setSampleHoldTrigger(ADC_TRIGGER_SOURCE1, false); /* Enabling conversions */ MAP_ADC14_enableConversion(); /* Configuring DMA module */ MAP_DMA_enableModule(); MAP_DMA_setControlBase(MSP_EXP432P401RLP_DMAControlTable); /* * Setup the DMA + ADC14 interface */ MAP_DMA_disableChannelAttribute(DMA_CH7_ADC14, UDMA_ATTR_ALTSELECT | UDMA_ATTR_USEBURST | UDMA_ATTR_HIGH_PRIORITY | UDMA_ATTR_REQMASK); /* * Setting Control Indexes. In this case we will set the source of the * DMA transfer to ADC14 Memory 0 and the destination to the destination * data array. */ MAP_DMA_setChannelControl(UDMA_PRI_SELECT | DMA_CH7_ADC14, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1); MAP_DMA_setChannelTransfer(UDMA_PRI_SELECT | DMA_CH7_ADC14, UDMA_MODE_PINGPONG, (void*) &ADC14->MEM[0], (void*)resultsBuffer, 1024); MAP_DMA_setChannelControl(UDMA_ALT_SELECT | DMA_CH7_ADC14, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1); MAP_DMA_setChannelTransfer(UDMA_ALT_SELECT | DMA_CH7_ADC14, UDMA_MODE_PINGPONG, (void*) &ADC14->MEM[0], (void*)&resultsBuffer[1024], 1024); /* Assigning/Enabling Interrupts */ MAP_DMA_assignInterrupt(DMA_INT1, 7); MAP_DMA_assignChannel(DMA_CH7_ADC14); MAP_DMA_clearInterruptFlag(7); /* Enabling Interrupts */ MAP_Interrupt_enableInterrupt(INT_DMA_INT1); MAP_Interrupt_enableInterrupt(INT_PORT1); MAP_Interrupt_enableMaster(); /* Going to sleep */ MAP_PCM_gotoLPM0(); __no_operation(); } /* * 15 Primary completed resultArray[0-1023] * 14 Alternate completed resultArray[1024-2047] * * 3 Primary completed resultArray[12288-13311] * 2 Alternate Completed resultArray[13312-14335] * setup last alternate here * 1 Primary completed resultArray[14336-15359] * 0 Alternate completed resultArray[15360-15999] * */ __attribute__((ramfunc)) // Requires compiler TI v15.12.1.LTS void DMA_INT1_IRQHandler(void) { uint8_t * uartPtr; uint32_t ii; #ifdef DEBUG BITBAND_PERI(P2->OUT, 0) = 1; #endif if(pingPongCounter == 0) { MAP_Timer_A_stopTimer(TIMER_A0_BASE); MAP_DMA_disableChannel(7); MAP_DMA_disableChannelAttribute(DMA_CH7_ADC14,UDMA_ATTR_ALTSELECT); // MAP_UART_transmitData(EUSCI_A0_BASE,tstConfiguration.selectClkConfig); // MAP_UART_transmitData(EUSCI_A0_BASE,tstConfiguration.selectRefConfig); for(ii=0;ii<ARRAY_LENGTH;ii++) { /* * LSB first */ uartPtr = (uint8_t*)&resultsBuffer[ii]; MAP_UART_transmitData(EUSCI_A0_BASE,*uartPtr++); MAP_UART_transmitData(EUSCI_A0_BASE,*uartPtr); __delay_cycles(150); } /* * Setting Control Indexes. In this case we will set the source of the * DMA transfer to ADC14 Memory 0 and the destination to the destination * data array. */ MAP_DMA_setChannelControl(UDMA_PRI_SELECT | DMA_CH7_ADC14, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1); MAP_DMA_setChannelTransfer(UDMA_PRI_SELECT | DMA_CH7_ADC14, UDMA_MODE_PINGPONG, (void*) &ADC14->MEM[0], (void*)resultsBuffer, 1024); MAP_DMA_setChannelControl(UDMA_ALT_SELECT | DMA_CH7_ADC14, UDMA_SIZE_16 | UDMA_SRC_INC_NONE | UDMA_DST_INC_16 | UDMA_ARB_1); MAP_DMA_setChannelTransfer(UDMA_ALT_SELECT | DMA_CH7_ADC14, UDMA_MODE_PINGPONG, (void*) &ADC14->MEM[0], (void*)&resultsBuffer[1024], 1024); } else { if(pingPongCounter > 1) { arrayOffset = 1024*(NUMBER_OF_DMA_PING_PONGS-pingPongCounter+2); if(pingPongCounter == 2) { arraySize = REMAINDER; arrayMode = UDMA_MODE_BASIC; } else { arraySize = 1024; arrayMode = UDMA_MODE_PINGPONG; } /* * Switch between primary and alternate bufferes with DMA's PingPong mode */ if (MAP_DMA_getChannelAttribute(7) & UDMA_ATTR_ALTSELECT) { // MAP_DMA_setChannelTransfer(UDMA_PRI_SELECT | DMA_CH7_ADC14, arrayMode, // (void*) &ADC14->MEM[0], // (void*)&resultsBuffer[arrayOffset],arraySize); MSP_EXP432P401RLP_DMAControlTable[7].dstEndAddr = (void*)&resultsBuffer[arrayOffset+arraySize]; MSP_EXP432P401RLP_DMAControlTable[7].control = (MSP_EXP432P401RLP_DMAControlTable[7].control & 0xff000000 ) | (((arraySize)-1)<<4) | arrayMode; } else { // MAP_DMA_setChannelTransfer(UDMA_ALT_SELECT | DMA_CH7_ADC14, arrayMode, // (void*)&ADC14->MEM[0], // (void*)&resultsBuffer[arrayOffset],arraySize); MSP_EXP432P401RLP_DMAControlTable[15].dstEndAddr = (void*)&resultsBuffer[arrayOffset+arraySize]; MSP_EXP432P401RLP_DMAControlTable[15].control = (MSP_EXP432P401RLP_DMAControlTable[15].control & 0xff000000 ) | (((arraySize)-1)<<4) | arrayMode; } } pingPongCounter--; } #ifdef DEBUG BITBAND_PERI(P2->OUT, 0) = 0; #endif } void configure_UART(void) { /* Configuring UART Module */ MAP_UART_initModule(EUSCI_A0_BASE, &uartConfig); /* Enable UART module */ MAP_UART_enableModule(EUSCI_A0_BASE); /* Selecting P1.2 and P1.3 in UART mode */ MAP_GPIO_setAsPeripheralModuleFunctionInputPin(GPIO_PORT_P1, GPIO_PIN2 | GPIO_PIN3, GPIO_PRIMARY_MODULE_FUNCTION); } void PORT1_IRQHandler(void) { #ifdef DEBUG BITBAND_PERI(P1->OUT, 0) = 1; #endif P1IFG &= ~BIT4; if(pingPongCounter==0) { pingPongCounter = NUMBER_OF_DMA_PING_PONGS; MAP_DMA_enableChannel(7); MAP_Timer_A_generatePWM(TIMER_A0_BASE, &timerA_PWM); } #ifdef DEBUG BITBAND_PERI(P1->OUT, 0) = 0; #endif }
Consider the flow of your code. The LPM0 is intended to keep the CPU from proceeding until the DMA interrupt. Now that you have added another interrupt for the UART, this will also allow the CPU to proceed. You may have a potential issue where the main loop is being executed while the DMA is still writing to the data. Can you simply remove the UART ISR and within the DMA isr check if the UART received any data? Do you really want the data transmitted continuously or do you want a burst (2Kb) of data every time a specific uart value is received.
Not sure is the attached is helpful, but in this example instead of a UART rx a port isr is used to burst out data.
Chris
**Attention** This is a public forum