strcpy() and/or strcat() hangs Arduino Uno - arduino

I have an Arduino Uno V3. The sketch I'm working on has a couple of global vars in which a file within a directory is stored which I want to playback on the Adafruit Music Maker shield. All is fine, as long as I just want to play the file which is referenced in the vars on instantiation, but when I call my function where I need to modify these char arrays, my program or the Arduino hangs or crashes.
These are my variables:
// mp3 player variables
boolean plrStartPlaying = false; // Is set to true in case an nfc tag is present with information on tracks to play
char plrCurrentFile[13] = "track001.mp3"; // which track is the player playing?
char plrCurrentFolder[9] = "system00"; // from which directory is the player playing?
char filename[23] = "/system00/track001.mp3"; // path and filename of the track to play
byte firstTrackToPlay = 1; // the track number as received from the tag
char curTrackCharNumber[4] = "001";
And this is my function I call to modify them:
// stores the file to play in the global var filename - it is created from the gloal vars plrCurrentFolder and plrCurrentFile
boolean createFileNameToPlay(byte trackNo) {
// fill global var curTrackCharNumber with provided trackNo - we need it next to create the global var plrCurrentFile
sprintf(curTrackCharNumber, "%03d", trackNo);
// create the name of the track to play from the curTrack
strcpy(plrCurrentFile[0], '\0');
strcat(plrCurrentFile, "track");
strcat(plrCurrentFile, curTrackCharNumber);
//strcat(plrCurrentFile, sprintf(plrCurrentFile, "%03d", trackNo));
strcat(plrCurrentFile, ".mp3");
// create the filename of the track to play, including path, so we can feed it to the music player
strcpy(filename[0], '\0');
strcat(filename, "/");
strcat(filename, plrCurrentFolder);
strcat(filename, "/");
strcat(filename, plrCurrentFile);
if (SD.exists(filename)) {
return (true);
} else {
return (false);
}
}
As said it does not work - I checked by commenting out all strcat() and strcpy() calls in the function and then my program works just fine. But if the code is active, it actually causes my Arduino to hang or the program to crash. Whatever the cause, the effect is that my program won't advance once this function is called and after a certain time, the Arduino resets.
Can someone explain to me why this happens?

You try to use strcpy() to copy a character to a character, not a character pointer to a character pointer — and the problem occurs (at least) twice:
strcpy(plrCurrentFile[0], '\0');
…
strcpy(filename[0], '\0');
That should be generating compiler errors; both arguments should be char *, but neither is a char *. Write either:
plrCurrentFile[0] = '\0';
…
filename[0] = '\0';
or:
strcpy(plrCurrentFile, "");
…
strcpy(filename, "");
Why are you not heeding compiler warnings? If you're not getting at least warnings, why not? Find the options necessary to create such warnings and preferably make them into errors. For example, with GCC, consider:
gcc -O3 -g -std=c11 -Wall -Wextra -Werror -Wmissing-prototypes -Wstrict-prototypes …
That's my base set of options; I don't run code that doesn't compile cleanly with those options. I sometimes add more.

Related

Finding pointer with 'find out what writes to this address' strange offset

