array in C/C++ for AVR keeps appending - c++

In C, I have an array waiting to receive bytes from a sensor, save in a buffer, and then print out like this:
unsigned char responseFrame[300];
int main(void) {
UART_init();
while(1) {
receive(responseFrame);
myLog(responseFrame, sizeof(responseFrame));
}
}
I populate the array by doing the following:
void receive(unsigned char *rcv_buff) {
uint8_t recv_data;
for (int i=0; i<300; i++){
USART1_Flush();
rcv_buff[i] = USART1_RX();
}
}
Then I print out what's in the buffer using the following:
// Logs this output to the serial port; used for debugging
void myLog(unsigned char *msg, int size) {
for (int i=0; i<size; i++) {
USART0_TX(msg[i]);
}
}
This prints out the array, but when another iteration of bytes is received, everything is appended so let's say I receive {0xFF, 0xFF} first my output for the first iteration is:
0xFF 0xFF, 0x00, 0x00 ... 0x00
But upon the next iteration let's say {0x0A, 0x0A} is received instead, in the output I see this:
0xFF, 0xFF, 0x0A, 0x0A, 0x00, 0x00 ... 0x00
NOTE: The ellipses is just saying there's more 0x00s which are printed out until we basically reach the size of the array.
Why is this appending and not overwriting from the start of the array?
Here's my USART0_TX and USART1_RX functions:
void USART0_TX(uint8_t myData) {
// Wait if a byte is being transmitted
while( !(UCSR0A & (1<<UDRE0)) );
// Transmit data
UDR0 = myData;
};
uint8_t USART1_RX(void) {
// Wait until recv buffer is full
while( !(UCSR1A & (1<<RXC1)) );
// Return recvd data
return UDR1;
};
Here's the code I'm using to flush my USART1 RX:
//USART1 flush, clears USART1 buffer
void USART1_Flush( void )
{
unsigned char dummy;
while ( UCSR1A & (1<<RXC1) ) dummy = UDR1;
}

I believe your function called "Flush" is really a "Poll" function, looking for a character to appear (this would be normal usage, wait for the char to appear). The logic where you use RXC1 appears inverted. Try looking at this quite professional looking AVR driver (that has a poll option just as you are doing):
usart.c
Another nicely commented polled driver (and small with lots of comments): avr uart driver

Related

Comparing UART register UDR0 with an unsigned char array

I am receiving serial communication through the USB port to my Arduino (ATmega2560) by using the RX0 pin. In the receive function I want to compare the register that receives information UDR0 with unsigned char pckaffe[4]. The data that is being sent through the USB port onto the Arduino comes from a pc and if everything works correctly, it should be sending unsigned char arrays, which is why I am comparing UDR0 to unsigned char pckaffe.
However at the if statement, the compiler is saying Error ISO C++ forbids comparison between pointer and integer [-fpermissive]
Why is that?
unsigned char pckaffe[4] = { 0x0C, 0x0A, 0x0F, 0x0E };
void USART_Receive(){
while(!(UCSR0A & (1<<RXC0)) );
if(UDR0 == pckaffe){
PORTB ^= (1 << PB1);
}
}
Why is that?
unsigned char pckaffe[4] = { 0x0C, 0x0A, 0x0F, 0x0E };
pckaffe is a unsigned char pointer, which you are trying to compare to an integer here
if(UDR0 == pckaffe)
pckaffe is a pointer to an array of chars, so the if statement is comparing the value of UDR0 (an int) to the address of pckaffe, which are incompatible types.
I want to compare the register that receives information UDR0 with unsigned char pckaffe[4]
URD0 contains one byte of data. pckaffe[4] - four of them. how you want to compare them?
Of course if(UDR0 == pckaffe) has no sense, pckaffe without index is implicitly converted to a pointer to the array. That gives you compilation error.
Probably you want something like that:
unsigned char pckaffe[4] = { 0x0C, 0x0A, 0x0F, 0x0E };
unsigned int pckaffe_pos = 0;
void USART_Receive(){
while(!(UCSR0A & (1<<RXC0)) ); // Wait for next received byte
uint8_t data = UDR0; // Get received byte
if (data == pckaffe[pckaffe_pos]) { // Compare the byte with next position in the array
pckaffe_pos++; // if matches, increase position
if (pckaffe_pos >= 4) { // If all bytes matched
pckaffe_pos = 0; // reset the pointer
PORTB ^= (1 << PB1); // do something
}
} else if (data == pckaffe[0]) { // next byte does not match, but matches the first
pckaffe_pos = 1; // next byte assumed to be the second in the sequence
} else { // does not match anything
pckaffe_pos = 0; // wait for the first byte in the sequence
}
}

