/var/www/restricted/ssh/stm32/www/stm32circle/ STM CircleOS forum / Software Interrupt

Username:     
Password:     
             

Forum

# 1   2011-07-11 16:25:16 Software Interrupt

skha
New member
Registered: 2011-07-11
Posts: 6

Software Interrupt

Hi, I want to trigger the DAC via Software Interrupt. I should be activate in the "Systick Handler". So I set the DAC to "DAC_InitStructure.DAC_Trigger = DAC_Trigger_Software;". But how can I start the conversation. I tryed to set the DAC_Trigger_Software but it doesent worke.

Offline

 

# 2   2011-07-11 20:31:48 Software Interrupt

ntrf.zns
Member
From: Belgorod, Russia
Registered: 2009-11-01
Posts: 134

Re: Software Interrupt

I actualy only worked with timer triggers. But i will try to help you.

This code does what you need to send new data to DAC. It will however take 1 APB1 cycle to actualy transfer data to DAC and some additional time to finish the conversion.

Code:

DAC_SoftwareTriggerCmd(DAC_Channel_1, ENABLE);

But i advise you to think if you actualy need a trigger. DAC could be configured to convert values as soon as they are written into one of holding regiters. Triggering the conversion is only usefull if you need to wait for some external signal telling you to start the conversion.

Maybe in your case it's just enough set trigger to DAC_Trigger_None.

Offline

 

# 3   2011-07-13 10:51:48 Software Interrupt

skha
New member
Registered: 2011-07-11
Posts: 6

Re: Software Interrupt

Thank you!
I want to create a DDS by using a timer interrupt. In this interrupt a variable counts up but before I count up the conversation has to start with the last value. Maybe there is a better way to do this?

Offline

 

# 4   2011-07-13 14:50:57 Software Interrupt

ntrf.zns
Member
From: Belgorod, Russia
Registered: 2009-11-01
Posts: 134

Re: Software Interrupt

So i guess you a are trying to generate sawtooth wave on dac output with a specific frequency? Generaly it's better to generate a big chukn of waveform in a certain buffer and then configure DMA for DAC so that all you will have to do is to fill the buffer again on DMA interrupt. It the most power-efficient way, but this might be too much work...

Instead you can use timer interrupt (any timer - not only systick) to send a new value to DAC. Just configure DAC without trigger and it will convert the value as soon as you call this function:

Code:

  DAC_SetChannel1Data(DAC_Align_12b_R , Data);

After that just continue with your normal program flow - prepare the next value or whatever. DAC will convert almost immediatly. Even if there will be some kind of delay it will be way out of audible range of frequency.

Offline

 

# 5   2011-07-13 17:07:15 Software Interrupt

skha
New member
Registered: 2011-07-11
Posts: 6

Re: Software Interrupt

I try to generate a sinus but I need resorces for other tasks. So I am not sure how fast can I recall the funktion. I already have the waveform values in an area and I thought I can use a pointer  for the the DMA_MemoryBaseAddr which shows to my area. But I always have to add the choosed frequency to the pointer after the conversation so I need this interrupts. I start the DAC with a timer and use the DMA_ITConfig to calculate the next step in the IRQ but I think its a very bad solution to wait for the DMA finish Interrupt (waste of time). If you say that your solution is the best for this appication i will try it.

Last edited by skha (2011-07-14 10:11:31)

Offline

 

# 6   2011-07-14 18:57:03 Software Interrupt

ntrf.zns
Member
From: Belgorod, Russia
Registered: 2009-11-01
Posts: 134

Re: Software Interrupt

DMA method work like this: you cofigure a circular DMA buffer so it will always be sent to DAC holding register when triggered by timer6 or timer7 (works best with them but you can use any other timer). Then you fill the buffer with sin values using currently selected frequency and aplitude. You also configure DMA "half buffer" and "transfer complete" interrupts. When interrupt is fired you determine which half of dma buffer is current and fill the opposite half of the buffer with the new values.

