Static variable resetting in C after value 0x0c - c

I am trying to read continuous data from remote device and I have static variable declared to receive and send ACK . Payload of 0 and 1 holds the sequence number of the data I am getting from remote device .
The problem I have is with variable fragment_num. After it reaches 0x0c it is resetting back to 0.
Its Free RTOS application . Are there any obvious reasons for a static variable to reset to 0 or is there any problem with my code ? Thanks
#define INTIAL_FRAGMENT 0x00
static uint8_t length;
static uint8_t fragment_num ;
uint8_t image[128];
download ()
{
if(((payload[1] << 8) | (payload[0])) == INTIAL_FRAGMENT)
{
memset(image , 0,128);
memcpy(image , payload,(len));
info_download();
length = len;
fragment_num +=1 ;
}
if(((payload[1] << 8) | (payload[0])) == fragment_num)
{
memcpy((image+length+1) , payload,(len));
length += len;
fragment_num ++;
info_download();
}

The problem is likely buffer overflow.
static uint8_t fragment_num ;
uint8_t image[128];
The compiler may have laid out fragment_num right after image in memory. If length or len is incorrect then memcpy() could write past the end of image and overwrite the value of fragment_num.
memcpy((image+length+1) , payload,(len));
I believe you want (image+length) instead of (image+length+1) here. Adding one skips a byte.
You should probably also verify len before memcpy() to make sure it doesn't overflow, e.g.:
if (len > 128)
return -1;
memcpy(image, payload, len);
if (length + len > 128)
return -1;
memcpy(image + length, payload, len);

Related

About one line in an implementation of MD5

I'm confused by one line of code in an implementation of MD5,
void MD5_Update(MD5_CTX *ctx, const void *data, unsigned long size)
{
MD5_u32plus saved_lo;
unsigned long used, available;
saved_lo = ctx->lo;
if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo)
ctx->hi++;
ctx->hi += size >> 29;
used = saved_lo & 0x3f;
if (used)
{
available = 64 - used;
if (size < available)
{
memcpy(&ctx->buffer[used], data, size);
return;
}
memcpy(&ctx->buffer[used], data, available);
data = (const unsigned char *)data + available;
size -= available;
body(ctx, ctx->buffer, 64);
}
if (size >= 64)
{
data = body(ctx, data, size & ~(unsigned long)0x3f);
size &= 0x3f;
}
memcpy(ctx->buffer, data, size);
}
The question line is if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo), it seems the 'size' counts bytes, but the 'ctx->lo' and 'saved_lo' count bits. Why add them together? There are also some similar codes in Github, and also some projects use these code. So anyone can give some explanation?
The remarks about "bit counters" are likely misleading - ctx->hi and ctx->lo count bytes, just like size does.
You correctly notice that you're just adding size (bytes) to ctx->lo (and then checking for overflow/propagating overflow into ctx->hi). The overflow check is pretty simple - lo is used as a 29-bit integer, and if the result after adding/masking is less than the original value, then overflow occurred.
The checks around used are also evidence for ctx->lo and ctx->hi being byte counters -- body processes data 64 bytes at a time, and the lo counter is ANDed with 0x3F (i.e. 63).