Managing buffers of binary data in C++

I'm trying to create a simple binary format to transmit over a BlueToothLE module on Arduino. I'm trying to describe properties of a list of objects. And for starters I'm trying to transmit just a single property.
The format I'm attempting to encode and pass around is as follows.
namePropertyID, nameLength, nameString...
So given a name of "Bob"
0x01 0x03 0x42 0x6F 0x62
nameID 3 chars "B" "o" "b"
But when I pass the buffer around, it seems to mutate.
before I pass it, it reads:
0x01 0x03 0x42 0x6F 0x62
But after I pass it, it reads:
0x00 0x3C 0x18 0x04 0x00
Program.h
typedef enum {
InfoTypeName = 0x01
} InfoType;
class Program {
public:
char *name;
uint8_t * data();
uint8_t dataLen();
};
Program.cpp
#include "Program.h"
uint8_t* Program::data() {
uint8_t nameLength = strlen(name);
uint8_t buff[dataLen()];
buff[0] = InfoTypeName;
buff[1] = nameLength;
for (uint8_t i = 0; i < nameLength; i++) {
buff[i+2] = (uint8_t)name[i];
}
// First check of data, things look ok.
for (uint8_t i = 0; i < nameLength+2; i++) {
Serial.print(F(" 0x")); Serial.print(buff[i], HEX);
}
Serial.println();
return buff;
}
uint8_t Program::dataLen() {
return strlen(name) + 2;
}
Elsewhere I pass this to the Bluetooth library:
BTLEserial.write(program.data(), program.dataLen());
Which is implemented like so, and is printing out seemingly incorrect data:
size_t Adafruit_BLE_UART::write(uint8_t * buffer, uint8_t len)
{
Serial.print(F("\tWriting out to BTLE:"));
for (uint8_t i=0; i<len; i++) {
Serial.print(F(" 0x")); Serial.print(buffer[i], HEX);
}
Serial.println();
// actually sends the data over bluetooth here...
}
So a few questions:
Why the data mutating?
Is this a good approach for generating buffers?
Is having two separate methods, one for length and one for data a good pattern?
The problem is that in Program::data(), buff is a local variable. You are returning a pointer to its first element, which is a dangling pointer at the call side. You need to ensure the buffer you export is something that stays alive for long enough. There are different ways of doing this, but I am not entirely familiar with the limitations arduino places on what parts of the C and C++ standard libraries you can use.
The simplest approach could be to reserve a buffer in main, and pass that around to the code that populates it and consumes it. Alternatively, you could give your Program class a buffer data member. The main problem is going to be ensuring that the buffer is large enough for different messages.
I would first try something like this:
void create_msg_(const char* name, uint8_t buff, size_t size)
{
// populate buff with the message
}
void send_msg(const char* name)
{
size_t size = strlen(name) + 2;
uint8_t buff[size]; // VLA extension, not std C++
create_msg_(name, buff, size);
BTLEserial.write(buff, size);
}

Unclear pointer defect in program