To use DMA or not to use it depends on the task. If you need to reconfigure parametes quickly, like if you are transfering a realtime values by using some kind of binary protocol - you can't use DMA because you simply won't be able to prepare enough data for efficient transfer. Also if you might not be able to store the data because it's taking too much memory and you need most of it for some general processing. But if your wave parameters are changing slower than 30KHz it's deffinetely worth to set DMA for data transfer. If user is responsible for selecting the frequency - it will be as low as 20Hz (speed of brain to hand signal).

Also not that each interrupt takes additional 12 cycles each time you enter or exit interrupt. Using DMNA interrupt to set up to 256 values instead of timer interrupt to set a single value will reduce required porcessor cycles by 255*12 = 3060 cycles. You can use those for some better purpose. It will actualy be even faster because of memory prefetch and other. That's why it's efficient.

As far as i undestood you have some input from user like frequency and amplitude and it actualy won't make any difference which method you use - user reactions will be much less frequent then dma interrupts. Even if you are going to implement frequency slides - this just won't happen fast enough. Just set buffer for 256 asmples and change frequency between buffer halves.

So to summarize: if you need to cahnge paramenters faster then 30KHz - DMA is probably not for you. Otherwise remember - hyman ear, eye and finger have too much imprecisions for you to think hard about perfect solutions.

If you need my code for DMA transfered WAV file player through DAC - just ask. Unfortunatly it's not ST StdLib - i wrote my own library for that project.

Offline

 

# 7   2011-07-18 15:18:14 Software Interrupt

skha
New member
Registered: 2011-07-11
Posts: 6

Re: Software Interrupt

Thank you, you are a greate help. I try both ways and now I try to set the DAC with that command: DAC_SetChannel1Data(DAC_Align_12b_R , Data); ... (you told me). I wrote a test and I wonder about the different results. The first part workes fine but the second only workes with 2 of these Orders. And if I compare the signals they look different (but that could be my mistake I currently have just a soundcard oszilloscope, tomorrow I have a real again) . I can set the counter to 1 sec but it still makes no difference. I mean the first is it what I want...  nice that it workes but what is wrong with the other. Oh and I made a test with LED GPIOs and by debugging. All stats are reachable.

Code:

        DAC_SetChannel1Data(DAC_Align_12b_R , Sine12bit[sin_arrayfeld]);


        test2 = Sine12bit[sin_arrayfeld];

        sin_arrayfeld ++;

        if(sin_arrayfeld > 3)
        {
            sin_arrayfeld = 0;
        }


//###########################################################################################


      if(test == 0 && test3 == 0)
      {
        DAC_SetChannel1Data(DAC_Align_12b_R , 0);
        //GPIO_WriteBit(GPIOE, GPIO_Pin_8, Bit_SET);

        test = 1;
        test3 = 1;
      }

      if (test == 1 && test3 == 0)
      {
            DAC_SetChannel1Data(DAC_Align_12b_R , 2000);
            //GPIO_WriteBit(GPIOE, GPIO_Pin_8, Bit_RESET);

            test = 2;
            test3 = 1;
      }
      if (test == 2 && test3 == 0)
      {
            DAC_SetChannel1Data(DAC_Align_12b_R , 4000);
            //GPIO_WriteBit(GPIOE, GPIO_Pin_8, Bit_SET);

            test = 0;
            test3 = 1;
      }
      test3 = 0;

Naturally i dont use both parts at the same time ;-) (so thats not the mistake)

Offline

 

# 8   2011-07-20 15:41:16 Software Interrupt

ntrf.zns
Member
From: Belgorod, Russia
Registered: 2009-11-01
Posts: 134

Re: Software Interrupt

Well first of all i see a huge difference between two of those examples:
- in first part one you you are resetting when (sin_arrayfeld > 3) this gives you 4 iterations! (from 0 to 3)
- in second part you only have 3 iterations.
So they are realy different smile

Also why are you using test3 variable in second part? Woldn't it be easier to use "else if" instead?

Code:

