Test Harness - Strange Simulator Behavior [solved]

Go To Last Post
11 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Greetings -

 

I've written a short test program to evaluate various implementations of a digital filter that I need to implement. I'll present the code and follow that with a short explanation and then a description of what I think I am seeing. AS7, gcc, Mega328P. The WHOLE program is in three files and the WHOLE program is listed, below.

 

main.c

/*
 * main.c
 *
 * Created: 7/9/2019 11:53:09 AM
 * Author : wagner
 */ 

#include <avr/io.h>
#include <stdlib.h>
#include <stdint.h>
#include "cfile.h"

//sensor data three samples made up
int16_t x[] = {-500,-500,-500 };
int16_t y[] = {20,20,20 };
int16_t z[] = {10,10,10 };

volatile signal_t xSignal;
volatile signal_t ySignal;
volatile signal_t zSignal;

volatile uint8_t flag;

int main(void)
{
    //INITIALIZATION
    uint8_t J = 0;

    while (1)
    {

    xSignal.xnew = x[J];
    //xSignal.y0 will be assigned by filter()
    filter( &xSignal );

    ySignal.xnew = y[J];
    filter( &ySignal );

    zSignal.xnew = z[J];
    filter( &zSignal );

    J ++;
    if ( J >= 3 )
    	J = 0;
    }
}  //end main.c

filter.h

/*
 * cfile.h
 *
 * Created: 7/9/2019 11:53:09 AM
 * Author : wagner
 */ 

#ifndef CFILE_H
#define CFILE_H

#include <stdlib.h>
#include <stdint.h>

//BASE 65536 0.002Hz
#define BASE 65536  //e.g. 1<<16
#define A0	 65532  //0.99937
#define B1	 65528  //0.99874
#define FILDLY 500	//startup stabilization samples

typedef struct{
    int16_t x0;
    int16_t x1;
    int16_t y0;
    int16_t y1;
    int16_t xnew;	//this avoids having to reference the new data globally inside the filter
 } signal_t;		

void filter( signal_t *);

#endif 

cfile.c

/*
 * cfile.c
 *
 * Created: 7/9/2019 11:53:09 AM
 * Author : wagner
 */ 

#include "cfile.h"

// =====================================================================================
//Versioin for 16-bit unsquared data but with long coefficients to get low corner
//
// The filter is a first order high-pass that is intended to eliminate static offset,
// background gravity, and temperature sensitivity in offset.
//
// Immplements the filter function y[n] = a0 (x[n] - x[n-1]) + b1 y[n-1]
// where: x[n] is the current input sample
//		 x[n-1] is the previous input sample
//		 y[n] is the current output sample from this filter
//		 y[n-1] is the previous output sample
//
// Note that a0 and b1 are fractions less than 1 and are implemented as fixed-point
// values based on some base BASE (see cfile.h) plus defined constants A0 and B1
//
// SEE cfiles.h for corner frequency
//
// It operates on the struct signal in which
//    		on call				operates on              on exit
//  signal.x0   PREVIOUS input			current input		PREVIOUS input
//  signal.x1   2ND PREVIOUS input		previous input		2ND PREVIOUS input
//  signal.y0   PREVIOUS output			current output		PREVIOUS output
//  signal.y1   2ND PREVIOUS output		previous output		2ND PREVIOUS output
//  signal.xnew NEW input			new signal value	this input
// =====================================================================================
void filter( signal_t *MySignal)
	{
	//the pointer references the struct signal_t xSignal, etc
	int32_t working;

	MySignal->x1 = MySignal->x0;
	MySignal->y1 = MySignal->y0;
	MySignal->x0 = MySignal->xnew;  

	working = (MySignal->x0 - MySignal->x1) * A0;
	working = working + B1*MySignal->y1;
	working = working / BASE;
	MySignal->y0 = working;

} //end filter()

 

OK, this compiles without errors or warning. Optimization is -O3

 

The arrays x[], y[], and z[] represent samples generated by my acceleration sensor. The struct signal_t is implemented 3 times, as XSignal, YSignal, and ZSignal. Each contains the old and new values of the input time series and the output time series for each axis' filter. The structs are passed, one at a time, to the function filter(signal_t *) to do the filtering for that axis for that sample. I've faked three samples of sensor data, just to get started. Also faked the sample index, J, just to get started.

 

Here are the odd things that happen:

 

1) When I run it through the simulator, it will not step into the function unless a breakpoint is present inside the function.

 

2) When the cursor has just passed the line xSignal.xnew = x[J]; the simulator does not know what xSignal is.

 