is there any way to write more than 255 bytes using i2c? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 11 months ago.
The community is reviewing whether to reopen this question as of 10 months ago.
Improve this question
When I send 255 data, all data were sent normally.
However, if I send more than 255 bytes of data, it gets corrupted.
It feels like I have only one page, which can hold only 255 bytes of data. So if I send more than 255 bytes of data, data gets mixed up and corrupted.
its fixed now!but 257~end of array of data seems not saving..
123_DATA_SIZE = 32;
123_PACKAGE_SIZE = (123_DATA_SIZE+2)
123_tbl_1_SIZE = sizeof(123_tbl_1)
123_tbl_1 = array of data i.e.{0x20,0x24,..,0x67) //assume there are
1024bytes of data
123_SLAVE_ADDR = 0x24 /////(initial slave address)
unsigned char ProgramCommand(WORD wAddr)
{
BYTE I2c_ProgramCommand[123_PACKAGE_SIZE]; // command + addr + data size
unsigned char Release_ProgramCommand[3] = {00,00,00};
unsigned char Low_ByteCommand[3] = {0x0E,0xFF,0xFF};
unsigned int count, count1;
Adding =0;
Adding1 = 0;
wAddr =0;
{
unsigned char I2c_OnlyOnceProgramCommand[3] = {0xE0,0x00,0x13};
if (i2c_123_iSP_Write(123_SLAVE_ADDR, I2c_OnlyOnceProgramCommand, 3)==0)
return 0;
}
for(count = 0; count < (123_tbl_1_SIZE/123_DATA_SIZE); count++)// size
of data divide by 32
{
I2c_ProgramCommand[0] = 0x90;
I2c_ProgramCommand[1] = wAddr;
changed below
if(count%(7+Adding) ==0)
{
SetAddressHighbyteCommand(0);
Adding +=8; // for additional pages..
// Adding1 +=1;
}
now i changed above part to
if(count%8 ==0) //
{
SetAddressHighbyteCommand((BYTE)(wAddr >> 8));
}
and this worked! sending more than 256 bytes still shown me correct data.
for( count1 = 0; count1<123_DATA_SIZE; count1++) // count1 runs total 32 times.
{
I2c_ProgramCommand[2+count1] = 123_tbl_1[wAddr+count1];
}
if( i2c_123_iSP_Write(123_SLAVE_ADDR, I2c_ProgramCommand,
123_PACKAGE_SIZE) == 0)
return 0;
SetAddressHighbyteCommand(0);
if(123_iSP_Write(123SLAVE_ADDR, Release_ProgramCommand, 3)==0)
return 0;
wAddr += 32;
}
return 1;
}
now the problem is, 257~512 bytes of data seems not saving properly.
read command is:
void ReadCommand(WORD wAddr)
{
unsigned char u8ReadBuffer[256];
unsigned int u16Cmd_LowAddr = 0xD000;
if(wAddr & 0xFF00)
{
SetAddressHighbyteCommand((BYTE)(wAddr >> 8));
}
u16Cmd_LowAddr |= (wAddr & 0x00FF);
i2c_123_iSP_Read(0x25,u16Cmd_LowAddr,u8ReadBuffer,256);
#if 1
{
WORD inx;
printf("ReadData --------- \n");
for(inx = 0; inx < 256; inx++)
{
printf("0x%02x, ", u8ReadBuffer[inx]);
}
}
#endif
}
when i chenge value of unsigned int u16Cmd_LowAddr = 0xD000;
into 0xE000, value shows only 0x00
i also tried 0xf00, but that didnt help neither
A typical I2C EEPROM does not allow writing more than one page at a time. So, if your EEPROM has 256-byte pages and you need to write more than 256 bytes, you need to perform multiple writes.
Here is an excerpt from an ST EEPROM datasheet:
The Page Write mode allows up to 256 byte to be written in a single
Write cycle, provided that they are all located in the same page in
the memory: that is, the most significant memory address bits, b16-b8,
are the same. If more bytes are sent than will fit up to the end of
the page, a “roll-over” occurs, i.e. the bytes exceeding the page end
are written on the same page, from location 0.

Algorithm for writing to EEPROM?