if(test == 0)
{
    ...
    test = 1;
}else if(test == 1)
{
    ...
    test = 2;
}else if(test == 2)
{
    ...
    test = 0;
}

But as for any other ARM processor i suggest you avoid using many consecutive if's. That actualy hurts preformance... and your eyes smile

Last edited by ntrf.zns (2011-07-20 15:41:43)

Offline

 

# 9   2011-07-21 11:44:08 Software Interrupt

skha
New member
Registered: 2011-07-11
Posts: 6

Re: Software Interrupt

hm ok fail again ^^ but I was confused about no signal. You said to use "if" is not a good idea. Is there a list to see how many clocks does a command need or is reading the assembler code or creating a clock-counter the only way to find it out. I know it depends on the compiler but I think there are some equalities.
The if was a test in this example. Later I used this code:

Code:

 DAC_SetChannel1Data(DAC_Align_12b_R , Sine12bit[~sin_arrayfeld & 0b0000111111111111] );
 sin_arrayfeld -= sig_freuquenz;

Oh i think you know that but just to say it again "Sine12bit" is an array with 4096 sine terms.

Last edited by skha (2011-07-21 11:50:29)

Offline

 

# 10   2011-07-21 21:41:38 Software Interrupt

ntrf.zns
Member
From: Belgorod, Russia
Registered: 2009-11-01
Posts: 134

Re: Software Interrupt

As far as i know there is no reliable way to know how many cycles it takes to preform an instruction. Even looking at the assember listing won't give any idea about it. In ARM execition times can vary significantly due to the cache (64-bit instruction buffer to precise), flash reading delays and pipeline stalls. But one thing is important - jumps (if, while, goto) will intoduce what is called a pipeline flush - when all processor pipeline stages are forced to complete before executing next command. The worst operation in this case is indirect call - needs memory lookup, pipeline flush and stack frame saving.

However there is an exception: IF instruction. It's issued when no more then 4 next commands need conditional execution. Then it almost free - 1 cycle, but it will only work for short expressions. For example:

Code:

    uint8_t mylocalvalue = params[0]; 
    if(mybitmask & 0x10) //produce negative value
        mylocalvalue = - mylocalvalue;

