I'm having a problem reading and writing to structs across multiple files. Essentially I need to write to variables within a struct that are later checked during a timer interrupt. When this happens, the new timer value is taken as a member in that struct. At the moment I hard set these timer values in a while(1) loop, but later these values will be taken from some algorithm. I'm not quite sure if I'm doing this reading of struct members correctly. The project compiles, however during runtime, it sets the timers to random values. GDB degugging confirmed they are correct however.
If I set the timer values directly, everything works file.
This is an embedded project on an ARM cortex M4.
I have a structure defined in types.h
#ifndef __TYPES_H
#define __TYPES_H
typedef struct { uint32_t a; uint32_t b; uint32_t c;} myStruct;
#endif
Then in main.c
#include <types.h>
myStruct hello
int main(void){
while(1){
hello.a = 10;
hello.b = 43;
hello.c = 98;
}
}
Then in interrupt.c
#include <types.h>
myStruct hello
int count = 0;
void timer_IRQHandler(void){
if(interrupt != RESET){
switch(count){
case 0:
timerSet(hello.a); // if i just put a number here, it works fine
count++;
break;
case 1:
timerSet(hello.b);
count++;
break;
case 2:
timerSet(hello.c);
count++;
break;
}
resetInterrupt();
}
}
--- SOLUTION ---
Ok I've figured it out, could do with moving things around but otherwise it works like this:
types.h
#ifndef __TYPES_H
#define __TYPES_H
typedef struct { uint32_t a; uint32_t b; uint32_t c;} myStruct;
#endif
Then in main.c
#include <types.h>
myStruct volatile hello = {10,10,10};
int main(void){
while(1){
hello.a = 10;
hello.b = 43;
hello.c = 98;
}
}
Then in interrupt.c
#include <types.h>
extern myStruct hello
int count = 0;
void timer_IRQHandler(void){
if(interrupt != RESET){
switch(count){
case 0:
timerSet(hello.a); // if i just put a number here, it works fine
count++;
break;
case 1:
timerSet(hello.b);
count++;
break;
case 2:
timerSet(hello.c);
count++;
break;
}
resetInterrupt();
}
}
The extern seems to have solved the problem of getting the struct across different files, and the initial value declaration of {10,10,10} has, I think solved some memory allocation problem. The code compiles, but doesn't hold correct values without it. I don't know what volatile does yet, no difference if I remove it. Something I shall read up on.
declare it in the header
extern myStruct hello;
and define it in only one cpp
myStruct hello;
Are you having a problem with the compiler optimizing the accesses in the while loop? Since the compiler doesn't know that another thread of execution is looking at the values of hello, maybe its just not writing them? Try to add volatile to your "extern myStruct hello" or look at the mixed assembly output and see if its writing through to the hello struct.
See here
You are in effect declaring the struct twice (with the same name) which is why your code is not working. Define it once (say in main) and then use extern to reference it in your other files.
extern myStruct hello;
It appears to me that your timer_IRQHandler is called in the kernel as an interrupt routine. If true, main is probably never called.
I would try to statically initialize your struct, rather than rely on main to initialize it. For example:
myStruct hello = { 10, 43, 98 };
and yes, if multiple files reference it you should declare it as extern in the header and define/initialize it only once in a source file.
As for volatile, that's for device registers or memory-mapped addresses that might not give the same answer if read twice. It tells the compiler to not try to optimize out multiple reads for that memory location.
Related
I've recently started working on a chess engine, and am having trouble with a function to apply moves to the board. I have a structure type for the board state, and another to store moves. These are both in my header file below.
#ifndef DECLARATIONS_H
#define DECLARATIONS_H
#include <stdbool.h>
#define BOARD_SIZE 120
typedef struct move {
int startingSquare;
int endingSquare;
int promotionPiece;
} move;
typedef struct boardState {
int board[BOARD_SIZE];
bool whoseTurn;
int ply;
int threeMoveRuleCount;
int fiftyMoveRuleCount;
bool whiteCastleKingside;
bool whiteCastleQueenside;
bool blackCastleKingside;
bool blackCastleQueenside;
int enPassant;
float evaluation;
move previousMove;
} boardState;
boardState currentBoard;
#endif
Main.c calls the "Process Move" function from movegeneration.c. It passes one of the boardstate types and one of the move types:
#include <stdio.h>
#include <string.h>
#include "declarations.h"
int main () {
move firstMove;
firstMove.startingSquare = 35;
firstMove.endingSquare = 55;
firstMove.promotionPiece = 0;
printf("Value of firstMove.endingSquare: %d\n", firstMove.endingSquare);
printf("Value of firstMove.startingSquare: %d\n", firstMove.startingSquare);
printf("Value of firstMove.promotionPiece: %d\n", firstMove.promotionPiece);
processMove(currentBoard, firstMove);
return 0;
}
Below is movegeneration.c, which contains the function to process the move:
#include <stdio.h>
#include "declarations.h"
boardState processMove(boardState, move);
boardState processMove(boardState oldBoardState, move moveToApply) {
boardState newBoardState = oldBoardState;
printf("Value of moveToApply.endingSquare: %d\n", moveToApply.endingSquare);
printf("Value of moveToApply.startingSquare: %d\n", moveToApply.startingSquare);
printf("Value of moveToApply.promotionPiece: %d\n", moveToApply.promotionPiece);
return newBoardState;
}
And here's the program output:
Value of firstMove.endingSquare: 55
Value of firstMove.startingSquare: 35
Value of firstMove.promotionPiece: 0
Value of moveToApply.endingSquare: 0
Value of moveToApply.startingSquare: 55
Value of moveToApply.promotionPiece: 1996058613
This isn't all the code from the .c files, but it's everything relevant here. What makes this bizarre is that the values of the move change as soon as I call the function. When I put all the code into one large .c file and compile that way, the problem goes away, but I'm trying to keep the code separate to stay organized. This one has me completely stumped. I'd appreciate any help!
There's at least 2 problems here, causing undefined behaviour.
Firstly, there are multiple definitions of boardState currentBoard; . Remember that #include is a plain text replacement, so both of your c files end up with a definition of that object. See here for an in-depth explanation with examples.
If you want to have a global object accessible from multiple translation units then the header file should contain a declaration only (i.e. prepend extern to the current line), and exactly one of the .c files should contain the definition.
Secondly, in main() you call an undeclared function processMove. If you compile in standard mode then the compiler should generate an error message. This is likely the cause of your symptoms, and I would strongly recommend invoking your compiler in modern standard mode with a high diagnostic level, as it would have saved you a lot of time to find out about this problem sooner.
To fix this, the declaration boardState processMove(boardState, move); should be in declarations.h.
I want to be able to modify a variable from one C file and see the changes of that variable on the other one
Here are my C files:
file1.c:
#include "myheader.h"
int
main( void )
{
printf("Variable %d\n", var);
}
file2.c:
#include "myheader.h"
int main(void){
int var = 1;
var = var + 1;
}
The header file looks like this:
extern int var;
Now, I want to run file2.c first and than when I run file1.c print the incremented value of var. Ideas?
I think I am doing everything like this answer, but can't make it work.
PS: Just started learning C.
Each of your "files".c has a main function and thus will compile into a separate executable.
So you can't have one executable increment a variable in its own address space and then have another executable see the change in someone else's address space - the other executable will have an own variable in its own address space. Unless you would use advanced inter process communication (but that is Lesson 42).
When I compile my code for my STM32F429 CPU everything works fine when I use the -O0 flag but as soon as I use a higher optimization (-O1, -O2, and -O3) the code breaks.
I'm using the CMSIS+HAL libraries from ST and some basic code.
The problem is that even though *uart_irq is defined as volatile the if (uart_irq && uart_irq->SOURCE == IRQ_SOURCE_UART) in the main loop is never evaluated.
I have tried to define uart_irq as a volatile void * without success.
The only thing that work is if uart_irq is defined as a volatile uint32_t and the integer is cast to a irq_instance when used as the compiler wont remove that during optimization.
I would be happy if anybody would shed some light on the problem.
Is this supposed to be the standard behavior?
Is this a known bug in the compiler?
main.h
#define API_COMMAND_SIZE 6
typedef struct irq_instance_s
{
uint8_t SOURCE;
uint8_t TYPE;
uint8_t *CONTEXT;
uint8_t SIZE;
} irq_instance;
extern volatile irq_instance *uart_irq;
main.c
The receive pointer is freed inside hande_command
#include "main.h
volatile irq_instance *uart_irq = 0;
int main(void)
{
uint8_t *receive = 0;
<Initialize stuff>
/* Initialize first UART recieve */
receive = malloc(API_COMMAND_SIZE);
while (HAL_UART_Receive_IT(&huart1, receive, API_COMMAND_SIZE) == HAL_BUSY);
/* Program Main loop */
while(1) {
if (uart_irq && uart_irq->SOURCE == IRQ_SOURCE_UART) { /* <---- Problem is here */
handle_interrupt(uart_irq);
free((void *)uart_irq);
uart_irq = 0;
}
}
}
stm32f4xx_it.c
The HAL_UART_RxCpltCallback are called after each successful UART receive.
#include "main.h"
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart)
{
uint8_t *receive = 0;
uart_irq = calloc(1, sizeof(irq_instance));
uart_irq->SOURCE = IRQ_SOURCE_UART;
uart_irq->CONTEXT = huart->pRxBuffPtr - huart->RxXferSize;
uart_irq->SIZE = huart->RxXferSize;
uart_irq->TYPE = IRQ_TYPE_COMMAND;
receive = malloc(API_COMMAND_SIZE);
while (HAL_UART_Receive_IT(&huart1, receive, API_COMMAND_SIZE) == HAL_BUSY);
}
volatile irq_instance *uart_irq
says that the thing pointed to by uart_irq is volatile. But
if (uart_irq && uart_irq->SOURCE == IRQ_SOURCE_UART)
is looking at the pointer itself, not the thing that's being pointed to. If the pointer itself is also volatile, which looking at your code it is, then declare it like this:
volatile irq_instance * volatile uart_irq
If I read this correctly then you are changing the uart_irq inside the IRQ handler and it's this change of pointer value that the optimizer cannot see in the regular program flow and hence is optimizing away.
The correct declaration for a volatile pointer is irq_instance * volatile uart_irq. The way that you have declared it tells gcc that the value pointed to by the pointer is volatile. If this is also the case then you may combine the two with volatile irq_instance * volatile uart_irq.
The variable uart_irq is volatile, not just what it points to... Define it this way:
extern irq_instance * volatile uart_irq;
I have 4 Files = pic.h, main.c, framehandle.c and framehandle.h
Both pic.h and framehandle.h are included within my main:
#include "pic.h"
#include "framehandling.h"
pic.h has the following struct definition.
struct f
{
unsigned sleep : 1;
unsigned push : 1;
unsigned rx : 1;
unsigned tx : 1;
unsigned validPacket : 1;
};
I declare this struct in my main.c file using
struct f flag;
when I try to use this inside framehandle.c I get an undeclared error which I understand.
To solve this I add the following inside framehandle.h:
extern struct f flag;
However the compiler is still complaining that flags are not declared inside framehandle.c
What am i doing wrong?
wouldn't extern struct f flag; supposed to tell the compiler to look else where for the decleration?
wouldnt't placing this inside the subjects header be the correct place?
--Edit--
I am adding the sequence of my include files and my variable declerations
#include "pic.h"
#include "framehandling.h"
struct f flag;
void main(void)
{ }
It will depend on if you have declared struct f flag; in main.c as global or local. If you have it declared inside of the function, you will have to move the declaration outside the function.
The solution to the problem was that extern struct f flag should have been inside pic.h. It makes sense in a way, to place it right after the decleration.. I would also like to thank you all for your input.
There is a header file named 'AAA.h'. In this header file we have define a structure called lrd, which looks like:
struct lrd
{
int tc;
char ptc[5];
char stc[5];
char ath[5];
int vc;
};
struct lrd lr;
This header file 'AAA.h' is included in two different files name 'BBB.c' and 'CCC.c'. We have assigned the values for structure variable lr in the 'BBB.c' file as following:
lr.tc=tc;
memcpy(lr.ptc,ptc,sizeof(ptc));
memcpy(lr.stc,stc,sizeof(stc));
memcpy(lr.ath,ath,sizeof(ath));
lr.vc=vc;
Above source variables take the value from database. And we use structure variable lr in the 'CCC.c' file. We are using structure lrd variable as follows:
char *ptc()
{
sprintf(str, "lr.ptc(%s)", lr.ptc);
trace(str);
return lr.ptc;
}
char *stc()
{
sprintf(str, "lr.stc(%s)", lr.stc);
trace(str);
return lr.stc;
}
Variable stc gives the wrong value in the 'CCC.c' file.
Please help me to figure it out.
See what benjarobin says. I am just showing you a small footprint
AAA.h
#ifndef _AAA_H
struct abc
{
int x;
char *y;
char *Z;
};
extern struct abc p;
extern void assign(void);
extern void display (void);
#endif
CCC.c
#include <stdio.h>
#include "AAA.h"
struct abc p; // Deceleration of p
void assign ()
{
p.x=20;
p.y="abcd";
p.Z="xyz0";
return;
}
BBB.c
#include <stdio.h>
#include "AAA.h"
void display (void)
{
printf("x = %d, y =%s, z=%s",p.x,p.y,p.Z);
}
DDD.c contains the main function.
#include <stdio.h>
#include "AAA.h"
void main ()
{
printf("\n\nAssigning Values\n\n");
assign ();
printf("\n\nIN BBB.c\n\n");
display ();
printf("\n\nIN MAIN\n\n");
printf("x = %d, y =%s, z=%s",p.x,p.y,p.Z);
}
output is
Assigning Values
IN BBB.c
x = 20, y =abcd, z=xyz0
IN MAIN
x = 20, y =abcd, z=xyz0
Your code shows:
memcpy(lr.ptc,ptc,sizeof(ptc));
memcpy(lr.stc,stc,sizeof(stc));
memcpy(lr.ath,ath,sizeof(ath));
It doesn't show the declarations of ptc, stc or ath. Since you are copying to lr.ptc etc, the operand of sizeof() should be lr.ptc etc, not the size of the source. Or, if you're being really careful, the minimum of the two sizes.
You could/should debug this with:
printf("%d (%s)(%s)(%s) %d\n", lr.tc, lr.ptc, lr.stc, lr.ath, lr.vc);
immediately after the assignments. If that shows the wrong value, then you know the problem is in the assignments. If that shows the correct values, then you can start looking for stray pointers and other such ghastly problems.
There's no proof that this is the problem because you've not produced an SSCCE (Short, Self-Contained, Correct Example). Specifically, you've only produced fragments of code, not an integrated set of three source files (though we can infer the header from the information given). And without the code that actually demonstrates the problem (all of it, including definitions for all the variables and functions — but not including any superfluous material), we can only speculate.
External variable should be avoid, but if you still want to use a global variable, you shall do these :
Declare the variable in a .c file
struct lrd lr;
Add the external definition in the .h (AAA.h)
external struct lrd lr;