In stm32 firmware I declare non static array:
uint8_t bufCan[8] = {0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31 };
And get it corrupted ( filled with another data) when I call function with this array as argument. While debugging I observe that this array is placed at address 0x20007fc8. RAM size is from 0x20000000 to 0x20008000. So this array is placed in stack and get corrupted.
This is not happens if I declare this array as static. In this case compiler place it array at address 0x20000234.
So what is issue of array corrupts? This should not occur even if I declare array as non static!
his is not happens if I declare this array as static
And get it corrupted ( filled with another data) when I call function with this array as argument.
I assume your code looks something like this
int another_function(int8_t *array){
//Your routine with array
}
int yourfunction(){
int8_t bufCan[8] = {0x37, 0x36, 0x35, 0x34, 0x33, 0x32, 0x31 };
another_function(bufCan);
}
So when you access array in another_function you find it is corrupted. But declaring this array as static solves the problem. Therefore we can assume the prblem is with the stack.
Few things may happen, first is dynamic memory allocation, let me assume that prior to calling another_function or within anoter_function body you have used dynamic memory allocator malloc(). This could lead to corrupted stack.
Another option is that you have wrote something to another array on stack and crossed its boundary which led to corrupted array again.
If you can update your post with code i can provide a more detailed answer to it.
Related
I want to copy an uint8_t array to a uint8_t pointer
uint8_t temp_uint8_array[] = {0x15, 0x25, 0x32, 0x00, 0x52, 0xFD};
uint8_t* Buffer = temp_uint8_array;
And now :
Buffer = {0x15, 0x25, 0x32};
So I understand that my data is cut because of 0x00, is there a solution ?
As I have access to the size of tha datas to be copied I tried to use
memcpy(Buffer, &temp_uint8_array, local_length);
But it does not work
uint8_t temp_uint8_array = is not an array but a syntax error.
So I understand that my data is cut because of 0x00
No it isn't. If you try to interpret the data as a string, then the 0x00 will get treated as a null terminator. But this is not a string.
is there a solution
Don't treat raw data as a string? memcpy will work perfectly fine.
But it does not work
What doesn't work? What is local_length and where did you get it from?
The memcpy isn’t correct :
memcpy(Buffer, &temp_uint8_array, …
As temp_uint8_array is an array then you should not prefix it with & :
memcpy(Buffer, temp_uint8_array,…
Buffer is pointing to temp_iint8_array so the memcpy does nothing but erasing bytes in the same memory location. You IDE might consider that uint8 array may be handled as char string and display contents until 0x00.
Ok so actually it was my variable viewer in my IDE that cuts my variable value so I can only see the value until the 0x00 but in memory the data has been copied.
Maybe it was interpreted as string so it display the value until the null terminator.
To know that I must have check what was going on in my mcu memory with th debugger.
I've got a function which expects a variable and a pointer.
void sendCMD(byte cmd, byte data[]){
...
}
Is it possible to call this function with the data in anyway like so
sendCMD(0xff, { 0x0a, 0x02 });
Since even by googleing I didn't find anything... maybe I haven't looked hard enough, but I'm also not exactly sure what the terms are I should be looking for.
Any help is kindly appreciated!
Note that byte is the same thing as a char!
You can use a compound array literal:
sendCMD(0xff, (byte[]){ 0x0a, 0x02 });
I have a number of arrays all of different sizes that I have stored in flash memory.
I can access single array entries with
byte j = pgm_read_byte(&(array[x]));
What I want to do is to pass the array from the flash memory as an argument to a function. I have tried giving a pointer to the array, as an argument but this gives a compilation error:
void callPGM2(byte arr_size, byte *arr) {
..
..
}
ptr2 = &pgm_read_byte(&(array_1[0]));
callPGM2(5, &ptr2);
Can full arrays be passed from flash memory as function arguments?
There's no way to directly pass a pointer to PROGMEM variables, because of the AVR's Harvard architecture with 2 address spaces that C has no way to straightforwardly express - You need to temporarily copy the memory to RAM using memcpy_P, for example.
And you want to learn about the functions provided in the pgmspace library. It holds equivalents to a number of C functions like strcmp, that allow you to work with a constant argument in program space.
To copy a string from flash memory to RAM
#include<avr/pgmspace.h>
const byte Update_1[5] PROGMEM = {0x01, 0xB2, 0x02, 0xFF, 0xFF};
byte buffer2[5];
setup {
memcpy_P (buffer2, &(Update_1),5);
}
I am struggling to understand why I get random data while trying to read from multidimensional table that is stored in rom.
I have a table of bitmap character which I want to display on OLED screen. Table of characters is too big to fit into ram and rom is natural place for it. When I try to read elements from the table, data is not the one stored in the table.
Here is what I try to do. I have bitmap declared as a multidimensional array at the begging of the C-file where it is used:
rom const char number[15][4][20] = { {
{0x00, 0x00, 0x00, 0x00, 0xc0, 0xe0, 0xf0, 0x70, 0x78, 0x38, 0x38, 0x38, 0x38, 0x78, 0x70, 0xf0, 0xe0, 0xc0, 0x00, 0x00},// row 1 columns 19
{0x00,...
This is where I try to read the data and print it to the screen:
for(i=0; i<4; i++)
{
PutImage(number[digit][i],20,4,offset,i+2);
}
Implementation of PutImage function:
void PutImage(char ptr[], unsigned char sizex, unsigned char sizey, unsigned char startx, unsigned char starty)
{
unsigned char _page, _column;
//startx += OFFSET;
OledWriteCommand(0xb0+starty);
OledWriteCommand(startx&0x0F);
OledWriteCommand(0x10 | ((startx>>4)&0x0F));
for(_column=0; _column<sizex; _column++)
{
OledWriteData(ptr[_column]);
}
}
If I change it so that data fits into ram it works just fine. So the problem has to be either that data is not stored correctly in the first place or the way I used it is incorrect.
The Pic I am using is 18F27J53 and datasheet section 7.1 (Table Reads and Table Writes) talks about some Assembler operations that are used for moving bytes between program memory and ram. As I am using C, i am not sure if that is something I need to be aware of or does the compiler know how to handle that.
Ok related question and its answer got me to (hopefully) right track: Can I make a function that accepts both ram and rom pointers in Microchip C18?
And thanks to Pandrei as well for pointing out that the implementation if PutImage could be the cause.
I got the code working by making duplicate function PutROMImage which accepts "near rom char*"
-type instead of just "char*" which defaults to ram.
So C18 does not allow pointers to point both ram and rom and PutImage -function parameter defaults to ram. So passing a pointer to array which is located in rom causes pointer point to random values.
I had not noticed this deficiency in the code and compiler wasn't smart enough to complain about that.
having the data in ROM (.txt section) or RAM (.data section) has nothing to do with the problem you are facing.
Assuming that the initialization is correct and you initialize all the elements (if you don't, the elements left out will be default initialized to 0), the problem might be in the function's implementation: PutImage.
Since you have problems when the size changes, maybe you have some hard-coded values in there...
I have a function that takes in pointers to different arrays which can look like this:
unsigned char *arr[] = {0x34, 0x10, 0x3f, 0x00, 0x00 }
I want to know how many elements (bytes) are in each array my function is getting. For example, I need a way to find that this array has 5 bytes. I pass this into a function to print the values of the array. Sizeof(arr) doesn't give me the right results.
Unless you're using a convention like "the array is null-terminated" (like C strings nominally are) you can't determine the size of the array at run-time. All you have at that point is a pointer.
This is C. and in C this does not exist. You have to somewhere remember /store the number of elements.
sizeof(arr)/sizeof(unsigned char*)
you can macro-ize this fairly easily as
#define ARRAY_LENGTH(_array_) (sizeof(_array_) / sizeof(_array_[0])
BTW, this will only work if you use it in the same scope as the array. This will not work if you pass the array to a function (and the array degrades into a pointer). If you pass the array to a function, you'll need to pass the number elements, and possibly the size of each element.