3) When the cursor is inside the function, the simulator does not know what MySignal is. 

 

In the past, I would have written this off to "optimization" but I don't think that is what is happening, here. I've looked at the lst file, and to the extent that I understand what it shows, it seems to be OK. 

 

I am assuming that I've made some kind of error here. Or, maybe just some invalid assumptions about how things ought to be. Can anyone help me out?

 

Thanks

Jim

This topic has a solution.

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

Last Edited: Sat. Jul 13, 2019 - 11:57 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ka7ehk wrote:
OK, this compiles without errors or warning.
1.

	MySignal->y0 = working;

Possible loss of a bit due to truncating 32b to 16b.

 

2. 'volatile' instead of 'static'?

 

3.

#define FILDLY 500	//startup stabilization samples

isn't referenced.

 

"Dare to be naïve." - Buckminster Fuller

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Good points -

 

1) int32_t working was integer divided by 0x00010000 which should have left a 16 bit answer. THAT should fit into a 16-bit variable. No warning was generated.

 

2) Assume you are referring to volatile filter structs. That was a technique cliff suggested to prevent variables and functions from being optimized away. No warning was generated.

 

3) I know. #define FILDLY is the number of samples the system has to wait after bootup to allow the filter to stabilize from the large initial offsets on some channels/axes. Its use is not yet implemented. No warning was generated.

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ka7ehk wrote:
1) int32_t working was integer divided by 0x00010000 which should have left a 16 bit answer. THAT should fit into a 16-bit variable. No warning was generated.
An information indication at this end.

ka7ehk wrote:
2) Assume you are referring to volatile filter structs.
Yes

Do structs require volatile?

 

"Dare to be naïve." - Buckminster Fuller

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Jim,
Attaching an AS7.0 project would invite more response.
I might construct the project for myself but I will never know what Project Properties you have configured. Only guesswork.
David.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Do structs require volatile?

In this case, yes, though volatile should be preserved in the function declaration.

From :

void filter( signal_t *);

To :

void filter( volatile signal_t *);

 

"Dare to be naïve." - Buckminster Fuller

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Oh! Missed that!

 

Not quite sure how to attach a complete project. Will try this.

 

Jim

Attachment(s): 

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

This is getting stranger and stranger.

 

NO variable, even the sample array index, J, is known to the simulator! Everything shows in the watch window as "unknown identifier". It does not seem to care if the variable is global or local, simple or complex, volatile or not, static or not. This was started as a regular new AS7 C project with nothing changed from default settings. Somewhat strangely, the very first time I tried to compile, the header file with a few declarations threw an error something like "int16_t unknown"; that was solved by #including <stdint.h>  I do not remember ever having to do that, before (but might have).

 

What I am currently doing is writing filter output values to OCR1A, OCR1B, and ICR1. I can do this because Timer1 is not used and these are volatile 16-bit "registers". The simulator DOES know these, via the IO View. 

 

So, I have it "solved" sufficiently for my testing. But, I would sure like it to work right so that I can follow operations through the filter and see, first hand, how it works. 

 

Maybe I should try creating some other new project, then if that works OK, move the code files there. Something isn't right!

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

Last Edited: Sat. Jul 13, 2019 - 10:45 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

ka7ehk wrote:
Everything shows in the watch window as "unknown identifier".
With or without post #6?

"Dare to be naïve." - Buckminster Fuller

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

With post #6. All variables, whether global, local to main() or local to filter(), what ever.

 

Interestingly, the compiler DID NOT error or warn about the lack of "volatile" in the argument list. It HAS in other projects.

 

Off to try a new version of the project.

 

Jim

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

Last Edited: Sat. Jul 13, 2019 - 10:48 PM
This reply has been marked as the solution. 
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Report: Constructed a new project. Copied the code files from the old project to the new one.

 

Watches work!

 

Now, it does not even stop in the function if a break is in place. Hunch: inlined. Need to look at lss file to make sure. But, at the very least, I can verify that the filter structs are modified correctly by the time the filter is finished.

 

Significant improvement. Thanks  to all who spent some time and little grey matters on this.

 

<EDIT> Strangely, after running it a few times, it now breaks inside the filter function and it knows the struct that it operates on, in the filter. Calling it "solved". </EDIT>

 

Jim

 

Jim Wagner Oregon Research Electronics, Consulting Div. Tangent, OR, USA http://www.orelectronics.net

Last Edited: Sat. Jul 13, 2019 - 11:55 PM