Hello:
I am trying to take "cc430x513x_dma_04.c - DMA0, Single transfer using ADC12 triggered by Timer_A0" example to uses the TI BIOS kernel. The BIOS setup HWI different than standard __interrupt void DMA_ISR(void).
Can some one shown me how to convert "cc430x513x_dma_04.c" DMA, ISR, and ADC to use the BIOS kernel?
Thank You
Mike
//******************************************************************************// CC430x513x Demo - DMA0, Single transfer using ADC12_A triggered by Timer_A0//// Description: This software uses TACCR1 as a sample and convert input into// the A0 of ADC12. ADC12IFG is used to trigger a DMA transfer and DMA// interrupt triggers when DMA transfer is done. TA1 is set as an output and// P1.0 is toggled when DMA ISR is serviced.// // ACLK = REFO = 32kHz, MCLK = SMCLK = default DCO 1048576Hz//// CC430x513x// -----------------// /|\| XIN|-// | | | 32kHz// --|RST XOUT|-// | |// | P1.0|-->LED// | |// | P4.1|-->TA1 output// | |// | P6.0|<--A0//// M. Morales// Texas Instruments Inc.// April 2009// Built with CCE v3.1 Build 3.2.3.6.4 & IAR Embedded Workbench Version: 4.11B//******************************************************************************
#include "cc430x513x.h"
unsigned int DMA_DST;
void main(void){ WDTCTL = WDTPW+WDTHOLD; // Hold WDT
P1OUT = 0; // P1.0, P1.6 clear P1DIR |= BIT0 + BIT6; // P1.0 output to LED, P1.6 GND PMAPPWD = 0x02D52; // Get write-access to port mapping regs P2MAP6 = PM_TA0CCR1A; // Map TA0CCR1 output to P2.6 PMAPPWD = 0; // Lock port mapping registers
P2DIR |= BIT6; // Output TA0CCR1 P2SEL |= BIT6; // Enable TA0CCR1 functionality /* Initialize Timer A0 */ TA0CCR0 = 0xFFFE; TA0CCR1 = 0x8000; TA0CCTL1 = OUTMOD_3; // CCR1 set/reset mode TA0CTL = TASSEL_2+MC_1+TACLR; // SMCLK, Up-Mode
/* Initialize REF module */ // Enable 2.5V shared reference, disable temperature sensor to save power REFCTL0 |= REFMSTR+REFVSEL_2+REFON+REFTCOFF; /* Initialize ADC12_A */ ADC12CTL0 = ADC12SHT0_15+ADC12MSC+ADC12ON;// Sampling time, MSC, ADC12 on ADC12CTL1 = ADC12SHS_1+ADC12CONSEQ_2; // Use sampling timer; ADC12MEM0 // Sample-and-hold source = CCI0B = // TBCCR1 output // Repeated-single-channel ADC12MCTL0 = ADC12SREF_0+ADC12INCH_0; // V+=AVcc V-=AVss, A0 channel ADC12CTL0 |= ADC12ENC;
__delay_cycles(75); // ~75us shared ref. settling time /* Initialize DMA0 */ DMACTL0 = DMA0TSEL_24; // ADC12IFGx triggered DMACTL4 = DMARMWDIS; // Read-modify-write disable DMA0CTL &= ~DMAIFG; DMA0CTL = DMADT_4+DMAEN+DMADSTINCR_3+DMAIE; // Rpt single tranfer, inc dst, Int DMA0SZ = 1; // DMA0 size = 1 __data16_write_addr((unsigned short) &DMA0SA,(unsigned long) &ADC12MEM0); // ... from ADC12MEM0 __data16_write_addr((unsigned short) &DMA0DA,(unsigned long) &DMA_DST); // ... to destination in RAM
__bis_SR_register(LPM0_bits + GIE); // LPM0 w/ interrupts __no_operation(); // used for debugging}
//------------------------------------------------------------------------------// DMA Interrupt Service Routine//------------------------------------------------------------------------------#pragma vector=DMA_VECTOR__interrupt void DMA_ISR(void){ switch(__even_in_range(DMAIV,16)) { case 0: break; case 2: // DMA0IFG = DMA Channel 0 P1OUT ^= BIT0; // Toggle P1.0 break; case 4: break; // DMA1IFG = DMA Channel 1 case 6: break; // DMA2IFG = DMA Channel 2 case 8: break; // DMA3IFG = DMA Channel 3 case 10: break; // DMA4IFG = DMA Channel 4 case 12: break; // DMA5IFG = DMA Channel 5 case 14: break; // DMA6IFG = DMA Channel 6 case 16: break; // DMA7IFG = DMA Channel 7 default: break; }}
Mike,If you’ve not seen it, there is a wiki page with some more information about SYS/BIOS specifics on MSP430 here: http://processors.wiki.ti.com/index.php/SYS/BIOS_for_the_MSP430 An example of configuring a minimal interrupt stub is here: http://processors.wiki.ti.com/index.php/SYS/BIOS_for_the_MSP430#Minimal_Stub For your ISR function I’m pointing to a “minimal” stub because the ISR is simple, and doesn’t do anything that triggers SYS/BIOS scheduling (like posting a Semaphore). I think you can:1) Add something like the following to your application .cfg file, to create an interrupt stub that calls your ISR function. var Hwi = xdc.useModule('ti.sysbios.family.msp430.Hwi');hwiParams.swiEnabled = false;hwiParams.taskEnabled = false;hwiParams.threadTypeEnabled = false;Hwi.create(52, '&DMA_ISR', hwiParams);The “52” corresponds to the priority of the DMA interrupt vector shown in the “Interrupt Vector Addresses” table in the device data sheet.2) Remove the “#pragma vector=DMA_VECTOR” and the “__interrupt” keyword from the DMA_ISR function (because the interrupt stub will call it as a ‘normal’ C function that must do a normal function return).That's it for the ISR. The DMA and other setup in main() should be reusable, but you'll need to invoke BIOS_start() at the end of main(), rather than just going to LPM.Hope this helps…Scott
Hi Scott,
Thank You for your help. I will try to get it working.
I would like to have ADC do 512 samples per second.
What is the ADC configuration settings to get 512 samples per second?
Hi Mike,
I’m not familiar with the setup options for that ADC.
You can try this MSP430 forum for help with ADC or other peripheral-related questions: http://e2e.ti.com/support/microcontrollers/msp43016-bit_ultra-low_power_mcus/default.aspx
Scott