Im trying to build modified example of usage of DES CBC EDE on openssl. Im using gcc version 4.4.6 (Buildroot 2012.02) compiling for arm (not my choise of compiler) on ubuntu 10.04. Here is a problem: when pointer declaration is uncommented - everything is normal. Test message deciphers. But when pointer declaration gets commented - test message shows only 2 first letters after deciphering. I just can not understand what could do a declaration of an unused pointer. Here is code:
#include <openssl/des.h>
#include <cstring>
#define BUFSIZE 512
using namespace std;
int main(int argc, char *argv[]) {
unsigned char in[BUFSIZE] = {};
unsigned char out[BUFSIZE] = {};
unsigned char back[BUFSIZE] = {};
unsigned char *strangePointer = &out[0]; // what is wrong with it?
int len;
DES_cblock key1, key2, key3;
DES_cblock ivsetup = {0xE1, 0xE2, 0xE3, 0xD4, 0xD5, 0xC6, 0xC7, 0xA8};
DES_cblock ivecLocal;
DES_key_schedule ks1, ks2, ks3;
const char* key = "0A0A0B0B0C0C0A0A0B0B0C0C";
memcpy(&key1,key,8);
memcpy(&key2,key + 8,8);
memcpy(&key2,key + 16,8);
DES_set_odd_parity(&key1);
DES_set_odd_parity(&key2);
DES_set_odd_parity(&key3);
DES_set_key((C_Block *)key1, &ks1);
DES_set_key((C_Block *)key2, &ks2);
DES_set_key((C_Block *)key3, &ks3);
const char* message = "Now is the time for all men to stand up and be counted";
/* 64 bytes of plaintext */
len = strlen(message);
memcpy(in,message,len);
printf("Plaintext: [%s]\n", in);
memcpy(ivecLocal, ivsetup, sizeof(ivsetup));
DES_ede3_cbc_encrypt(in, out, len, &ks1, &ks2, &ks3, &ivecLocal, DES_ENCRYPT);
int lenout = 0;
while(out[lenout] != '\0') ++lenout;
memcpy(ivecLocal, ivsetup, sizeof(ivsetup));
DES_ede3_cbc_encrypt(out, back, lenout, &ks1, &ks2, &ks3, &ivecLocal, DES_DECRYPT);
printf("Decrypted Text: [%s]\n", back);
return 0;
}
You have several things incorrect in your code. I'll start with the simple answer first:
Your third key isn't even populated with key data. It is random data on the local activation stack.
memcpy(&key1,key,8);
memcpy(&key2,key + 8,8);
memcpy(&key2,key + 16,8); // <<=== NOTE still key2
Oh, copy-paste, ye are a cruel and heartless wench. Anyway, by removing the variable you're commenting out, this key is moving further up (or down, depending on your implementation) the stack in memory, and the result is a different value . But the bottom line, you're using indeterminate data for your third key.
But that isn't the entire problem. That change in key exposes another issue, you're output length calculation, which is also flat-wrong. This:
int lenout = 0;
while(out[lenout] != '\0') ++lenout;
assumes the length of the output cipher can be found by searching for a 0-byte. The DES algorithm can easily emit such a byte anywhere in an encryption block. This is plain wrong. The size of the output of a DES_ede3_cbc_encrypt encryption operation is always a multiple of the block size, which for DES is 8 bytes (not coincidentally the size of a DES_cblock), The correct calculation of your output buffer size is:
int lenout = ((len + sizeof(DES_cblock) - 1)/sizeof(DES_cblock))*sizeof(DES_cblock);
which may seem like a helluva lot, but in the end all this does is round up to the nearest multiple of the block length. Further, you don't even need the input buffer. The API will do the calculation for you if you simply pass your input data message and its true length. But I leave that for you to finish (hint: just remove input and pass message).
the result is:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <openssl/des.h>
#define BUFSIZE 512
int main(int argc, char *argv[])
{
unsigned char in[BUFSIZE] = {};
unsigned char out[BUFSIZE] = {};
unsigned char back[BUFSIZE] = {};
int len;
DES_cblock key1, key2, key3;
DES_cblock ivsetup = {0xE1, 0xE2, 0xE3, 0xD4, 0xD5, 0xC6, 0xC7, 0xA8};
DES_cblock ivecLocal;
DES_key_schedule ks1, ks2, ks3;
const char* key = "0A0A0B0B0C0C0A0A0B0B0C0C";
memcpy(&key1,key,8);
memcpy(&key2,key + 8,8);
memcpy(&key3,key + 16,8);
DES_set_odd_parity(&key1);
DES_set_odd_parity(&key2);
DES_set_odd_parity(&key3);
DES_set_key(&key1, &ks1);
DES_set_key(&key2, &ks2);
DES_set_key(&key3, &ks3);
const char* message = "Now is the time for all men to stand up and be counted";
len = strlen(message);
memcpy(in,message,len);
printf("Plaintext: [%s]\n", in);
memcpy(ivecLocal, ivsetup, sizeof(ivsetup));
DES_ede3_cbc_encrypt(in, out, len, &ks1, &ks2, &ks3, &ivecLocal, DES_ENCRYPT);
int lenout = ((len + sizeof(DES_cblock) - 1)/sizeof(DES_cblock))*sizeof(DES_cblock);
memcpy(ivecLocal, ivsetup, sizeof(ivsetup));
DES_ede3_cbc_encrypt(out, back, lenout, &ks1, &ks2, &ks3, &ivecLocal, DES_DECRYPT);
printf("Decrypted Text: [%s]\n", back);
return 0;
}
Output
Plaintext: [Now is the time for all men to stand up and be counted]
Decrypted Text: [Now is the time for all men to stand up and be counted]
You are most probably experiencing a buffer overflow. The declaration of len comes after back on the stack. If back overflows, then len will be overwritten. Adding another variable (strangePointer) in between adds a gap on the stack that stops len getting overwritten.
Probably increasing BUFSIZE should solve your issue.

