I was trying to pass PORTs address trough a struct by using a function, by i don't know how to correct work with pointers. Here's the code of my struct and function:
typedef struct {
read:1;
last_read:1;
changed:1;
unsigned short *port; //Here the declaration of the pointer that will receive the address
pin:1;
active_state:1;
} Input;
void Setup_input(Input s,char *port, char pin, char active_state){
s.port = &port; //HERE I TRY TO PASS THE ADDRESS OF THE PORT TO THE POINTER OBJECT
s.pin = pin;
s.active_state = active_state;
It turns out that I'm not doing it correctly and I'm not able to read or control correctly the PORT. I'm using Mikroelectronic PRO compilers.
This line of code
s.port = &port;
stores the address of the parameter into the member port. When you dereference the pointer in the structure you will access the stack memory where the parameter port were while calling Setup_input(). This causes undefined behavior.
What you obviously want is to assigne the value of the parameter:
s.port = port;
Related
I am writing a function:
void callFunctionAt(uint32_t address){
//There is a void at address, how do I run it?
}
This is in Atmel Studio's C++. If previous questions are to be believed, the simple answer is to write the line "address();". This cannot be correct. Without changing the header of this function, how would one call the function located at the address given?
The answer should be system-agnostic for all micro controllers which support standard c++ compilation.
The common way to do this is to give the argument the correct type. Then you can call it right away:
void callFunctionAt(void (*address)()) {
address();
}
However, since you wrote "Without changing the header of this function [...]", you need to cast the unsigned integer to a function pointer:
void callFunctionAt(uint32_t address) {
void (*f)() = reinterpret_cast<void (*f)()>(address);
f();
}
But this is not safe and not portabel because it assumes that the uint32_t can be casted into a function pointer. And this needs not to be true: "[...] system-agnostic for all micro controllers [...]". Function pointers can have other widths than 32 bits. Pointers in general might consist of more than the pure address, for example include a selector for memory spaces, depending on the system's architecture.
If you got the address from a linker script, you might have declared it like this:
extern const uint32_t ext_func;
And like to use it so:
callFunctionAt(ext_func);
But you can change the declaration into:
extern void ext_func();
And call it directly or indirectly:
ext_func();
callFunctionAt(&ext_func);
The definition in the linker can stay as it is, because the linker knows nothing about types.
There is no generic way. It depends on which compiler you are using. In the following I'll assume avr-g++ because it's common and freely available.
Spoiler: On AVR, it's more complicated than on most other machines.
Suppose you actually have a uint32_t address which would be a byte address. Function pointers in avr-g++ are word addresses actually, where a word has 16 bits. Hence, you'll have to divide the byte address by 2 first to get a word address; then cast it to a function pointer and call it:
#include <stdint.h>
typedef void (*func_t)(void);
void callFunctionAt (uint32_t byte_address)
{
func_t func = (func_t) (byte_address >> 1);
func();
}
If you started with a word address, then you can call it without further ado:
void callFunctionAt (uint32_t address)
{
((func_t) word_address)();
}
This will only work for devices with up to 128KiB of flash memory!
The reason is that addresses in avr-g++ are 16 bits long, cf. the layout of void* as per avr-gcc ABI. This means using scalar addresses on devices with flash > 128KiB will not work in general, for example when you issue callFunctionAt (0x30000) on an ATmega2560.
On such devices, the 16-bit address in Z register used by EICALL instruction is extended by the value held in the EIND special function register, and you must not change EIND after entering main. The avr-g++ documentation is clear about that.
The crucial point here is how you are getting the address. First, in order to call and pass it around properly, use a function pointer:
typedef void (*func_t)(void);
void callFunctionAt (func_t address)
{
address();
}
void func (void);
void call_func()
{
func_t addr = func;
callFunctionAt (addr);
}
I am using void argument in the declaration because this is how you'd do it in C.
Or, if you don't like the typedef:
void callFunctionAt (void (*address)(void))
{
address();
}
void func (void);
void call_func ()
{
void (*addr)(void) = func;
callFunctionAt (addr);
}
If you want to call a function at a specific word address like, for example 0x0 to "reset"1 the µC, you could
void call_0x0()
{
callFunctionAt ((func_t) 0x0);
}
but whether this works depends on where your vector table is located, or more specifically, how EIND was initialized by the startup code. What will always work is using a symbol and define it with -Wl,--defsym,func=0 when linking with the following code:
extern "C" void func();
void call_func ()
{
void (*addr)(void) = func;
callFunctionAt (addr);
}
The big difference compared to using 0x0 directly it that the compiler will wrap symbol func with symbol modifier gs which it will not do when using 0x0 directly:
_Z9call_funcv:
ldi r24,lo8(gs(func))
ldi r25,hi8(gs(func))
jmp _Z14callFunctionAtPFvvE
This is needed if the address is out of the scope of EIJMP to advise the linker to generate a stub.
1 This will not reset the hardware. The best approach to force a reset is by letting the watchdog timer (WDT) issue a reset for you.
Methods
Yet another situation is when you want the address of a non-static method of a class because you also need a this pointer in that case:
class A
{
int a = 1;
public:
int method1 () { return a += 1; }
int method2 () { return a += 2; }
};
void callFunctionAt (A *b, int (A::*f)())
{
A a;
(a.*f)();
(b->*f)();
}
void call_method ()
{
A a;
callFunctionAt (&a, &A::method1);
callFunctionAt (&a, &A::method2);
}
The 2nd argument of callFunctionAt specifies which method (of a given prototype) you want, but you also need an object (or pointer to one) to apply it. avr-g++ will use gs when taking the method's address (provided the following call(s) cannot be inlined), thus it will also work for all AVR devices.
Based on comments I think you are asking about how microcontroller calls function.
Could you compile your program to see assembly files?
I would recommend you to read one of them.
Every function after compiling are translated to instructions that CPU can do (loading to register, adding to register etc.).
So then your void foo(int x) {statements;} compile to simple CPU instructions and whenever you call foo(x) in your program, you are moving to instructions that are related to foo - you are calling a subroutine.
As far as I remeber there is a CALL function in AVR to invoke subroutines and the name of subroutine is the label where executing program jump and invoking next instruction at adress.
I think you can clarify your doubts when you read some AVR assembly tutorials.
It is fun (at least for me) to see what exactly CPU do when it calls function that I wrote, but it required to know what instructions do. You develop in AVR so there is a set of instructions that you can read about in this PDF and compare with your assembly files.
I'm facing a problem can't be able to resolve to store an array of struct in nvs.
I have this structure composed of variable length String:
typedef struct
{
String Name;
String Surname;
String Status;
String Expiry;
} EpromTags;
EpromTags arraytag[50];
void setup()
{
//should load arraytag from EEPROM here
}
In other routines I have this data coming from a remote server, so I'm saving it to me arraytag
for (int i=0, i<50,i++)
{
arraytag[i].Name = valuename[i];
arraytag[i].Surname = valuesurname[i];
arraytag[i].Status = valuestatus[i];
arraytag[i].Expiry = valueexp[i];
}
//should save to arraytag to EEPROM here
The idea is to load the value of the structure to men on arrive and load back on setup.
I have been able to write single elements to EEPROM but I'm finding difficulties in saving this array of struct.
can someone drive me in the right directions or have suggestions?
The String class handles a char array buffer allocated in heap memory. The object of class String only has a pointer to this buffer. If you store a String object to EEPROM, you don't store the buffer and after retrieving the object the pointer is not valid.
Use C strings (zero terminated character arrays) of predefined size to store a struct with string in EEPROM.
typedef struct
{
char name[NAME_MAX_LENGTH];
char surname[SURENAME_MAX_LENGTH];
char status[STATUS_LENGTH];
char expiry[EXP_LENGTH];
} EpromTags;
To save any data type you can use EEPROM.put(). To read it back you use EEPROM.get(). So you can use a straight forward EEPROM.put(arraytag) to store all 50 items of the array and EEPROM.get(arraytag) to read it back.
The size of the struct is sizeof(EpromTags). The size of the array is count of items multiplied by the size of the item.
Note that the ESP32 EEPROM library emulates the EEPROM in flash memory and requires to call EEPROM.begin() and EEPROM.commit(). See the examples of the ESP32 EEPROM library on how to use it.
As my question says, to access Port by its address, Can we write it as "&PORTA" ??
In my problem, I want to read/write port value from/to HMI, using Modbus Protocol.
I have an array of structure :
typedef struct func_code_reg {
volatile uint16_t addr;
volatile uint16_t *data;
}RW_REG_DATA;
// described as
RW_REG_DATA rwCoilStatusTbl[] = {
// Addr Data_Register
{ 0, &rwCoil_0000 },
{ 1, &rwCoil_0001 },
};
Whenever HMI reads data , it reads the current value of register &rwCoil_000x
Whenever HMI writes data, the register &rwCoil_000x gets updated.
Instead, I would like to use &PORTA to read Port status or to update Port Status.
Is it possible ?? & if possible, is it the correct way to update the Port status ??
Or any better way, please guide me.
(I am using dsPic33E series)
PORTx is already mapped to the contents of the PORTx register, you don't need its address. To read from a port, use the PORTx register. To write, use the LATx register.
So if you want the value rwCoil_000x to be reflected on a port (A), simply write:
LATA = rwCoil_000x;
And if you want to read from the port into the same variable, write:
rwCoil_000x = PORTA;
Of course, this assumes PORTA is set to be a general purpose output.
If you want to generalize over many different ports, you can build an array of volatile references to *PORT.
I did this once for the other way, the outputs, LAT registers, see Using an array of LATs to toggle outputs. type of (byte) pointer to lat
I am trying using the arduino IDE to write a sketch. I have data in progmem and want to move the data with a function to a memory address allocated using malloc. My code is below:
const uint8_t Data_6 [256] PROGMEM = { 0x11, 0x39......};
void setup() {
Serial.begin(57600);
oddBallData (Data_6, 0x00, 256);
}
void main() {
}
void oddBallData(const uint8_t *data, uint8_t mem, uint16_t bytes) {
uint8_t *buff1 = (uint8_t*)malloc(sizeof(bytes));
if (buff1 = 0) {
Serial.println(F("FATAL ERROR - NO MEMORY"));
}
else {
for (uint16_t x = 0; x < 6; x++ ) {
buff1[x] = data[x]; //edited from data[0] to [x] made a mistake in post
Serial.println(buff1[x],HEX);
}
}
buff1[0] = data[0];
Serial.println(buff1[0],HEX);
free(buff1);
}
I have some data saved in progmem and want to write that data to a second device using i2c protocol. I have multiple constant arrays of data saved to my progmem, with different sizes. So I have used malloc to reserve some memory from the heap, inside of the function.
I have not been able to write the data from the progmem so I have stripped things back to so that I am just trying to point to the progmem data using malloc and then print it.
This is where I found a the problem. If I print a single array entry from the data constant. It prints the correct value. If I use a loop I get mixed results, the loop works as long as the condition check value is below 3 or sometimes below 6!!!...?
If above this value the entire print is just garbage. Can anyone explain what I am seeing?
The culprit is probably
uint8_t *buff1 = (uint8_t*)malloc(sizeof(bytes));
sizeof(bytes) returns the size of the variable (which is probably 2 bytes) so you are just allocating 2 bytes of memory. You should use the value directly, eg:
uint8_t* buff1 = malloc(bytes);
Mind that the cast is not required in C since a void* is convertible to any other pointer type directly.
Again - AVR PROGMEM is not directly accessible from memory space, it needs different instruction than access into the RAM. If you are using it like this, you'll get RAM content on passed address, not the FLASH one. You have to use special functions for this. For example memcpy_P(ram_buff,flash_ptr); makes a copy from flash into the ram. Or you can read one byte by pgm_read_byte(flash_ptr + offset)
BTW: If you are using Data_6[0] and it's working, it's just because compiler sees it as a constant and constant can be replaced by its value compile time.
I Guess you just forgot to flush()
try to do Serial.flushI() after Serial.println(buff1[x],HEX);
you can also check flush documentation
I know what pointers are but when it comes to strings/arrays I get really confused. If someone has an answer or a website that explains it that would be great. For example:
char * strncopy (char*dest, char * source, size_t);
Why the pointer? what is it pointing to? Does it a pointer usually store an address?
It is sayed in my textbook that each string building function is of type pointer char*.
Also I was trying to see if I could write a program that would clear things up, but it didn't work. Can someone tell me how to fix it, or what I'm doing wrong.
#include <stdio.h>
#include <string.h>
char * getname ()
{
char name [10];
scanf ("%s", name);
return (name);
}
int main (void)
{
char name[10];
printf ("Enter your name\n");
name[] = getname();
printf ("Hi %s", name);
return (0);
}
Inside of your getname function, when you return a pointer to the name array because it's allocated on the stack it gets destroyed leaving you with an invalid pointer. Dereferencing such a pointer causes many, many problems.
You should allocate the name array inside of getname on the heap, with malloc/calloc so that when you return the pointer the data won't be destroyed.
With regards to functions like strncpy, they tend to return a pointer to the resulting string; e.g.: strncpy returns a pointer to the destination.
Pointer itself represents an address, e.g. if you have a pointer typed char *pstr, you can always check the underlying address with printf("address of my pointer %p\n", pstr);
In C programming language, a string is an array of char. If you have a good knowledge of array and its memory layout, it's not too hard for you to understand c-styled string. Generally speaking, an array in C is a continuous chunk of memory with name of array represent address of the first element in the array. So is string who is a chunk of memory with name of the char array address of the first character. In addition, c-styled string terminates with character \0, so if you want to manage memory for string yourself, remember one extra byte for the tailing \0.
As to your second problem, your name in function getname is a local variable whose life time ends when function returns. However, you still want to access name outside the function which is inappropriate. You can solve this be dynamically allocated memory like in dasblinkenlight's and others' post.
Good luck.