I'm importing a a lib in my ESP32 project, this was originally designed for eclipse and imported into my code, using PlatformIO, putting it under lib:
Strange behaviour, if I activate the line:
errn = decode_dinExiDocument(&stream1, &exiDin1);
Code is compiled and executed but, no output from the function call is made, even the line:
Serial.println("dintest1");
At beginning of the function call to verify the method has been called.
If I remove call to decode_dinExiDocument everything is printed out correctly.
I'm little lost as I don't see any way to debug this. Any ideas?
#include <Arduino.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include "EXITypes.h"
#include "dinEXIDatatypes.h"
#include "dinEXIDatatypesEncoder.h"
#include "dinEXIDatatypesDecoder.h"
#define BUFFER_SIZE 256
uint8_t buffer1[BUFFER_SIZE];
uint8_t buffer2[BUFFER_SIZE];
static int din_test1(){
Serial.println("dintest1");
int errn = 0;
struct dinEXIDocument exiDin1;
struct dinEXIDocument exiDin2;
bitstream_t stream1;
bitstream_t stream2;
size_t pos1 = 0;
size_t pos2 = 0;
stream1.size = BUFFER_SIZE;
stream1.data = buffer1;
stream1.pos = &pos1;
stream2.size = BUFFER_SIZE;
stream2.data = buffer2;
stream2.pos = &pos2;
/* SetupSessionReq */
/* BMW: 80 9A 00 11 D0 20 00 03 C1 FC 30 00 43 F8 00 */
buffer1[0] = 0x80;
buffer1[1] = 0x9A;
buffer1[2] = 0x00;
buffer1[3] = 0x11;
buffer1[4] = 0xD0;
buffer1[5] = 0x20;
buffer1[6] = 0x00;
buffer1[7] = 0x03;
buffer1[8] = 0xC1;
buffer1[9] = 0xFC;
buffer1[10] = 0x30;
buffer1[11] = 0x00;
buffer1[12] = 0x43;
buffer1[13] = 0xF8;
buffer1[14] = 0x00;
//if i make this call method is not called and i get no output
errn = decode_dinExiDocument(&stream1, &exiDin1);
Serial.println(errn);
return errn;
}
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
}
void loop() {
// put your main code here, to run repeatedly:
printf("+++ Start simple DIN test +++\n");
int errn = din_test1();
printf("+++ Terminate simple DIN test with errn = %d +++\n\n", errn);
if(errn != 0) {
printf("\nDIN test error %d!\n", errn);
}
Serial.println("new loop");
delay(2000);
}
Also line that print "new loop" is not called but the delay is respected.
It is kind of impossible to answer to you without knowing what the function decode_dinExiDocument(&stream1, &exiDin1) does.
I see that the function comes from https://github.com/mhei/OpenV2G and that the library is in alpha release at the moment. I also noticed how the developers do not really like to put comments in their code.
First of all, I strongly advise you to have a look at this link: https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/error-handling.html
In particular, there are function calls to get a string out of an error code and redirect it to the serial port.
What is happening is a fatal error that resets your microcontroller. Is it possible that your function generates a memory leak, a stack overflow or that it tries to access a non initialized pointer?
It is also possible that the library internally uses some OS specific functions that try to allocate too much memory or that try to access some OS specific code which cannot be present on the ESP32?
Where did you call the "init" code for your structures? If you look at this header: https://github.com/mhei/OpenV2G/blob/master/src/din/dinEXIDatatypes.h you can easily see that there is a init_dinEXIDocument(struct dinEXIDocument* exiDoc); function to be called to initialize your structs before using them.
As a side note/personal opinion, I would never willingly use a function made of a giant switch statement with 81 uncommented and undocumented cases.
I solved problem.
code was right.
unfortunately memory heap allocation for thread was low so code hangs.
I leave the answer here if someone has similar problem
Related
I am trying to send a packet to a server over 3g and TCP connection. Below is a link to the .cpp and .h file I have found:
https://os.mbed.com/users/Nels885/code/Adafruit_FONA_3G/
More specifically, I am really confused on how TCPSend works under the Adafruit_FONA_3G class. I am trying to implement it but my code seems to get stuck at packet[0] = 0; under function bool Adafruit_FONA_3G::TCPsend(char *packet).
I have tried commenting out packet[0] = 0; and the code runs all the way through. I have also tried initializing char* packet[32]; before packet[0] = 0; and the code runs all the way through. I am assuming the function is not detecting the packet input.
Here is the specific function from the .cpp file:
bool Adafruit_FONA_3G::TCPsend(char *packet)
{
if (strlen(packet) > 0)
{
mySerial.printf("%s", packet);
//mySerial.printf("%s\r\n", packet);
readline();
packet[0] = 0;
return true;
}
else
return false;
}
Here is my main code:
#include "mbed.h"
#include "Adafruit_FONA.h"
#define FONA_RST D4
#define FONA_TX D1
#define FONA_RX D0
#define FONA_RI D7 //not used
char replybuffer[255];
Adafruit_FONA_3G fona(FONA_TX, FONA_RX, FONA_RST, FONA_RI);
Serial pc(USBTX, USBRX);
int main()
{
fona.TCPinitialize();
char Timeout[21];
fona.getTCPtimeout(Timeout);
char * Server = "52.14.99.26";
uint16_t Port = 10001;
fona.TCPconnect(Server,Port);
char *Packet = "Pick Up %";
fona.TCPsend(Packet);
fona.TCPclose();
}
Adafruit_FONA_3G::TCPsend() assumes that you pass it a writable buffer. You're passing a read-only buffer. So, replace
char *Packet = "Pick Up %";
with
char Packet[] = "Pick Up %";
The problem is really that your compiler allows you to initialize writable pointers with read-only values. This is a shortcoming of your compiler.
Using mbed OS and stm32 nucleo board with Adafruit Fona 3g, I am trying to send data to a server via 3g connection. I am using the .cpp file and .h file posted here: https://os.mbed.com/users/Nels885/code/Adafruit_FONA_3G/file/b18cfba4283a/
The code seems to get stuck on getTCPtimeout. I am having trouble figuring out why this is the case.
I have tried commenting out the getTCPtimeout function to see the results and the code runs through completely, but never establishes a connection with the server.
#include "mbed.h"
#include "Adafruit_FONA.h"
#define FONA_RST D4
#define FONA_TX D1
#define FONA_RX D0
#define FONA_RI D7 //not used
char replybuffer[255];
Adafruit_FONA_3G fona(FONA_TX, FONA_RX, FONA_RST, FONA_RI);
Serial pc(USBTX, USBRX);
int main()
{
fona.TCPinitialize();
pc.printf ("initialize \n");
char *Timeout = "10000000";
fona.getTCPtimeout(Timeout);
pc.printf ("timeout \n");
char * Server = "47.218.188.133";
uint16_t Port = 23;
fona.TCPconnect(Server,Port);
pc.printf ("connect \n");
char * Packet = "Pick Up %";
fona.TCPsend(Packet);
pc.printf ("send \n");
fona.TCPclose();
pc.printf ("close \n");
}
Edit: I was running the code and noticed that after fixing the above issue, the code would get stuck TCPSend function, specifically right before
packet[0] = 0;
which is shown down here:
bool Adafruit_FONA_3G::TCPsend(char *packet)
{
if (strlen(packet) > 0) {
mySerial.printf("%s", packet);
//mySerial.printf("%s\r\n", packet);
readline();
packet[0] = 0;
return true;
} else return false;
}
When commenting out the line, the code would run all the way through. I am still in the process of testing to see if the code still functions as intended, but my question is what exactly is the purpose of packet[0] = 0;?
Adafruit_FONA_3G::getTCPtimeout() assumes that you pass it a writable buffer of size > 20. You're passing a read-only buffer of smaller size. So, replace
char *Timeout = "10000000";
with
char Timeout[21];
Using device manager a user can explicitly enable/disable a device, as can be seen in the following image.
For a given device I want to know if it's currently in a user disabled/enabled state.
I have tried the following approaches
CM_Get_DevNode_Status(&status, &problem, data.DevInst, 0); I was hoping that presence of DN_STARTED, or DN_DRIVER_LOADED would tell me that. But these can be zero even when a driver is being loaded/unloaded by the OS, when the device connects/disconnects. For example, a device which is enabled, and for which driver is loaded. DN_STARTED will be 1, but when we disconnect device it is set to zero before the device's entry is removed from device manager.
SetupDiGetDeviceRegistryProperty(..., SPDRP_INSTALL_STATE, ...) I though a state of CM_INSTALL_STATE_INSTALLED should mean that the device is enabled. But the function returns this state even for disabled devices.
Using WMI I was able to get the required information, but I used wmi in PowerShell. I do not want to use wmi, as it is quite difficult to implement in native c++. I used the following query.
Select Name, Availability, ConfigManagerErrorCode, ConfigManagerUserConfig from Win32_PnPEntity where Name = 'NVIDIA Quadro M1000M'
ConfigManagerErrorCode in above query, if set to 22, means that device has been disabled, 21 means that windows is removing the device
I am looking for a non wmi solution.
The information can be obtained from a device's problem code. There are two ways which I could find to get it.
Use SetupDiGetDeviceProperty() to query DEVPKEY_Device_ProblemCode.
Use CM_Get_DevNode_Status() the problem code will be present in the second argument after the call.
A problem code of 22 (CM_PROB_DISABLED) means that the device has been explicitly disabled by a user by either using device manager, or other such utility.
Sample code
#include "stdafx.h"
#include <Windows.h>
#include <SetupAPI.h>
#include <Cfgmgr32.h>
#include <devguid.h>
#include <initguid.h>
#include "devpkey.h"
#include <algorithm>
#include <iostream>
using namespace std;
int main()
{
HDEVINFO hDevInfo = ::SetupDiGetClassDevs(&GUID_DEVCLASS_DISPLAY, NULL, NULL, 0); //only getting for GPUs on the machine
if (INVALID_HANDLE_VALUE != hDevInfo)
{
SP_DEVINFO_DATA data;
data.cbSize = (DWORD)sizeof(data);
for (unsigned int nIndex = 0; ::SetupDiEnumDeviceInfo(hDevInfo, nIndex, &data); nIndex++)
{
ULONG status = 0, problem = 0;
CONFIGRET cr = ::CM_Get_DevNode_Status(&status, &problem, data.DevInst, 0); //after the call 'problem' variable will have the problem code
if (CR_SUCCESS == cr)
{
cout << " problem " << problem <<endl;
if(problem == CM_PROB_DISABLED)
{ /*Do Something*/ }
DEVPROPTYPE propertyType;
const DWORD propertyBufferSize = 100;
BYTE propertyBuffer[propertyBufferSize];
std::fill(begin(propertyBuffer), end(propertyBuffer), BYTE(0));
DWORD requiredSize = 0;
if (SetupDiGetDeviceProperty(hDevInfo, &data, &DEVPKEY_Device_ProblemCode, &propertyType, propertyBuffer, propertyBufferSize, &requiredSize, 0)) //after the call 'propertyBuffer' will have error codes
{
unsigned long deviceProblemCode = *((unsigned long*)propertyBuffer);
cout << " deviceProblemCode " << deviceProblemCode << endl;
if(problem == CM_PROB_DISABLED)
{ /*Do Something*/ }
}
}
}
}
return 0;
}
Sample Output
problem 0
deviceProblemCode 0
problem 22
deviceProblemCode 22
In the question it can be seen that Intel(R) HD Graphics 530 was enabled, and NVIDIA Quadro M1000M was disabled. Hence in the output we got a problem code of 0, and a problem code of 22 (CM_PROB_DISABLED).
This might seem like a basic question, but I can't find a solution anywhere.
I have to get Information out of a kernel mode. Therefore i work with an IOCTL.
My User-Mode-Applications sends this IOCTL using DeviceIoControl with METHOD_OUT_DIRECT because i need to transfer big amounts of data.
This sends a char-Pointer to my Driver.
The Driver gets the IOCTL and can respond to it within the interrupt request.
Code looks like this:
case IOCTL_FILTERIO_REQUEST_DATA:
{
PVOID pInputBuffer;
PVOID pOutputBuffer;
ULONG outputBufferLength;
PCHAR pReturnData = g_pDataPack;
ULONG dwDataSize = 8000;
ULONG dwDataRead = 0, dwDataWritten = 0;
status = STATUS_UNSUCCESSFUL;
pInputBuffer = Irp - > AssociatedIrp.SystemBuffer;
pOutputBuffer = NULL;
if (Irp - > MdlAddress) {
pOutputBuffer = MmGetSystemAddressForMdlSafe(Irp - > MdlAddress, NormalPagePriority);
}
if (pOutputBuffer) {
RtlCopyMemory(pOutputBuffer, pReturnData, dwDataSize);
status = STATUS_SUCCESS; * g_pDataPack = 0;
db_counter = 0;
}
}
break;
But i need to copy information from another part of the kernel-mode.
I tried to create a global PCHAR like this:
Header-File (Declaration) : extern PCHAR g_pDataPack;
Source-File (Definition) : PCHAR g_pDataPack = "IOCTL DEFINITION";
Editing (Other Source-File): *g_pDataPack++ = 'some stuff';
My Problem is, that i have to edit and enlarge the global PCHAR many times before the interrupt copies it to the local PCHAR and sends it back to my USER-Mode-Application.
I tried to reset the global Pointer every 5000 editions, but that did not realy work.
if (db_counter > 5000)
{
*g_pDataPack = 0;
db_counter = 0;
}
The Program crashes after a special amount of time. I guess, because the global pointer allocates to much space?
I tried to create a CHAR Array, but that did not work at all.
Is there another better or easier way to allocate a special size of memory and then edit this one and copy it to the local PCHAR pReturnData when i need it or do i have to learn how to work with DMA for this project?
Declare it this way to have it global to a module:
module.c:
#include <windows.h>
#define GLOBALBUFFERMAX (1024)
CHAR dataPack[GLOBALBUFFERMAX] = "";
PCHAR g_pDataPack = dataPack;
... and the following way to have it global to the program (#include module.h to every module that shall be able to access pglobal_buffer):
module.h:
#include <windows.h>
#define GLOBALBUFFERMAX (1024)
extern PCHAR g_pDataPack;
module.c
#include <windows.h>
#include "module.h"
CHAR dataPack[GLOBALBUFFERMAX] = "";
PCHAR g_pDataPack = dataPack;
I use win8 Consumer preview build 8250 for executing a program, which works OK on win7
The program uses the following macros/functions:
#if defined(_WIN32)
#include <io.h>
#define streamDup(fd1) _dup(fd1)
#define streamDup2(fd1,fd2) _dup2(fd1,fd2)
#endif
static int acquireOutputStream()
{ int fd = streamDup(fileno(stdout));
FILE* f = freopen("tmp","w",stdout);
return fd; }
static void releaseOutputStream(int fd)
{ fflush(stdout);
streamDup2(fd,fileno(stdout));
close(fd);
}
The program performs the following:
for (int i = 0; i < 1000;++i) {
int fd = acquireOutputStream();
printf("redirect %d\n",i);
releaseOutputStream(fd);
printf("test %d\n",i);
}
Every time I run it ,it prints to file tmp random number of correct "redirect j" printings :
After it ,the file is empty for the remaining executions.(f pointer is never NULL in the acquireOutputStream)"test j" is always printed correctly.
What could be a problem? Is it a known issue on win 8?
There is one small issue i see with your code.
static void releaseOutputStream(int fd)
{ fflush(stdout);
streamDup2(fd,fileno(stdout));
close(fd);
}
In this function you do not close stdout prior to the dup2 call (fclose(stdout)).
Please add more detail to the question on exactly what you are seeing when running this code. It would help in diagnosing the issue.