In new STM32F2xx they implemented some-kind of I-cahe for 32 entries (if i'm correct) to hide flash memory reading delays. That's why it runs 120MHz.

By the way: did it finaly worked? Are you getting the correct output?

Offline

 

# 11   2011-07-22 08:37:20 Software Interrupt

skha
New member
Registered: 2011-07-11
Posts: 6

Re: Software Interrupt

Hello,
first: I know my english is very bad sorry for that I try my best. If you have big problems to read it please stop reading and write me and I try to improve this text.


I have the stm32F107 so I only have 75MHz System clock (maybe the wrong µC selection... ;-)). I did not found this special function "if" which document contains that (RM0008?)? And yes the code workes I get a good sin signal with noise but that noise seems to "generate" by the cheap eval board and the electricity around me. But I am not sure that this is better than an "if". And yes I still have to write my Lookup table in the ram to save performance. I heard I have to reduce the DAC output because there are non linearities at "0V" and "3V" so a good working is beween 0.5V and 2.5V. The next step for me is it to capture a signal with the ADC and transfered it to the DAC , to save the frequency and the amplitude and to manipulate the signal (I think with ADC =>DMA => RAM => DMA => DAC // or // ADC => DMA=> DAC/RAM) because I need the therms to compare them). I want to manipulate the signal by stopping the DMA transfered and insert a look up table signal. I use the last 2 frequenzies to generate a slide. So if the frequency was growing up it hasnt to stop during the manipulation. The amplitude and frequency can be detected with a hardware or software solution (depends on the free µC recources). I would always compare the last highest therm with the next therm and detect the zero crossing. I thought about less ADC conversations and a sin(x)/x filter to restore it but DMA should be more efficient and I need many therms to find the right amplitude.

Thats what I try now.

Offline

 

# 12   2011-08-04 06:05:56 Software Interrupt

adamricky
New member
Registered: 2011-07-29
Posts: 5

Re: Software Interrupt

Interrupt(process id, interrupt number)

and another that allows a process to associate a handler with an interrupt:

Handle(interrupt number, handler)

Software interruprts allow only one bit information to be communicate - that an event associated with the interrupt number has occurred. They are typically used by an operating system to inform a process about the following events:
The user typed the ``attention key''.
An alarm scheduled by the process has expired.
Some limit, such as file size or virtual time, has been exceeded.

It is important to distinguish among interrupts, traps, software interrupts, and exceptions. In all cases, an event is processed asynchronously by some handler procedure. Interrupt and trap numbers are defined by the hardware which is also responsible for calling the procedure in the kernel space. An interrupt handler is called in response to a signal from another device while a trap handler is called in response to an instruction executed within the cpu.

Software interrupt and exception handlers are called in user space. A software interrupt handler is called in response to the invocation of a system call. Software interrupt numbers are defined by the operating system. Exceptions are defined and processed by the programming language. An exception raised in some block, b, of some process p, can be caught by a handler in the same block, or a block/procedure (in p) along static/dynamic links from b, or by a process q that (directly or indirectly) forked p. The raiser of an exception does not identify which process should handle it, so exceptions are not IPC mechanisms.

The notion of software interrupts is somewhat confused in some environments such as the PC, where traps to kernel-provided I/O routines are called software interrupts. There is a special instruction on the PC called INT which is used to invoke these traps. For instance, the instruction

int 16H

executes the BIOS interrupt routine for processing the current character received from the keyboard. (It is executed by the interrupt handler of the Xinu kernel to ask the PC BIOS handler to fetch the character from the keyboard.) The term interrupt is used because these rountines are called usually by hardware interrupt routines. We are using the term software interrupts for what Unix calls signals, which are not to be confused with semaphores, though you invoke the signal operation on both!

Offline

 

# 13   2011-08-22 09:42:04 Software Interrupt

hariprasaadh
New member
Registered: 2011-07-22
Posts: 3

Re: Software Interrupt

Having trouble using the DAC on the dsPIC33FJ64GP802.

Let me start by saying I wouldn't ask for help here if I hadn't already tried *everything* I can think of.  I've already spent too much time going over datasheets, app notes, sample code, etc.  I've also looked at previous posts regarding this peripheral, and I still haven't had any luck.  That's why I'm here.  I appreciate any help any gurus can provide.

One thing that has me confused from Microchip's ADC-DAC loopback example code is this (the bold lines in the code below).  They choose the FRC w/ PLL as the clock source, then they choose the auxiliary oscillator as the clock source, then they disable the auxiliary oscillator that they just chose.  WTF??  How does that make sense?



// MICROCHIP'S CODE

/* Initiate DAC Clock */
ACLKCONbits.SELACLK = 0;     // FRC w/ Pll as Clock Source 
ACLKCONbits.AOSCMD = 0;     // Auxiliary Oscillator Disabled
ACLKCONbits.ASRCSEL = 0;     // Auxiliary Oscillator is the Clock Source
ACLKCONbits.APSTSCLR = 7;     // FRC divide by 1 

DAC1STATbits.ROEN = 1;     // Right Channel DAC Output Enabled   

DAC1DFLT = 0x8000;     // DAC Default value is the midpoint 

         // 103.16KHz      // 8.038KHz     // 44.211KHz    // 25KHz
DAC1CONbits.DACFDIV = 5;       //76; //13;    // 23; //     // Divide High Speed Clock by DACFDIV+1 

DAC1CONbits.FORM = 1;     // Data Format is signed integer
DAC1CONbits.AMPON = 0;     // Analog Output Amplifier is enabled during Sleep Mode/Stop-in Idle mode

DAC1CONbits.DACEN = 1;     // DAC1 Module Enabled 





So, my DAC_Init code and my main function is shown below.  This has all the different configs I've tried to use (including the commented parts).  I'm using the FRC w/ PLL at 80Mhz, and I have the auxiliary clock post scaler set to divide that by 4, then the DAC clock divider divides it by 2.  This should give me a DAC clock of about 20Mhz, which is a sampling rate of 78125 samples per second.  This should be acceptable, right?
Basically my DAC does nothing.  I get a single-ended output of 45 mV or so, and this output never changes.  I'm feeding it with the value I get from my ADC, as you'll see in my main function.  The ADC is just reading the voltage from a voltage divider via a pot.  I've tried using the DAC interrupt to trigger the program to send more data to the FIFO, but that interrupt never gets set (it should trigger when FIFO is empty, but doesn't).  So now I'm not using the interrupts and I'm simply sending data to the FIFO whenever it is not full or not empty (tried both).

