I have 3 .c source files: common.c, interface_1.c, interface_2.c.
In common.c, I define some functions and global variables, and in interface_1.c and interface_2.c, these functions and global variables will be invoked.
Now, interface_1.c and interface_2.c will be compiled to .dll so as to be used by other program. The problem is that, while two dll files are called, global variables defined in common.c should be the same, which means: if a global variable is changed during the process of calling interface_1.dll, the same variable in interface_2.dll should be changed at the same time.
Background
I want to use PLECS to do power electronics simulation. There is a block called DLL which is very powerful. User can write c/cpp code and compile them to dynamic link library. Each DLL block can only call one .dll file. I have two DLL blocks and want to make a global variable to communicate between them.
The template of c source file which will be compile to dll are shown below.
DllHeader.h
#ifndef PLECSDLLHEADER_H_
#define PLECSDLLHEADER_H_
#if defined _WIN32
#define DLLEXPORT __declspec(dllexport)
#elif __GNUC__ >=4
#define DLLEXPORT __attribute__ ((visibility("default")))
#else
#define DLLEXPORT
#endif
#ifdef __cplusplus
extern "C" {
#endif
#pragma pack(push, 4)
struct SimulationSizes {
int numInputs; /* the number of inputs that the DLL needs */
int numOutputs; /* the number of outputs that the DLL provides */
int numStates; /* the number of discrete states that the DLL needs */
int numParameters; /* the number of user parameters that the DLL needs */
};
struct SimulationState {
const double* const inputs; /* array of input values (read-only) */
double* const outputs; /* array of output values (to fill by DLL) */
double* const states; /* array of discrete states (read/write) */
const double* const parameters; /* array of parameters (read-only) */
const double time; /* current simulation time (read-only) */
const char* errorMessage; /* error message to set by DLL */
void* userData; /* pointer to any DLL data (untouched by PLECS) */
};
#pragma pack(pop)
/* Required: DLL needs to set all fields in aSizes. */
/* Called once before the simulation. */
DLLEXPORT void plecsSetSizes(struct SimulationSizes* aSizes);
/* Optional: DLL may acquire resources, initialize states and outputs. */
/* Called once during the initialization of a new simulation. */
DLLEXPORT void plecsStart(struct SimulationState* aState);
/* Required: DLL needs to set outputs depending on inputs and states. */
/* Called whenever the simulation time reaches a multiple of the sample */
/* time. */
DLLEXPORT void plecsOutput(struct SimulationState* aState);
/* Optional: DLL may release any acquired resources. */
/* Called when the simulation is finished, even when an error occured. */
DLLEXPORT void plecsTerminate(struct SimulationState* aState);
#ifdef __cplusplus
}
#endif
#endif /* PLECSDLLHEADER_H_ */
interface.c
#include "DllHeader.h"
//Map input and output parameters to meaningful names
#define in aState->inputs[0]
#define out aState->outputs[0]
DLLEXPORT void plecsSetSizes(struct SimulationSizes* aSizes)
{
aSizes->numInputs = 1;
aSizes->numOutputs = 1;
aSizes->numStates = 0;
aSizes->numParameters = 0; //number of user parameters passed in
}
//This function is automatically called at the beginning of the simulation
DLLEXPORT void plecsStart(struct SimulationState* aState)
{
// do some initialization ...
}
//This function is automatically called every sample time
//output is written to DLL output port after the output delay
DLLEXPORT void plecsOutput(struct SimulationState* aState)
{
// do some calculation ...
}
Using LoadLibrary works. Be careful that in interface.c full path of common.dll should be specified! Solution is shown at the end.
For Lundin, it's involved in embedded development, some variables are time-based, which means they are alive all the time and invoked by other control functions. For example, a signal is sampled and passed to a variable, this sampled data will be used in several place, such as filter, closed-loop control... So it's difficult to decouple these messy usage...
common.h
#ifndef COMMON_H_
#define COMMON_H_
#if defined _WIN32
#define DLLEXPORT __declspec(dllexport)
#elif __GNUC__ >=4
#define DLLEXPORT __attribute__ ((visibility("default")))
#else
#define DLLEXPORT
#endif
#ifdef __cplusplus
extern "C" {
#endif
#pragma pack(push, 4)
typedef struct{
float a;
float b;
} Coord;
#pragma pack(pop)
extern Coord curPos;
DLLEXPORT Coord GetcurPos(void);
DLLEXPORT float getMax(float a, float b);
DLLEXPORT void SetcurPos(float a, float b);
#ifdef __cplusplus
}
#endif
#endif /* COMMON_H_ */
common.c
#include "common.h"
Coord curPos;
DLLEXPORT float getMax(float a, float b){
return a>b?a:b;
}
DLLEXPORT Coord GetcurPos(void){
return curPos;
}
DLLEXPORT void SetcurPos(float a, float b){
curPos.a=a;
curPos.b=b;
}
interface_a.c
#include "DllHeader.h"
#include <windows.h>
#include "common.h"
//Map input and output parameters to meaningful names
#define in aState->inputs[0]
#define out aState->outputs[0]
HMODULE module;
typedef float(*AddFunc)(float, float);
typedef Coord (*PosGetter)(void);
AddFunc dllmax;
PosGetter getCurPos;
DLLEXPORT void plecsSetSizes(struct SimulationSizes* aSizes)
{
aSizes->numInputs = 1;
aSizes->numOutputs = 1;
aSizes->numStates = 0;
aSizes->numParameters = 0; //number of user parameters passed in
}
DLLEXPORT void plecsStart(struct SimulationState* aState)
{
module = LoadLibrary(TEXT("D:\\Simulation\\PLECSLearn\\DLL\\global_test\\common.dll"));
if (module == NULL)
{
aState->errorMessage = "Failed to load common.dll";
}
dllmax = (AddFunc)GetProcAddress(module, "getMax");
getCurPos = (PosGetter)GetProcAddress(module, "GetcurPos");
}
//This function is automatically called every sample time
//output is written to DLL output port after the output delay
DLLEXPORT void plecsOutput(struct SimulationState* aState)
{
if (getCurPos().a == 1){
out = 2;
} else {
out = -1;
}
// out = dllmax(200,300);
}
interface_b.c
#include "DllHeader.h"
#include <windows.h>
#include "common.h"
//Map input and output parameters to meaningful names
#define in aState->inputs[0]
#define out aState->outputs[0]
HMODULE module;
typedef float(*AddFunc)(float, float);
typedef Coord (*PosGetter)(void);
typedef void (*PosSetter)(float, float);
AddFunc dllmax;
PosGetter getCurPos;
PosSetter setCurPos;
DLLEXPORT void plecsSetSizes(struct SimulationSizes* aSizes)
{
aSizes->numInputs = 1;
aSizes->numOutputs = 1;
aSizes->numStates = 0;
aSizes->numParameters = 0; //number of user parameters passed in
}
DLLEXPORT void plecsStart(struct SimulationState* aState)
{
module = LoadLibrary(TEXT("D:\\Simulation\\PLECSLearn\\DLL\\global_test\\common.dll"));
if (module == NULL)
{
aState->errorMessage = "Failed to load common.dll";
}
dllmax = (AddFunc)GetProcAddress(module, "getMax");
getCurPos = (PosGetter)GetProcAddress(module, "GetcurPos");
setCurPos = (PosSetter)GetProcAddress(module, "SetcurPos");
}
//This function is automatically called every sample time
//output is written to DLL output port after the output delay
DLLEXPORT void plecsOutput(struct SimulationState* aState)
{
static int cnt = 0;
if (cnt<5000){
setCurPos(0,0);
}else{
setCurPos(1,2);
}
cnt++;
out = getCurPos().a;
}
Related
tmp2.c
/*
gcc -Wall -Werror -g assert.c tmp2.c && ./a.out
*/
#include "tmp2.h"
#include <assert.h>
int main(void)
{
// assert(1 == 2);
Assert(1 == 2);
return 0;
}
tmp2.h
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include <math.h>
#include<stdint.h>
#include<stdalign.h>
#include<stdbool.h>
/*
* BoolIsValid
* True iff bool is valid.
*/
#define BoolIsValid(boolean) ((boolean) == false || (boolean) == true)
/*
* PointerIsValid
* True iff pointer is valid.
*/
#define PointerIsValid(pointer) ((const void*)(pointer) != NULL)
extern void
ExceptionalCondition(const char *conditionName,
const char *fileName,
int lineNumber);
/*
* USE_ASSERT_CHECKING, if defined, turns on all the assertions.
* - plai 9/5/90
*
* It should _NOT_ be defined in releases or in benchmark copies
*/
/*
* Assert() can be used in both frontend and backend code. In frontend code it
* just calls the standard assert, if it's available. If use of assertions is
* not configured, it does nothing.
*/
#define USE_ASSERT_CHECKING 0
#ifndef USE_ASSERT_CHECKING
#define Assert(condition) ((void)true)
#define AssertMarcod(condition) ((void)true)
#elif defined(FRONTEND)
#include<assert.h>
#define Assert(p) assert(p)
#define AssertMarco(p) ((void) assert(p))
#else
/*
* Assert
* Generates a fatal exception if the given condition is false.
*/
#define Assert(condition) \
do { \
if (!(condition)) \
ExceptionalCondition(#condition,__FILE__,__LINE__); \
} while (0)
/*
* AssertMacro is the same as Assert but it's suitable for use in
* expression-like macros, for example:
*
* #define foo(x) (AssertMacro(x != 0), bar(x))
*/
#define AssertMacro(condition) \
((void) ((condition) || \
(ExceptionalCondition(#condition,__FILE__,__LINE__),0)))
#endif
assert.c
#include "tmp2.h"
#include <unistd.h>
#ifdef HAVE_EXECINFO_H
#include <execinfo.h>
#endif
/*
* ExceptionalCondition - Handles the failure of an Assert()
*
* We intentionally do not go through elog() here, on the grounds of
* wanting to minimize the amount of infrastructure that has to be
* working to report an assertion failure.
*/
void
ExceptionalCondition(const char *conditionName,
const char *fileName,
int lineNumber)
{
/* Report the failure on stderr (or local equivalent) */
if (!PointerIsValid(conditionName)
|| !PointerIsValid(fileName))
fprintf(stderr,"TRAP: ExceptionalCondition: bad arguments in PID %d\n",
(int) getpid());
else
fprintf(stderr,"TRAP: failed Assert(\"%s\"), File: \"%s\", Line: %d, PID: %d\n",
conditionName, fileName, lineNumber, (int) getpid());
/* Usually this shouldn't be needed, but make sure the msg went out */
fflush(stderr);
// /* If we have support for it, dump a simple backtrace */
// #ifdef HAVE_BACKTRACE_SYMBOLS
// {
// void *buf[100];
// int nframes;
// nframes = backtrace(buf, lengthof(buf));
// backtrace_symbols_fd(buf, nframes, fileno(stderr));
// }
// #endif
/*
* If configured to do so, sleep indefinitely to allow user to attach a
* debugger. It would be nice to use pg_usleep() here, but that can sleep
* at most 2G usec or ~33 minutes, which seems too short.
*/
#ifdef SLEEP_ON_ASSERT
sleep(1000000);
#endif
abort();
}
In this context, I'm trying a way to use the AssertMacro; that is, find a way to invoke assert.c ExceptionalCondition function. Assume FRONTEND is not defined. USE_ASSERT_CHECKING can be 1 or 0.
update: to use ExceptionalCondition function I need to declare it on tmp2.h via
extern void
ExceptionalCondition(const char *conditionName,
const char *fileName,
int lineNumber);
I also need to define USE_ASSERT_CHECKING in tmp2.h or before tmp2.h.
If I don't define USE_ASSERT_CHECKING seems all the assert will be true always?
I have this code for deleting directories. I have header1.h, header1.c, main.c.
I get some errors, but the one is more difficult to me to understand is the errors:
(1) storage size of ffblk isn't known.
Also, i have the doubt of how to define the attributes of ffblk, which are ff_name and ff_attrib
This example is from various code examples from the internet(even other from here), all of them do the same code, just in my case it does not work.
Am i missing the definition of the struct? or maybe i have added code where it should not be any code?
Could you please help me? I dont usually program in C. and i am using Dev-Cpp.
header1.h:
#ifndef HEADER1_H_INCLUDED
#define HEADER1_H_INCLUDED
typedef struct ffblk ffblk;
#endif
header.c:
#include <stdio.h>
#include <stdlib.h>
#include "header1.h"
struct ffblk
{
char ff_attrib[20]; //this line i added just so dont show error of unknown
char ff_name[20]; //this line i added just so dont show error of unknown
};
main.c:
#ifndef FA_RDONLY
#define FA_RDONLY _A_RDONLY
#endif
#ifndef FA_HIDDEN
#define FA_HIDDEN _A_HIDDEN
#endif
#ifndef FA_SYSTEM
#define FA_SYSTEM _A_SYSTEM
#endif
#ifndef FA_DIREC
#define FA_DIREC _A_SUBDIR
#endif
#ifndef FA_ARCH
#define FA_ARCH _A_ARCH
#endif
# include <stdio.h>
# include <dos.h>
# include <dir.h>
# include <io.h>
# include <conio.h>
#include "header1.h"
typedef struct ffblk ffblk;
int BorrarArchivo(char *nombarch)
{
printf("Borrando Archivo %s \n",nombarch);
remove(nombarch);
return 0;
}
int EliminarAtributo(char *nombarch,int atributo)
{
printf("Elimina Atributo %s %d\n",nombarch,atributo);
chmod(nombarch,atributo);
return 0;
}
int BorrarArbol(void)
{
struct ffblk ffblk;
int done,err;
err=0;
done=findfirst("*.*",&ffblk,FA_RDONLY|FA_HIDDEN|FA_DIREC|FA_ARCH|FA_SYSTEM);
while (!done)
{
if (FA_HIDDEN & ffblk.ff_attrib)
EliminarAtributo(ffblk.ff_name,FA_HIDDEN);
if (FA_SYSTEM & ffblk.ff_attrib)
EliminarAtributo(ffblk.ff_name,FA_SYSTEM);
if (FA_RDONLY & ffblk.ff_attrib)
EliminarAtributo(ffblk.ff_name,FA_RDONLY);
if (FA_ARCH & ffblk.ff_attrib)
err=BorrarArchivo(ffblk.ff_name);
else if (FA_DIREC & ffblk.ff_attrib)
{
if (ffblk.ff_name[0]!='.')
{
chdir(ffblk.ff_name);
err=BorrarArbol();
chdir("..");
if (!err)
printf("Removiendo %s\n",ffblk.ff_name);
rmdir(ffblk.ff_name);
}
}
else
err=BorrarArchivo(ffblk.ff_name);
if (err)
{
printf("Error en el borrado ... !"); return err;
}
done=findnext(&ffblk);
}
return 0;
}
int main (void)
{ int err=0;
char c;
printf("Esta seguro [ Si -> S , No ->otra tecla ] =>");
c=getchar();
if (!(c=='S' || c=='s')) return 0;
err=BorrarArbol();
if (err) printf("Error en el borrado ... !");
return err;
}
EDIT:
I found a definition of struct and paste it in header.h
typedef struct ffblk {
char lfn_magic[6]; /* LFN: the magic "LFN32" signature */
short lfn_handle; /* LFN: the handle used by findfirst/findnext */
unsigned short lfn_ctime; /* LFN: file creation time */
unsigned short lfn_cdate; /* LFN: file creation date */
unsigned short lfn_atime; /* LFN: file last access time (usually 0) */
unsigned short lfn_adate; /* LFN: file last access date */
char ff_reserved[5]; /* used to hold the state of the search */
unsigned char ff_attrib; /* actual attributes of the file found */
unsigned short ff_ftime; /* hours:5, minutes:6, (seconds/2):5 */
unsigned short ff_fdate; /* (year-1980):7, month:4, day:5 */
unsigned long ff_fsize; /* size of file */
char ff_name[260]; /* name of file as ASCIIZ string */
}ffblk;
now it shows error:
C:\Users\1\AppData\Local\Temp\cc89P309.o:Untitled3.c:(.text+0x8e): undefined reference to `findfirst'
C:\Users\1\AppData\Local\Temp\cc89P309.o:Untitled3.c:(.text+0x1d8): undefined reference to `findnext'
At the end, the problem was always the functions findfirst(a,b,c) and findnext(a,b,c). I had to change the functions and use their version with 2 parameters and not 3. I put all the code in one file with the includes, typedef struct and the code below.
About compile suricata.
In Makefile,when CFLAGS wrap "-Werror-implicit-function-declaration"
I got the error:
detect-engine-siggroup.c: In function ‘SigGroupHeadFree’:
detect-engine-siggroup.c:187:9: error: implicit declaration of function ‘_mm_free’ [-Werror=implicit-function-declaration]
SCFreeAligned(sgh->mask_array);
^
detect-engine-siggroup.c: In function ‘SigGroupHeadBuildHeadArray’:
detect-engine-siggroup.c:1715:5: error: implicit declaration of function ‘_mm_malloc’ [-Werror=implicit-function-declaration]
sgh->mask_array = (SignatureMask *)SCMallocAligned((cnt * sizeof(SignatureMask)), 16);
When I delete "-Werror-implicit-function-declaration" in Makefile,I will got the error:
detect-engine-siggroup.o: In function `SigGroupHeadFree':
/root/suricata/suricata-2.0.9/src/detect-engine-siggroup.c:187: undefined reference to `_mm_free'
detect-engine-siggroup.o: In function `SigGroupHeadBuildHeadArray':
/root/suricata/suricata-2.0.9/src/detect-engine-siggroup.c:1715: undefined reference to `_mm_malloc'
Note:_mm_free and _mm_malloc is define in util-mem.h
Yet,I add some code in the other source file,but not in detect-engine-siggroup.c and util-mem.h.
What's wrong?
in detect-engine-siggroup.c(note I have deleted some redundant code here):
void SigGroupHeadFree(SigGroupHead *sgh)
{
if (sgh == NULL)
return;
SCLogDebug("sgh %p", sgh);
PatternMatchDestroyGroup(sgh);
#if defined(__SSE3__) || defined(__tile__)
if (sgh->mask_array != NULL) {
/* mask is aligned */
SCFreeAligned(sgh->mask_array);
sgh->mask_array = NULL;
}
#endif
if (sgh->head_array != NULL) {
SCFree(sgh->head_array);
sgh->head_array = NULL;
}
if (sgh->match_array != NULL) {
detect_siggroup_matcharray_free_cnt++;
detect_siggroup_matcharray_memory -= (sgh->sig_cnt * sizeof(Signature *));
SCFree(sgh->match_array);
sgh->match_array = NULL;
}
sgh->sig_cnt = 0;
if (sgh->init != NULL) {
SigGroupHeadInitDataFree(sgh->init);
sgh->init = NULL;
}
SCFree(sgh);
detect_siggroup_head_free_cnt++;
detect_siggroup_head_memory -= sizeof(SigGroupHead);
return;
}
in util-mem.h(note I have deleted some redundant code here):
#ifndef __UTIL_MEM_H__
#define __UTIL_MEM_H__
#include "util-atomic.h"
#if CPPCHECK==1
#define SCMalloc malloc
#define SCCalloc calloc
#define SCRealloc realloc
#define SCFree free
#define SCStrdup strdup
#define SCMallocAligned _mm_malloc
#define SCFreeAligned _mm_free
#else /* CPPCHECK */
#if defined(_WIN32) || defined(__WIN32)
#include "mm_malloc.h"
#endif
#if defined(__tile__)
/* Need to define __mm_ function alternatives, since these are SSE only.
*/
#include <malloc.h>
#define _mm_malloc(a,b) memalign((b),(a))
#define _mm_free(a) free((a))
#endif /* defined(__tile__) */
SC_ATOMIC_EXTERN(unsigned int, engine_stage);
/* Use this only if you want to debug memory allocation and free()
* It will log a lot of lines more, so think that is a performance killer */
/* Uncomment this if you want to print memory allocations and free's() */
//#define DBG_MEM_ALLOC
#ifdef DBG_MEM_ALLOC
#define SCFree(a) ({ \
extern uint8_t print_mem_flag; \
if (print_mem_flag == 1) { \
SCLogInfo("SCFree at %p", (a)); \
} \
free((a)); \
})
#else /* !DBG_MEM_ALLOC */
#define SCFree(a) ({ \
free(a); \
})
#if defined(__WIN32) || defined(_WIN32)
#define SCFreeAligned(a) ({ \
_mm_free(a); \
})
#else /* !win */
#define SCFreeAligned(a) ({ \
_mm_free((a)); \
})
#endif /* __WIN32 */
#endif /* DBG_MEM_ALLOC */
#endif /* CPPCHECK */
#endif /* __UTIL_MEM_H__ */
#endif /* DBG_MEM_ALLOC */
#endif /* CPPCHECK */
#endif /* __UTIL_MEM_H__ */
/*********************************************************************/
Now solved the problem,reason is forgetting to #include <pmmintrin.h> /* for SSE3 */
/*********************************************************************/
It looks like you have not included util-mem.h properly. SCFreeAligned seem to expand to _mm_free, but _mm_free doesn't seem to expand. Looking at the header file the definition of _mm_free seem to be dependent on __title__ being defined.
Then the compiler just sees a call to _mm_free which is given an implicit prototype as _mm_free doesn't exist. Then of course _mm_free will not be found during linking.
I would like to measure time in C, and I am having a tough time figuring it out, all I want is something like this:
start a timer
run a method
stop the timer
report the time taken (at least to micro accuracy)
Any help would be appreciated.
(I am compiling in windows using mingw)
High resolution timers that provide a resolution of 1 microsecond are system-specific, so you will have to use different methods to achieve this on different OS platforms. You may be interested in checking out the following article, which implements a cross-platform C++ timer class based on the functions described below:
[Song Ho Ahn - High Resolution Timer][1]
Windows
The Windows API provides extremely high resolution timer functions: QueryPerformanceCounter(), which returns the current elapsed ticks, and QueryPerformanceFrequency(), which returns the number of ticks per second.
Example:
#include <stdio.h>
#include <windows.h> // for Windows APIs
int main(void)
{
LARGE_INTEGER frequency; // ticks per second
LARGE_INTEGER t1, t2; // ticks
double elapsedTime;
// get ticks per second
QueryPerformanceFrequency(&frequency);
// start timer
QueryPerformanceCounter(&t1);
// do something
// ...
// stop timer
QueryPerformanceCounter(&t2);
// compute and print the elapsed time in millisec
elapsedTime = (t2.QuadPart - t1.QuadPart) * 1000.0 / frequency.QuadPart;
printf("%f ms.\n", elapsedTime);
}
Linux, Unix, and Mac
For Unix or Linux based system, you can use gettimeofday(). This function is declared in "sys/time.h".
Example:
#include <stdio.h>
#include <sys/time.h> // for gettimeofday()
int main(void)
{
struct timeval t1, t2;
double elapsedTime;
// start timer
gettimeofday(&t1, NULL);
// do something
// ...
// stop timer
gettimeofday(&t2, NULL);
// compute and print the elapsed time in millisec
elapsedTime = (t2.tv_sec - t1.tv_sec) * 1000.0; // sec to ms
elapsedTime += (t2.tv_usec - t1.tv_usec) / 1000.0; // us to ms
printf("%f ms.\n", elapsedTime);
}
On Linux you can use clock_gettime():
clock_gettime(CLOCK_REALTIME, &start); // get initial time-stamp
// ... do stuff ... //
clock_gettime(CLOCK_REALTIME, &end); // get final time-stamp
double t_ns = (double)(end.tv_sec - start.tv_sec) * 1.0e9 +
(double)(end.tv_nsec - start.tv_nsec);
// subtract time-stamps and
// multiply to get elapsed
// time in ns
Here's a header file I wrote to do some simple performance profiling (using manual timers):
#ifndef __ZENTIMER_H__
#define __ZENTIMER_H__
#ifdef ENABLE_ZENTIMER
#include <stdio.h>
#ifdef WIN32
#include <windows.h>
#else
#include <sys/time.h>
#endif
#ifdef HAVE_STDINT_H
#include <stdint.h>
#elif HAVE_INTTYPES_H
#include <inttypes.h>
#else
typedef unsigned char uint8_t;
typedef unsigned long int uint32_t;
typedef unsigned long long uint64_t;
#endif
#ifdef __cplusplus
extern "C" {
#pragma }
#endif /* __cplusplus */
#define ZTIME_USEC_PER_SEC 1000000
/* ztime_t represents usec */
typedef uint64_t ztime_t;
#ifdef WIN32
static uint64_t ztimer_freq = 0;
#endif
static void
ztime (ztime_t *ztimep)
{
#ifdef WIN32
QueryPerformanceCounter ((LARGE_INTEGER *) ztimep);
#else
struct timeval tv;
gettimeofday (&tv, NULL);
*ztimep = ((uint64_t) tv.tv_sec * ZTIME_USEC_PER_SEC) + tv.tv_usec;
#endif
}
enum {
ZTIMER_INACTIVE = 0,
ZTIMER_ACTIVE = (1 << 0),
ZTIMER_PAUSED = (1 << 1),
};
typedef struct {
ztime_t start;
ztime_t stop;
int state;
} ztimer_t;
#define ZTIMER_INITIALIZER { 0, 0, 0 }
/* default timer */
static ztimer_t __ztimer = ZTIMER_INITIALIZER;
static void
ZenTimerStart (ztimer_t *ztimer)
{
ztimer = ztimer ? ztimer : &__ztimer;
ztimer->state = ZTIMER_ACTIVE;
ztime (&ztimer->start);
}
static void
ZenTimerStop (ztimer_t *ztimer)
{
ztimer = ztimer ? ztimer : &__ztimer;
ztime (&ztimer->stop);
ztimer->state = ZTIMER_INACTIVE;
}
static void
ZenTimerPause (ztimer_t *ztimer)
{
ztimer = ztimer ? ztimer : &__ztimer;
ztime (&ztimer->stop);
ztimer->state |= ZTIMER_PAUSED;
}
static void
ZenTimerResume (ztimer_t *ztimer)
{
ztime_t now, delta;
ztimer = ztimer ? ztimer : &__ztimer;
/* unpause */
ztimer->state &= ~ZTIMER_PAUSED;
ztime (&now);
/* calculate time since paused */
delta = now - ztimer->stop;
/* adjust start time to account for time elapsed since paused */
ztimer->start += delta;
}
static double
ZenTimerElapsed (ztimer_t *ztimer, uint64_t *usec)
{
#ifdef WIN32
static uint64_t freq = 0;
ztime_t delta, stop;
if (freq == 0)
QueryPerformanceFrequency ((LARGE_INTEGER *) &freq);
#else
#define freq ZTIME_USEC_PER_SEC
ztime_t delta, stop;
#endif
ztimer = ztimer ? ztimer : &__ztimer;
if (ztimer->state != ZTIMER_ACTIVE)
stop = ztimer->stop;
else
ztime (&stop);
delta = stop - ztimer->start;
if (usec != NULL)
*usec = (uint64_t) (delta * ((double) ZTIME_USEC_PER_SEC / (double) freq));
return (double) delta / (double) freq;
}
static void
ZenTimerReport (ztimer_t *ztimer, const char *oper)
{
fprintf (stderr, "ZenTimer: %s took %.6f seconds\n", oper, ZenTimerElapsed (ztimer, NULL));
}
#ifdef __cplusplus
}
#endif /* __cplusplus */
#else /* ! ENABLE_ZENTIMER */
#define ZenTimerStart(ztimerp)
#define ZenTimerStop(ztimerp)
#define ZenTimerPause(ztimerp)
#define ZenTimerResume(ztimerp)
#define ZenTimerElapsed(ztimerp, usec)
#define ZenTimerReport(ztimerp, oper)
#endif /* ENABLE_ZENTIMER */
#endif /* __ZENTIMER_H__ */
The ztime() function is the main logic you need — it gets the current time and stores it in a 64bit uint measured in microseconds. You can then later do simple math to find out the elapsed time.
The ZenTimer*() functions are just helper functions to take a pointer to a simple timer struct, ztimer_t, which records the start time and the end time. The ZenTimerPause()/ZenTimerResume() functions allow you to, well, pause and resume the timer in case you want to print out some debugging information that you don't want timed, for example.
You can find a copy of the original header file at http://www.gnome.org/~fejj/code/zentimer.h in the off chance that I messed up the html escaping of <'s or something. It's licensed under MIT/X11 so feel free to copy it into any project you do.
The following is a group of versatile C functions for timer management based on the gettimeofday() system call. All the timer properties are contained in a single ticktimer struct - the interval you want, the total running time since the timer initialization, a pointer to the desired callback you want to call, the number of times the callback was called. A callback function would look like this:
void your_timer_cb (struct ticktimer *t) {
/* do your stuff here */
}
To initialize and start a timer, call ticktimer_init(your_timer, interval, TICKTIMER_RUN, your_timer_cb, 0).
In the main loop of your program call ticktimer_tick(your_timer) and it will decide whether the appropriate amount of time has passed to invoke the callback.
To stop a timer, just call ticktimer_ctl(your_timer, TICKTIMER_STOP).
ticktimer.h:
#ifndef __TICKTIMER_H
#define __TICKTIMER_H
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include <sys/types.h>
#define TICKTIMER_STOP 0x00
#define TICKTIMER_UNCOMPENSATE 0x00
#define TICKTIMER_RUN 0x01
#define TICKTIMER_COMPENSATE 0x02
struct ticktimer {
u_int64_t tm_tick_interval;
u_int64_t tm_last_ticked;
u_int64_t tm_total;
unsigned ticks_total;
void (*tick)(struct ticktimer *);
unsigned char flags;
int id;
};
void ticktimer_init (struct ticktimer *, u_int64_t, unsigned char, void (*)(struct ticktimer *), int);
unsigned ticktimer_tick (struct ticktimer *);
void ticktimer_ctl (struct ticktimer *, unsigned char);
struct ticktimer *ticktimer_alloc (void);
void ticktimer_free (struct ticktimer *);
void ticktimer_tick_all (void);
#endif
ticktimer.c:
#include "ticktimer.h"
#define TIMER_COUNT 100
static struct ticktimer timers[TIMER_COUNT];
static struct timeval tm;
/*!
#brief
Initializes/sets the ticktimer struct.
#param timer
Pointer to ticktimer struct.
#param interval
Ticking interval in microseconds.
#param flags
Flag bitmask. Use TICKTIMER_RUN | TICKTIMER_COMPENSATE
to start a compensating timer; TICKTIMER_RUN to start
a normal uncompensating timer.
#param tick
Ticking callback function.
#param id
Timer ID. Useful if you want to distinguish different
timers within the same callback function.
*/
void ticktimer_init (struct ticktimer *timer, u_int64_t interval, unsigned char flags, void (*tick)(struct ticktimer *), int id) {
gettimeofday(&tm, NULL);
timer->tm_tick_interval = interval;
timer->tm_last_ticked = tm.tv_sec * 1000000 + tm.tv_usec;
timer->tm_total = 0;
timer->ticks_total = 0;
timer->tick = tick;
timer->flags = flags;
timer->id = id;
}
/*!
#brief
Checks the status of a ticktimer and performs a tick(s) if
necessary.
#param timer
Pointer to ticktimer struct.
#return
The number of times the timer was ticked.
*/
unsigned ticktimer_tick (struct ticktimer *timer) {
register typeof(timer->tm_tick_interval) now;
register typeof(timer->ticks_total) nticks, i;
if (timer->flags & TICKTIMER_RUN) {
gettimeofday(&tm, NULL);
now = tm.tv_sec * 1000000 + tm.tv_usec;
if (now >= timer->tm_last_ticked + timer->tm_tick_interval) {
timer->tm_total += now - timer->tm_last_ticked;
if (timer->flags & TICKTIMER_COMPENSATE) {
nticks = (now - timer->tm_last_ticked) / timer->tm_tick_interval;
timer->tm_last_ticked = now - ((now - timer->tm_last_ticked) % timer->tm_tick_interval);
for (i = 0; i < nticks; i++) {
timer->tick(timer);
timer->ticks_total++;
if (timer->tick == NULL) {
break;
}
}
return nticks;
} else {
timer->tm_last_ticked = now;
timer->tick(timer);
timer->ticks_total++;
return 1;
}
}
}
return 0;
}
/*!
#brief
Controls the behaviour of a ticktimer.
#param timer
Pointer to ticktimer struct.
#param flags
Flag bitmask.
*/
inline void ticktimer_ctl (struct ticktimer *timer, unsigned char flags) {
timer->flags = flags;
}
/*!
#brief
Allocates a ticktimer struct from an internal
statically allocated list.
#return
Pointer to the newly allocated ticktimer struct
or NULL when no more space is available.
*/
struct ticktimer *ticktimer_alloc (void) {
register int i;
for (i = 0; i < TIMER_COUNT; i++) {
if (timers[i].tick == NULL) {
return timers + i;
}
}
return NULL;
}
/*!
#brief
Marks a previously allocated ticktimer struct as free.
#param timer
Pointer to ticktimer struct, usually returned by
ticktimer_alloc().
*/
inline void ticktimer_free (struct ticktimer *timer) {
timer->tick = NULL;
}
/*!
#brief
Checks the status of all allocated timers from the
internal list and performs ticks where necessary.
#note
Should be called in the main loop.
*/
inline void ticktimer_tick_all (void) {
register int i;
for (i = 0; i < TIMER_COUNT; i++) {
if (timers[i].tick != NULL) {
ticktimer_tick(timers + i);
}
}
}
Using the time.h library, try something like this:
long start_time, end_time, elapsed;
start_time = clock();
// Do something
end_time = clock();
elapsed = (end_time - start_time) / CLOCKS_PER_SEC * 1000;
If your Linux system supports it, clock_gettime(CLOCK_MONOTONIC) should be a high resolution timer that is unaffected by system date changes (e.g. NTP daemons).
Great answers for GNU environments above and below...
But... what if you're not running on an OS? (or a PC for that matter, or you need to time your timer interrupts themselves?) Here's a solution that uses the x86 CPU timestamp counter directly... Not because this is good practice, or should be done, ever, when running under an OS...
Caveat: Only works on x86, with frequency scaling disabled.
Under Linux, only works on non-tickless kernels
rdtsc.c:
#include <sys/time.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef unsigned long long int64;
static __inline__ int64 getticks(void)
{
unsigned a, d;
asm volatile("rdtsc" : "=a" (a), "=d" (d));
return (((int64)a) | (((int64)d) << 32));
}
int main(){
int64 tick,tick1;
unsigned time=0,mt;
// mt is the divisor to give microseconds
FILE *pf;
int i,r,l,n=0;
char s[100];
// time how long it takes to get the divisors, as a test
tick = getticks();
// get the divisors - todo: for max performance this can
// output a new binary or library with these values hardcoded
// for the relevant CPU - if you use the equivalent assembler for
// that CPU
pf = fopen("/proc/cpuinfo","r");
do {
r=fscanf(pf,"%s",&s[0]);
if (r<0) {
n=5; break;
} else if (n==0) {
if (strcmp("MHz",s)==0) n=1;
} else if (n==1) {
if (strcmp(":",s)==0) n=2;
} else if (n==2) {
n=3;
};
} while (n<3);
fclose(pf);
s[9]=(char)0;
strcpy(&s[4],&s[5]);
mt=atoi(s);
printf("#define mt %u // (%s Hz) hardcode this for your a CPU-specific binary ;-)\n",mt,s);
tick1 = getticks();
time = (unsigned)((tick1-tick)/mt);
printf("%u ms\n",time);
// time the duration of sleep(1) - plus overheads ;-)
tick = getticks();
sleep(1);
tick1 = getticks();
time = (unsigned)((tick1-tick)/mt);
printf("%u ms\n",time);
return 0;
}
compile and run with
$ gcc rdtsc.c -o rdtsc && ./rdtsc
It reads the divisor for your CPU from /proc/cpuinfo and shows how long it took to read that in microseconds, as well as how long it takes to execute sleep(1) in microseconds... Assuming the Mhz rating in /proc/cpuinfo always contains 3 decimal places :-o
I've just started with the evk1105 dev.board. and i need to get printf() redirected to usart.
I have the following code (edited usart example for evk1105):
#include <avr32/io.h>
#include "compiler.h"
#include "board.h"
#include "power_clocks_lib.h"
#include "gpio.h"
#include "usart.h"
#include "nmea.h"
#include <stdio.h>
/*! \name USART Settings
*/
//! #{
# define EXAMPLE_TARGET_PBACLK_FREQ_HZ FOSC0 // PBA clock target frequency, in Hz
#if BOARD == EVK1105
# define EXAMPLE_USART (&AVR32_USART0)
# define EXAMPLE_USART_RX_PIN AVR32_USART0_RXD_0_0_PIN
# define EXAMPLE_USART_RX_FUNCTION AVR32_USART0_RXD_0_0_FUNCTION
# define EXAMPLE_USART_TX_PIN AVR32_USART0_TXD_0_0_PIN
# define EXAMPLE_USART_TX_FUNCTION AVR32_USART0_TXD_0_0_FUNCTION
# define EXAMPLE_USART_CLOCK_MASK AVR32_USART0_CLK_PBA
# define EXAMPLE_PDCA_CLOCK_HSB AVR32_PDCA_CLK_HSB
# define EXAMPLE_PDCA_CLOCK_PB AVR32_PDCA_CLK_PBA
#endif
#if !defined(EXAMPLE_USART) || \
!defined(EXAMPLE_USART_RX_PIN) || \
!defined(EXAMPLE_USART_RX_FUNCTION) || \
!defined(EXAMPLE_USART_TX_PIN) || \
!defined(EXAMPLE_USART_TX_FUNCTION)
# error The USART configuration to use in this example is missing.
#endif
//! #}
#if UC3L
/*! \name Parameters to pcl_configure_clocks().
*/
//! #{
static scif_gclk_opt_t gc_dfllif_ref_opt = { SCIF_GCCTRL_SLOWCLOCK, 0, false };
static pcl_freq_param_t pcl_dfll_freq_param =
{
.main_clk_src = PCL_MC_DFLL0,
.cpu_f = EXAMPLE_TARGET_MCUCLK_FREQ_HZ,
.pba_f = EXAMPLE_TARGET_PBACLK_FREQ_HZ,
.pbb_f = EXAMPLE_TARGET_PBACLK_FREQ_HZ,
.dfll_f = EXAMPLE_TARGET_DFLL_FREQ_HZ,
.pextra_params = &gc_dfllif_ref_opt
};
//! #}
#endif
/* STIAN */
char nmea1[] ="$GPRMC,131637.000,V,5820.0658,N,00834.5652,E,0.00,,090911,,,A*69";
char nmea2[]="$GPRMC,131637.000,A,5820.0658,N,00834.5652,E,0.00,,090911,,,A*7E";
char nmea3[]="$GPRMC,131640.000,A,5820.0657,N,00834.5652,E,0.00,,090911,,,A*71";
char line [82];
char nmea[90];
/*END STIAN*/
int usart_get_return(volatile avr32_usart_t *usart)
{
int rx_char;
int retval = USART_SUCCESS;
int i = 0;
while (1)
{
rx_char = usart_getchar(usart);
if (rx_char == USART_FAILURE)
{
usart_write_line(usart, "Error!!!\r\n");
retval = USART_FAILURE;
break;
}
if (rx_char == '\x03')
{
retval = USART_FAILURE;
break;
}
usart_putchar(usart, rx_char);
nmea[i] = rx_char;
i++;
if (rx_char == '\r')
{ // Add a LF and consider this as the end of the line.
usart_putchar(usart, '\n');
break;
}
}
return retval;
}
int main(void)
{
pcl_switch_to_osc(PCL_OSC0, FOSC0, OSC0_STARTUP);
static const gpio_map_t USART_GPIO_MAP =
{
{EXAMPLE_USART_RX_PIN, EXAMPLE_USART_RX_FUNCTION},
{EXAMPLE_USART_TX_PIN, EXAMPLE_USART_TX_FUNCTION}
};
// USART options.
static const usart_options_t USART_OPTIONS =
{
.baudrate = 57600,
.charlength = 8,
.paritytype = USART_NO_PARITY,
.stopbits = USART_1_STOPBIT,
.channelmode = USART_NORMAL_CHMODE
};
//set_usart_base( ( void * ) EXAMPLE_USART );
// Assign GPIO to USART.
gpio_enable_module(USART_GPIO_MAP,
sizeof(USART_GPIO_MAP) / sizeof(USART_GPIO_MAP[0]));
// Initialize USART in RS232 mode.
usart_init_rs232(EXAMPLE_USART, &USART_OPTIONS, EXAMPLE_TARGET_PBACLK_FREQ_HZ);
// Hello world!
usart_write_line(EXAMPLE_USART, "Polycon AIS-module! (press enter)\r\n");
// Press enter to continue.
while (usart_get_return(EXAMPLE_USART) == USART_FAILURE); // Get and echo characters until end of line.
printf("NMEA inneholder:%s\r\n",nmea);
while (usart_get_return(EXAMPLE_USART) == USART_FAILURE); // Get and echo characters until end of line.
usart_write_line(EXAMPLE_USART, "Goodbye.\r\n");
while (true);
}
When adding set_usart_base I get the following compile error implicit declaration of function 'set_usart_base'
set_usart_base found here: avrfreaks.net
Any hints on what I'm doing wrong?
Instead of this:
set_usart_base( ( void * ) EXAMPLE_USART );
use this:
extern volatile avr32_usart_t *volatile stdio_usart_base;
stdio_usart_base = EXAMPLE_USART;
Declaration to use may be:
extern volatile struct avr32_usart_t *volatile stdio_usart_base;
Take a look to: http://support.atmel.no/knowledgebase/avr32studiohelp/AT32UC3B_Software_Framework/SERVICES/USB/CLASS/HID/EXAMPLES/HID_EXAMPLE_STANDALONE/DOC/html/a00045.html#l00171