I have a memory which is a column of 4 byte rows. I can only write to it in 16 bytes and read is done in 4 bytes (line by line, that is) using I2C.
I am interested in how to write data into the EEPROM: the data that is being written consists of a few different parts of which two can be of variable length. For example, I can have XYYZ or XYYYYZZZZZZZ where each letter is 4 bytes.
My question is, how I should go about this problem to have a general way of writing the message to the memory using 16 byte write that would accommodate the variable nature of the two parts?
Rather than try to work in 4 or 16-byte units, you could consider using a small (21-byte) static cache for the eeprom. Let's assume you have
void eeprom_read16(uint32_t page, uint8_t *data);
void eeprom_write16(uint32_t page, const uint8_t *data);
where page is the address divided by 16, and always operate on 16 byte chunks. The cache itself and its initialization function (you'd call once at power-on) would be
static uint32_t eeprom_page; /* uint16_t suffices for 2 MiB EEPROM */
static uint8_t eeprom_cache[16];
static uint8_t eeprom_dirty;
static void eeprom_init(void)
{
eeprom_page = 0x80000000U; /* "None", at 32 GiB */
eeprom_dirty = 0;
}
static void eeprom_flush(void)
{
if (eeprom_dirty) {
eeprom_write16(eeprom_page, eeprom_cache);
eeprom_dirty = 0;
}
}
The eeprom_flush() function is only needed if you wish to ensure some data is stored in the EEPROM -- basically, after each complete transaction. You can safely call it at any time.
To access any memory in the EEPROM, you use the accessor functions
static inline uint8_t eeprom_get(const uint32_t address)
{
const uint32_t page = address >> 4;
if (page != eeprom_page) {
if (eeprom_dirty) {
eeprom_write(eeprom_page, eeprom_cache);
eeprom_dirty = 0;
}
eeprom_read(page, eeprom_cache);
eeprom_page = page;
}
return eeprom_cache[address % 0xFU];
}
static inline void eeprom_set(const uint32_t address, const uint8_t value)
{
const uint32_t page = address >> 4;
if (page != eeprom_page) {
if (eeprom_dirty) {
eeprom_write(eeprom_page, eeprom_cache);
eeprom_dirty = 0;
}
eeprom_read(page, eeprom_cache);
eeprom_page = page;
}
eeprom_dirty = 1;
eeprom_cache[address % 0xFU] = value;
}
Feel free to omit the inline if you like; it is just an optimization. The static inline above tell a C99 compiler to inline the functions if possible. It might increase a bit your code size, but it should produce faster code (because the compiler can make better optimizations when such small functions are inlined into the code).
Note that you should not use the above in interrupt handlers, because normal code is not prepared for the eeprom page to change mid-operation.
You can mix read and write operations, but that may lead to unnecessary wear on the EEPROM. You can, of course, split the read and write sides to separate caches, if you do mix reads and writes. That would also allow you to safely do EEPROM reads from an interrupt context (although the delay/latency of the I2C access might wreak havoc elsewhere).
Not tailored specifically to your examples, completely untested and relying on having "read 4 bytes from EEPROM" and "write 16 bytes to EEPROM" encapsulated in suitable functions.
void write_to_eeprom(uint32_t start, size_t len, uint8_t *data) {
uint32_t eeprom_dst = start & 0xfffffff0;
uint8_t buffer[16];
ssize_t data_offset;
for (data_offset = (start - eeprom_dst); data_offset < len; data_offset += 16, eeprom_dst+= 16) {
if (data_offset < 0) || ((len - data_offset) < 16) {
// we need to fill our buffer with EEPROM data
read_from_eeprom(eeprom_dst, buffer); // read 4 bytes, place at ptr
read_from_eeprom(eeprom_dst+4, buffer+4);
read_from_eeprom(eeprom_dst+8, buffer+8);
read_from_eeprom(eeprom_dst+12, buffer+12);
for (int buf_ix=0, ssize_t tmp_offset = data_offset; buf_ix < 16; buf_ix++, offset++) {
if ((offset >= 0) && (buf_ix < 16)) {
// We want to copy actual data
buffer[buf_ix] = data[offset];
}
}
} else {
// We don't need to cater for edge cases and can simply shift
// 16 bytes into our tmp buffer.
for (int ix = 0; ix < 16; ix++) {
buffer[ix] = data[data_offset + ix];
}
}
write_to_eeprom(eeprom_dst, buffer);
}
}

UART write buffer with PDC

I'm having a problem with writing to a USARt using const char buffer and char arrray.
Here is my UART write function:
unsigned int USART_Send( unsigned char *p_pucData,
unsigned int p_unLen)
{
AT91C_BASE_US2->US_TPR = (unsigned int)p_pucData;
AT91C_BASE_US2->US_TCR = p_unLen;
AT91C_BASE_US2->US_PTCR = AT91C_PDC_TXTEN;
while((AT91C_BASE_US2->US_CSR & ((0x1 << 11) | (0x1 << 4) ) ) == 0);
AT91C_BASE_US2->US_PTCR = AT91C_PDC_TXTDIS;
return p_unLen;
}
Below function working with const char* like:
USART_Send("IsitDone?",9); //Working
If I use a array buffer like below it is showing garbage characters, wonder why ?
unsigned char arr[10];
memcpy(arr, "HelloWorld", 10);
USART_Send(arr, sizeof(arr)); //Not working properly displaying Garbage chars
Ricardo Crudo is correct. You run into the following problem:
arr is created on the stack
arr is filled
call USART_Send
fill transmit pointer, counter, enable tx requests
/* peripheral state is TXBUFE = '0' and ENDTX = '0' because: */
/* TXBUFE = '0' when PERIPH_TCR != 0 and */
/* ENDTX = '0' when PERIPH_TCR != 0 */
/* but we just wrote to PERIPH_TCR, so it's != 0 */
/* both conditions are satisfied, b/c the transfer hasn't started yet! */
wait until (TXBUFE = '0' and ENDTX = '0')
/* your code thinks PDC is done here */
/* but in reality, PDC is getting started */
disable tx requests
return from sub-function
overwrite stack (and arr) with unrelated data here
/* PDC might push out last word(s) here due to pipelining/ */
/* instruction cache/side effects/you-name-it */
/* even though its matrix requests were disabled a few cycles ago */
Solutions:
copy to a global buffer or
wait some cycles between enabling tx requests and checking if the PDC is done (possibly a whole baud tick) or
read back PERIPH_TCR and check if it's zero instead of checking the flags
Ideally, you would allocate some dynamic memory for strings and deallocate it after the PDC is done asynchronously to your actual code. You might want to check if you can get some kind of interrupt after the PDC/peripheral is done, then deallocate the memory it read from.
If you don't have dynamic memory allocation, then use the a global ring buffer and abstract your string/char send function to use this buffer instead.

Get the character dominant from a string

Okay.. according to the title i am trying to figure out a way - function that returns the character that dominates in a string. I might be able to figure it out.. but it seems something is wrong with my logic and i failed on this. IF someome can come up with this without problems i will be extremelly glad thank you.
I say "in a string" to make it more simplified. I am actually doing that from a buffered data containing a BMP image. Trying to output the base color (the dominant pixel).
What i have for now is that unfinished function i started:
RGB
bitfox_get_primecolor_direct
(char *FILE_NAME)
{
dword size = bmp_dgets(FILE_NAME, byte);
FILE* fp = fopen(convert(FILE_NAME), "r");
BYTE *PIX_ARRAY = malloc(size-54+1), *PIX_CUR = calloc(sizeof(RGB), sizeof(BYTE));
dword readed, i, l;
RGB color, prime_color;
fseek(fp, 54, SEEK_SET); readed = fread(PIX_ARRAY, 1, size-54, fp);
for(i = 54; i<size-54; i+=3)
{
color = bitfox_pixel_init(PIXEL_ARRAY[i], PIXEL_ARRAY[i+1], PIXEL_ARRAY[i+2);
memmove(PIX_CUR, color, sizeof(RGB));
for(l = 54; l<size-54; l+=3)
{
if (PIX_CUR[2] == PIXEL_ARRAY[l] && PIX_CUR[1] == PIXEL_ARRAY[l+1] &&
PIX_CUR[0] == PIXEL_ARRAY[l+2])
{
}
Note that RGB is a struct containing 3 bytes (R, G and B).
I know thats nothing but.. thats all i have for now.
Is there any way i can finish this?
If you want this done fast throw a stack of RAM at it (if available, of course). You can use a large direct-lookup table with the RGB trio to manufacture a sequence of 24bit indexes into a contiguous array of counters. In partial-pseudo, partial code, something like this:
// create a zero-filled 2^24 array of unsigned counters.
uint32_t *counts = calloc(256*256*256, sizeof(*counts));
uint32_t max_count = 0
// enumerate your buffer of RGB values, three bytes at a time:
unsigned char rgb[3];
while (getNextRGB(src, rgb)) // returns false when no more data.
{
uint32_t idx = (((uint32_t)rgb[0]) << 16) | (((uint32_t)rgb[1]) << 8) | (uint32_t)rgb[2];
if (++counts[idx] > max_count)
max_count = idx;
}
R = (max_count >> 16) & 0xFF;
G = (max_count >> 8) & 0xFF;
B = max_count & 0xFF;
// free when you have no more images to process. for each new
// image you can memset the buffer to zero and reset the max
// for a fresh start.
free(counts);
Thats it. If you can afford to throw a big hulk of memory at this a (it would be 64MB in this case, at 4 bytes per entry at 16.7M entries), then performing this becomes O(N). If you have a succession of images to process you can simply memset() the array back to zeros, clear max_count, and repeat for each additional file. Finally, don't forget to free your memory when finished.
Best of luck.

Resources