Since my DAC clock is within range (and I know the MCU clock is fine, I've seen it on the scope) and I've tried basically every possible configs, I'm not sure what else to try.  Thus, I turn to the masterminds of the forum.  Thanks for any and all help!

Compiler is MikroC for dsPIC's, programmer is PICkit 2.


MY CODE STARTS HERE....

void DAC_Init() {
   
        ACLKCONbits.SELACLK = 0; // Fvco is the source for auxiliary clock divider
        ACLKCONbits.AOSCMD = 0; // Auxiliary oscillator disabled
        ACLKCONbits.APSTSCLR = 5; // Divide by 4
        ACLKCONbits.ASRCSEL = 1; // Primary oscillator is the clock source

        // Only use right channel of DAC
        DAC1STATbits.LOEN = 0; // Disable left channel DAC outputs
        DAC1STATbits.ROEN = 1; // Enable right channel DAC outputs
        DAC1STATbits.RITYPE = 1; // Interrupt if FIFO is (0) not full (1) empty

        DAC1CONbits.FORM = 0; // Unsigned integer data format (1=signed via 2's comp)
        DAC1CONbits.AMPON = 0; // Disable amplifier during sleep/idle modes
        DAC1CONbits.DACFDIV = 1; // DAC clock divider, divide by 2

        // DAC clock = 160Mhz/4/2 = 20Mhz
        // Sample rate is 20Mhz/256 = 78125 samples per second

        DAC1DFLT = 0x8000; // Initialize DAC default output register with midpoint

        DAC_FLAG = 0; // Clear right channel interrupt flag (IFS4bits.DAC1RIF)
        IFS4bits.DAC1LIF = 0; // Clear left channel interrupt flag

        IEC4bits.DAC1RIE = 1; // Enable right channel interrupts
        IEC4bits.DAC1LIE = 0; // Disable left channel interrupts

        DAC1CONbits.DACEN = 1; // Enable DAC
}


unsigned result;
void main() {

  // Initialize the oscillator at 40 MIPS
  Osc_Init();
  // Set TRIS bits
  Tris_Init();
  // Set up software SPI signals
  Soft_SPI_Init();
  // Initialize port expander
  Port_Exp_Init();
  // Initialize LCD panel
  LCDinit();
  // Initialize ADC module: 12-bit mode using internal Vref
  ADC1_Init_Advanced(_ADC_12bit, _ADC_INTERNAL_REF);
  // Initialize DAC module
  DAC_Init();
   
   
  LCDstring("DAC FIFO:");
  while(1) {

      // Get a sample
      result = ADC1_Get_Sample(ADC_CHANNEL); // Sample channel 9 (pin 26)

      // If FIFO is empty, write data to it
    /*if(DAC_FLAG)
      {
         LED = 1;
         DAC1RDAT = result;
         DAC_FLAG = 0; // Clear interrupt flag
      }*/
       
      // While FIFO is not full, send it data
      while(DAC1STATbits.RFULL != 1)
      {
          LED = 1;
          DAC1RDAT = result;
      }
       
      LCDvalue(DAC1RDAT);
      next_line();
      LED = 0;

  }
}

Offline

 

Board footer