memcpy - int variable to BYTE

I am trying to create a data packet, using memcpy. I expect to see the output in pOutBuffer, whose first four bytes will have 999, followed by 111 followed by 12; But currently i am getting some garbage.
The problem is that instead of copying the value, it copies the address, I think. How can i copy these values in to a contiguous memory so that i can write it to disk and can retrieve the data at the receiving end with my defined format?
Thanks.
#include "stdafx.h"
#include "windows.h"
typedef struct
{
int Begin;
int End;
int Size;
}PACKET;
void AddBuffer(PACKET* pPacket, BYTE* pOutBuffer)
{
memcpy(pOutBuffer, &pPacket->Begin, sizeof(int));
memcpy(pOutBuffer+sizeof(int), &pPacket->End, sizeof(int));
memcpy(pOutBuffer+sizeof(int)+sizeof(int), &pPacket->Size, sizeof(int));
}
int _tmain(int argc, _TCHAR* argv[])
{
PACKET* pPacket = new PACKET;
pPacket->Begin = 999;
pPacket->End = 111;
pPacket->Size = 12;
BYTE* pOutBuffer = new BYTE [pPacket->Size];
AddBuffer(pPacket, pOutBuffer);
//Write pOutBuffer on to the disk
//WriteFile(vhFileToWrite,(BYTE*)pOutBuffer,pPacket.Size,&vRetFileSize,NULL);
//Delete pOutBuffer
return 0;
}
Source sample has been updated. It now builds ok
Your code works correctly. On a little-endian machine with sizeof(int)==4, the number 999 will be stored as the four bytes 0xe7, 0x03, 0x00, 0x00.
You said you saw the character 'ç': That is because you are trying to view the array as a string, and ç has the character code 0xe7, which is indeed the first byte written. If you view it as an array (either using Visual Studio's memory view, or by typing pOutBuffer,12 in the watch window), you will see the correct byte values.

Read and copy file with EOF indicator in the middle

I used the code below to copy from one binary file to another, but the first file contains some EOF indicators (0xFF) as part of it, so the copy function actually copies the file until its first EOF indicator.
For example: if my file is {0x01, 0x02, 0x03, 0xFF, 0x01, 0x02, 0xFF, 0xFF} then only {0x01, 0x02, 0x03} will be copied to the new file. Any idea how to fix it (or maybe I'm missing something there...)
Code:
int Util_Copy_File(char* source, char* dest)
{
FILE *fs,*ft;
char ch;
char infile[100];
sprintf(infile, "%s", dest);
fs = fopen(infile,"r");
if(fs==NULL)
{
return -1;
}
ft = fopen(dest,"w");
if(ft==NULL)
{
fclose(fs);
return STATUS_FAIL;
}
while(1)
{
ch = getc(fs);
if(ch==EOF)
{
break;
}
else
putc(ch,ft);
}
fclose(fs);
fclose(ft);
return 0;
}
Thanks,
Binyamin
fgetc returns an int, not a char , so you can tell the difference between EOF and a char with the same value as EOF.
Change:
char ch;
to
int ch
And (usually not relevant if you're on *nix)
fs = fopen(infile,"r");
to
fs = fopen(infile,"rb");
0xFF is not EOF. -1 is EOF. The problem is that you're storing the int return value of getc in a char, which collapses 0xFF onto -1 (actually it's implementation-defined behavior but that's what common implementations will do).
The return value of getc is an int whose value is either in the range of unsigned char or EOF (which has value -1). And the correct type for binary data is unsigned char, not char.