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.
Related
I'm working through a course, and am being tasked to look through and tweak some C code. I have never written C a day in my life, however I was able to pick up on some of the functions and complete the exercise :)
During the exercise, I was allocating memory space in a buffer and filling that space with arbitrary characters. This was part of a buffer overflow assignment.
I learned two functions:
malloc(size_t) - allocates memory with a size_t
memset(ptr, bytes, space) - sets shellcode into the memory
I'll use this code block as an example:
char *nop = malloc(10);
memset(nop, 0x00, 10);
memset(nop, 0x90, 10);
My question is in regards to the code above, where i am reserving space in memory and filling it with nops. Why is it necessary, if at all, that I fill the space with null bytes first before overwriting with my desired characters.
Would the following work the same, or do i need to fill with null bytes first:
char *nop = malloc(10);
memset(nop, 0x90, 10);
The second call to memset will completely overwrite what the first memset does, so the first one is redundant.
Had you first set all of the bytes to 0, then set a subset of them to 0x90, then it might make sense. But you're writing to all of the same bytes, so no need for the first one.
You don't have to call the first memset (with 0x00 as the value) first. In fact, I'd expect a decent compiler to completely optimize the first call out if it saw that the very next line was going to fill the exact same chunk of memory with a different byte.
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);
}
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.
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'm a complete novice in everything except maybe breathing, so sorry if I'm not being clear, but here goes:
I have a function in C which writes bytes to a circuit via an I2C bus, and in the header file it looks like this:
BOOL WINAPI JidaI2CWrite(HJIDA hJida, DWORD dwType, BYTE bAddr, LPBYTE pBytes, DWORD dwLen);
hJida: Board handle.
dwType: Zero-based number of the I2C
bus.
bAddr: Address of the device on the
I2C bus, the full 8 bits as it is
written to the bus.
pBytes: Pointer to location that
contains the bytes.
dwLen: Number of bytes to write.
If I wanted to write just one byte to a circuit with the address 0x98, I would do something like this:
unsigned char writing[1];
writing[0]=0x10;
unsigned char *pointer;
pointer = &writing[0];
JidaI2CWrite(hJida,0,0x98,pointer,1);
which seems to work, but if I wanted to write two bytes, say 0x10FF, it doesn't. So how do I make a pointer that points to two bytes instead of just one?
Thanks
You want something like this:
unsigned char writing[2];
writing[0] = 0x01;
writing[1] = 0x02;
JidaI2CWrite(hJida, 0, 0x98, writing, 2);
Notice that an array in C can be usually be used just like a pointer. The variable writing can be thought of as just a pointer to a chunk of memory that in this case has a size of 2 bytes. Creating another pointer to point to that location is redundant (in this case).
Note you could make it point to any number of bytes:
unsigned char writing[12];
//fill the array with data
JidaI2CWrite(hJida, 0, 0x98, writing, 12);
Try this...
//A buffer containing the bytes to be written
unsigned char writeBuffer[] = {0x10, 0xFF};
//writeBuffer itself points to the start of the write buffer
//you dont need an extra pointer variable
//Indicate the size of the buffer in the call to the function
//pointers do not carry array size information with them (in C/C++)
JidaI2CWrite(hJida,0,0x98,writeBuffer,2);
or better yet
unsigned char writeBuffer[] = {0x10, 0xFF};
JidaI2CWrite(hJida,0,0x98,writeBuffer
,sizeof(writeBuffer)/sizeof(unsigned char));
Note: sizeof(writeBuffer)/sizeof(writeBuffer[0]) automatically calculates the size of the array in bytes for you
It appears as though the dwLen parameter is the number of bytes to write. So:
unsigned char writing[2];
writing[0] = 0x10;
writing[1] = 0xff;
JidaI2CWrite(hJida, 0, 0x98, writing, 2);
Note that your use of pointer pointing to writing[1] probably shouldn't work as written, because that sets pointer to point to the byte after the byte you really want to write. I'm suspecting this is a typo, but if not you may wish to review your existing code before proceeding.
writing is already the pointer that you want.
Get rid of pointer.
The final parameter to JidaI2CWrite is the number of bytes you want to to write.
The pointer pBytes points to the start of the block you want to write.
I see 2 choices:
1) write them separately:
writing[0] = 0x10;
writing[1] = 0xFF;
2) check if short on your system is 2Bytes and use a short.
probably as ((short*)writing)[0] = 0x10FF;
Also, you need to declaire writing is char writing[2];
and then, as others have said, write the 2 bytes...