I'm trying to find a base pointer for UrbanTerror42.
My setup is as followed, I have a server with 2 players.
cheat-engine runs on client a.
I climb a ladder with client b and then scan for incease/decrease.
When I have found the values, I use find out what writes to this address.
But the offset are very high and point to empty memory.
I don't really know how to proceed
For the sake of clarity, I have looked up several other values and they have the same problem
I've already looked at a number of tutorials and forums, but that's always about values where the offsets are between 0 and 100 and not 80614.
I would really appreciate it if someone could tell me why this happened and what I have to do/learn to proceed.
thanks in advance
Urban Terror uses the Quake Engine. Early versions of this engine use the Quake Virtual Machine and the game logic is implemented as bytecode which is compiled into assembly by the Quake Virtual Machine. Custom allocation routines are used to load these modules into memory, relative and hardcoded offsets/addresses are created at runtime to accommodate these relocations and do not use the normal relocation table method of the portable executable file format. This is why you see these seemingly strange numbers that change every time you run the game.
The Quake Virtual Machines are file format .qvm and these qvms in memory are tracked in the QVM table. You must find the QVM table to uncover this mystery. Once you find the 2-3 QVMs and record their addresses, finding the table is easy, as you're simply doing a scan for pointers that point to these addresses and narrowing down your results by finding those which are close in memory to each other.
The QVM is defined like:
struct vmTable_t
{
vm_t vm[3];
};
struct vm_s {
// DO NOT MOVE OR CHANGE THESE WITHOUT CHANGING THE VM_OFFSET_* DEFINES
// USED BY THE ASM CODE
int programStack; // the vm may be recursively entered
intptr_t(*systemCall)(intptr_t *parms);
//------------------------------------
char name[MAX_QPATH];
// for dynamic linked modules
void *dllHandle;
intptr_t entryPoint; //(QDECL *entryPoint)(int callNum, ...);
void(*destroy)(vm_s* self);
// for interpreted modules
qboolean currentlyInterpreting;
qboolean compiled;
byte *codeBase;
int codeLength;
int *instructionPointers;
int instructionCount;
byte *dataBase;
int dataMask;
int stackBottom; // if programStack < stackBottom, error
int numSymbols;
struct vmSymbol_s *symbols;
int callLevel; // counts recursive VM_Call
int breakFunction; // increment breakCount on function entry to this
int breakCount;
BYTE *jumpTableTargets;
int numJumpTableTargets;
};
typedef struct vm_s vm_t;
The value in EAX in your original screenshot should be the same as either the codeBase or dataBase member variable of the QVM structure. The offsets are just relative to these addresses. Similarly to how you deal with ASLR, you must calculate the addresses at runtime.
Here is a truncated version of my code that does exactly this and additionally grabs important structures from memory, as an example:
void OA_t::GetVM()
{
cg = nullptr;
cgs = nullptr;
cgents = nullptr;
bLocalGame = false;
cgame = nullptr;
for (auto &vm : vmTable->vm)
{
if (strstr(vm.name, "qagame")) { bLocalGame = true; continue; }
if (strstr(vm.name, "cgame"))
{
cgame = &vm;
gamestatus = GSTAT_GAME;
//char* gamestring = Cvar_VariableString("fs_game");
switch (cgame->instructionCount)
{
case 136054: //version 88
cgents = (cg_entities*)(cgame->dataBase + 0x1649c);
cg = (cg_t*)(cgame->dataBase + 0xCC49C);
cgs = (cgs_t*)(cgame->dataBase + 0xf2720);
return;
Full source code for reference available at OpenArena Aimbot Source Code, it even includes a video overview of the code.
Full disclosure: that is a link to my website and the only viable resource I know of that covers this topic.

Communication issue printing from Arduino to Qt using QSerialPort

I am having problems communicating FROM the arduino to my Qt application through QSerialPort. I have a listening signal that tells me when there is data ready to be read from the arduino. I expect a value for the number of steps that a stepper motor has undertaken before hitting a limit switch, so only a simple int such as "2005". When the data is available for reading, sometimes I get two separate reads with "200" and "5". Obviously this messes things up when I am parsing the data because it records it as two numbers, both much smaller than the intended number.
How can I fix this without me putting in a Sleep or QTimer to allow for a bit more time for the data to come in from the arduino? Note: my program is not multithreaded.
Example Qt code:
//Get the data from serial, and let MainWindow know it's ready to be collected.
QByteArray direct = arduino->readAll();
data = QString(direct);
emit dataReady();
return 0;
Arduino:
int count = 2005;
Serial.print(count);
You can add line break to synchronize.
Example Qt code:
//Get the data from serial, and let MainWindow know it's ready to be collected.
QByteArray direct = arduino->readLine();
data = QString(direct);
emit dataReady();
return 0;
Arduino:
int count = 2005;
Serial.print(count);
Serial.println();
If you are going to use QSerialPort::readyRead signal, you need to also use the QSerialPort::canReadLine function, see this.
Thank you for your help Arpegius. The println() function was definitely a good choice to use for the newline delimiter. And following that link, I was able to get a listening function that got everything the arduino sent as seperate strings. The extra if statements in the loop handle any cases where the incoming string does not contain the newline character (I am paranoid :D)
My code for anyone that has the same problem in the future.
int control::read()
{
QString characters;
//Get the data from serial, and let MainWindow know it's ready to be collected.
while(arduino->canReadLine())
{
//String for data to go.
bool parsedCorrectly = 0;
//characters = "";
//Loop until we find the newline delimiter.
do
{
//Get the line.
QByteArray direct = arduino->readLine();//Line();
//If we have found a new line character in any line, complete the parse.
if(QString(direct).contains('\n'))
{
if(QString(direct) != "\n")
{
characters += QString(direct);
characters.remove(QRegExp("[\\n\\t\\r]"));
parsedCorrectly = 1;
}
}
//If we don't find the newline straight away, add the string we got to the characters QString and keep going.
else
characters += QString(direct);
}while(!parsedCorrectly);
//Save characters to data and emit signal to collect it.
data = characters;
emit dataReady();
//Reset characters!
characters = "";
}
return 0;
}

Type-punning (GCC) - incrementing a pointer parameter on stack

OK, I understand that the GCC 4.x warning "dereferencing type-punned pointer will break strict-aliasing rules" is no joke and I should clean up my code.
I have code which compiles und runs fine with GCC 3.x, and would be very happy if it would do so with GCC 4.x, too. Assume I want to have the assembled code as short as possible: the function gets passed a pointer and should write some data to there. My original code uses the pointer directly on the stack (without a copy) and increments it there (note that I don't want to pass the incremented value back to the caller). You may think also of passing parameters by register - then any copy would be overhead.
So this was my "ideal" code:
void foo(void *pdataout) {
for (int i=16; i--;)
*(*reinterpret_cast<BYTE**>(&pdataout))++ = 255;
}
I tried some variant (note that the address-operator must be applied to 'pdataout' before any type-cast):
void foo(void *pdataout) {
BYTE *pdo = reinterpret_cast<BYTE*>(*reinterpret_cast<BYTE**>(&pdataout));
for (int i=16; i--;)
*pdo++ = 255;
}
and also this:
void foo(void *pdataout) {
BYTE *pdo = *reinterpret_cast<BYTE**>(&pdataout);
for (int i=16; i--;)
*pdo++ = 255;
}
Nothing pleases GCC 4.x... This last one does - but, it uses a copy of the parameter which I don't like. Is there a way to do this without the copy? I have no idea how to tell it the compiler :-(
void foo(void *pdataout) {
BYTE *pdo = reinterpret_cast<BYTE*>(pdataout);
for (int i=16; i--;)
*pdo++ = 255;
}
As far as I understand now, despite there is no more warning by GCC, using the indirection via an additional variable is not safe!
For me (as union is not usable), the only real solution is to use the -fno-strict-aliasing compiler option. Only with that, GCC is aware that pointers of different type to the same memory address can refer to the same variable.
This article finally helped me to understand strict-aliasing.

Optimizing mask function with ARM SIMD instructions

I was wondering if you could help me use NEON intrinsics to optimize this mask function. I already tried to use auto-vectorization using the O3 gcc compiler flag but the performance of the function was smaller than running it with O2, which turns off the auto-vectorization. For some reason the assembly code produced with O3 is 1,5 longer than the one with O2.
void mask(unsigned int x, unsigned int y, uint32_t *s, uint32_t *m)
{
unsigned int ixy;
ixy = xsize * ysize;
while (ixy--)
*(s++) &= *(m++);
}
Probably I have to use the following commands:
vld1q_u32 // to load 4 integers from s and m
vandq_u32 // to execute logical and between the 4 integers from s and m
vst1q_u32 // to store them back into s
However i don't know how to do it in the most optimal way. For instance should I increase s,m by 4 after loading , anding and storing? I am quite new to NEON so I would really need some help.
I am using gcc 4.8.1 and I am compiling with the following cmd:
arm-linux-gnueabihf-gcc -mthumb -march=armv7-a -mtune=cortex-a9 -mcpu=cortex-a9 -mfloat-abi=hard -mfpu=neon -O3 -fprefetch-loop-arrays name.c -o name
Thanks in advance
I would probably do it like this. I've included 4x loop unrolling. Preloading the cache is always a good idea and can speed things up another 25%. Since there's not much processing going on (it's mostly spending time loading and storing), it's best to load lots of registers, then process them as it gives time for the data to actually load. It assumes the data is an even multiple of 16 elements.
void fmask(unsigned int x, unsigned int y, uint32_t *s, uint32_t *m)
{
unsigned int ixy;
uint32x4_t srcA,srcB,srcC,srcD;
uint32x4_t maskA,maskB,maskC,maskD;
ixy = xsize * ysize;
ixy /= 16; // process 16 at a time
while (ixy--)
{
__builtin_prefetch(&s[64]); // preload the cache
__builtin_prefetch(&m[64]);
srcA = vld1q_u32(&s[0]);
maskA = vld1q_u32(&m[0]);
srcB = vld1q_u32(&s[4]);
maskB = vld1q_u32(&m[4]);
srcC = vld1q_u32(&s[8]);
maskC = vld1q_u32(&m[8]);
srcD = vld1q_u32(&s[12]);
maskD = vld1q_u32(&m[12]);
srcA = vandq_u32(srcA, maskA);
srcB = vandq_u32(srcB, maskB);
srcC = vandq_u32(srcC, maskC);
srcD = vandq_u32(srcD, maskD);
vst1q_u32(&s[0], srcA);
vst1q_u32(&s[4], srcB);
vst1q_u32(&s[8], srcC);
vst1q_u32(&s[12], srcD);
s += 16;
m += 16;
}
}
I would start with the simplest one and take it as a reference for compare with future routines.
A good rule of thumb is to calculate needed things as soon as possible, not exactly when needed.
This means that instructions can take X cycles to execute, but the results are not always immediately ready, so scheduling is important
As an example, a simple scheduling schema for your case would be (pseudocode)
nn=n/4 // Assuming n is a multiple of 4
LOADI_S(0) // Load and immediately after increment pointer
LOADI_M(0) // Load and immediately after increment pointer
for( k=1; k<nn;k++){
AND_SM(k-1) // Inner op
LOADI_S(k) // Load and increment after
LOADI_M(k) // Load and increment after
STORE_S(k-1) // Store and increment after
}
AND_SM(nn-1)
STORE_S(nn-1) // Store. Not needed to increment
Leaving out these instructions from the inner loop we achieve that the ops inside don't depend on the result of the previous op.
This schema can be further extended in order to take profit of the time that otherwise would be lost waiting for the result of the previous op.
Also, as intrinsics still depend on the optimizer, see what does the compiler do under different optimization options. I prefer to use inline assembly, which is not difficult for small routines, and give you more control.

how to recheck file in Arduino SD card

I am trying to create a list of files on my SD card this is easy enough to do once but the moment I run the program more than once the list become either shortened or the program say there is no files at all.
To make this as easy as possible I am using the SD example that comes with the arduino SD library and just putting the setup part ( that would normally run once ) in the loop part.
Heres what I have with that.
#include <SD.h>
File root;
void setup()
{
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
Serial.print("Initializing SD card...");
// On the Ethernet Shield, CS is pin 4. It's set as an output by default.
// Note that even if it's not used as the CS pin, the hardware SS pin
// (10 on most Arduino boards, 53 on the Mega) must be left as an output
// or the SD library functions will not work.
pinMode(10, OUTPUT);
if (!SD.begin(10)) {
Serial.println("initialization failed!");
return;
}
Serial.println("initialization done.");
}
void loop()
{
Serial.println("hit any key then enter to run the list");
while(!Serial.available())
{;}
Serial.read();
root = SD.open("/");
printDirectory(root, 0);
Serial.println("done!");
// nothing happens after setup finishes.
}
void printDirectory(File dir, int numTabs) {
while(true) {
File entry = dir.openNextFile();
if (! entry) {
// no more files
//Serial.println("**nomorefiles**");
break;
}
for (uint8_t i=0; i<numTabs; i++) {
Serial.print('\t');
}
Serial.print(entry.name());
if (entry.isDirectory()) {
Serial.println("/");
printDirectory(entry, numTabs+1);
} else {
// files have sizes, directories do not
Serial.print("\t\t");
Serial.println(entry.size(), DEC);
}
}
}
But then I get this weird output after running it
Initializing SD card...initialization done.
hit any key then enter to run the list
HFBVYRG.TXT 7
THBVFG.TXT 7
WAZXDSQ.TXT 7
QAZXSW.TXT 21
WSXZAQ.TXT 7
1478523.TXT 7
QWSDFRE.TXT 7
ZXCVBNM.TXT 7
MKOLIJY.TXT 7
done!
hit any key then enter to run the list
HFBVYRG.TXT 7
THBVFG.TXT 7
WAZXDSQ.TXT 7
QAZXSW.TXT 21
WSXZAQ.TXT 7
1478523.TXT 7
QWSDFRE.TXT 7
ZXCVBNM.TXT 7
MKOLIJY.TXT 7
done!
hit any key then enter to run the list
HFBVYRG.TXT 7
THBVFG.TXT 7
WAZXDSQ.TXT 7
QAZXSW.TXT 21
done!
hit any key then enter to run the list
done!
hit any key then enter to run the list
done!
hit any key then enter to run the list
done!
hit any key then enter to run the list
////////////////////////////////////////////////////////////////////////////////////
as you can see it gets shorter and shorter then just stops altogether.
Does anyone have any ideas why ?
I have tried playing around with pointers and closing and reopening the file but I have come up with nothing.
Any ideas would be greatly appreciated.
No good can come from mismatched open()'s and close()'s. You open the root directory every pass through the loop:
root = SD.open("/");
but never
root.close();
First, fix this error and also check that when you open the root that you succeed before trying to print a listing:
root = SD.open("/");
if(root) {
printDirectory(root, 0);
Serial.println("done!");
root.close();
}
else {
Serial.println("failed to open directory");
}
Second, close the files that are opened in the directory walk
void printDirectory(File dir, int numTabs) {
while(true) {
File entry = dir.openNextFile();
...
entry.close();
}
return;
}
Lastly, consider not blocking in the loop(). Other things can happen outside your loop() and they will be blocked indefinitely depending on how long you wait to hit a key. A more typical code pattern is to spin wildly through the loop() as opposed to blocking waiting for user input. For example:
boolean bNeedPrompt = true;
void loop() {
// Show the prompt once, then mark as displayed so that text does not
// continuously scroll on the screen
if(bNeedPrompt) {
Serial.println("hit any key then enter to run the list");
bNeedPrompt = false;
}
if(Serial.available()) {
Serial.read();
// do action
// set flag so that prompt will display again
bNeedPrompt = true;
}
return;
}
jdr5ca's answer addresses a lot of the problems with your setup - by not closing files you are going to be leaking resources which won't end well. It is particularly important on such a low memory setup as the Arduino, which has only 2k RAM for the original chips, so worth bearing in mind throughout your code.
Short answer for your remaining question: it won't be entirely predictable, but low memory is likely the cause of your problem. Read on for more details.
I've had some similar experiences with the SD library recently, though not with such an obvious cause. I found that if the free memory on my system got below about 500 bytes (a quarter of the total RAM) then the SD library starts to behave very oddly when trying to list directories.
I saw similar things to you, for example:
list entries under root directory and find two sub-directories
list entries in one of those sub-directories, worked fine
list entries under root directory and now I find only one sub-directory! The one I had listed the contents of has vanished!
I could still list the contents of the sub-directory fine, ie. it is still there!
resetting the Arduino and starting again gave the same results, again showing that the files were still present on SD card
I think all of this comes down to SD library being both quite memory hungry (#include SD.h uses up 500 bytes off the bat!), and not handling low memory errors particularly obviously.
So if things are acting strangely then:
check your memory usage (see eg. freeRam() from http://playground.arduino.cc/Code/AvailableMemory)
reduce your memory usage where ever possible. In rough order:
remove libraries you don't need
get rid of any hard coded strings that you don't need (eg. in calls to Serial.print())
for hard coded strings you do need make them as short as possible, and store them in flash (eg. Serial.print(F("String in flash"));) rather than RAM
you can't stick format strings (eg. for snprintf) in flash currently, so avoid using those and just build up the output manually (it is more long handed but saves memory)
make sure you are using appropriate variable types everywhere (ie. the smallest sized type that will suit your purposes) - especially important if you have any arrays, for obvious reasons!

Resources