Jump to content
yyrkoon

SocketCAN help needed

Recommended Posts

I've used packed unions before for reading from flash and dumping into a structure for use later.

I guess I was too entrenched into higher level languages to even care about the need for "objects" in C. But now that I'm deeply intrenched into C, and Linux for embedded devices. I suppose I am more motivated to truly learn the language. Actually exploring the advanced usage of, etc.

Share this post


Link to post
Share on other sites

Speaking of structures, and unions. I wonder if anyone has comments on what is the best / most efficient way to copy one structure into another ? Googling now, but that does not guarantee I'll find a good, correct answer. I know of a couple ways off the top of my head that I can think of but . . .

Share this post


Link to post
Share on other sites

Actually the whole problem is this:

 

1- copying frames from socketCAN into a buffer - SOLVED

2- copying the buffer from step 1 into a data type that can then easily represent what the data in the buffer means - SOLVED

3- copying the data from the data structure from 2nd step, into yet another pre-formated type. - UNSOLVED

 

So obviously I do not want to use more memory / resources than necessary. But am starting to see no real way around directly assigning members from step 2 directly into members of some data type in step 3. The data type in step 3 I am hoping to to form a JSON object, but am starting to stumble when considering a "generic" type for representing all possibilities. Where the size of the fully constructed buffer will definitely vary. Any ideas ?

 

EDIT:

 

So the only real way that I can think of, which I can do this. Is to write a function, switch / case off of some value( this part I know already ), and create / construct each buffer type by hand. Seems really clunky to me, but until I can get some code on "paper" to look at. I'll probably not be able to see it any other way. Perhaps even using a union{struct} type again to keep many lines of sprintf() / strncpy() from occurring. . . hmmmm

Share this post


Link to post
Share on other sites

grrrr internet been down all day. But anyway, ran into a hiccup where using malloc() to initialize a data type in my shared memory module was somehow causing SIGSEGV. Did not have gdb installed, nor strace, and with internet down. I could not track it down . . .

 

So was reading the book "The Linux programming interface", and was reading about alloca() when I read something to the effect of ...

Using alloca() can be especially useful if we employ longjmp() (Section 6.8) or siglongjmp() (Section 21.2.1) to perform a nonlocal goto from a signal handler. In this case, it is difficult or even impossible to avoid memory leaks if we allocatedmemory in the jumped-over functions using malloc(). By contrast, alloca() avoids this problem completely, since, as the stack is unwound by these calls, the allocated memory is automatically freed.

So . . . I gave alloca() a shot, and *bam* code instantly started working . . . all while reducing my code by around 20 lines. Since I no longer needed a *New, and *Delete function to handle the dynamic memory for a data type that did not last longer than the calling function anyway :/ *slaps forehead*.

Share this post


Link to post
Share on other sites

Anyway, this bothers me. But it does have it's merits I guess. Such as no additional overhead, and simplicity . . . aside from that. No size checking, sprintf() straight into a mmap()'d file pointer, and . . . yeah I don't know.

void WriteToShm(shm_t *shm, statistics_t *stats){
    LockShm(shm);

    switch(stats->length){
        case 0x49:    // AC_OUTPUT_STATUS
            sprintf(shm->mmap_addr,
            "{ \"srcid\": %d, \"rms_voltage\": %.2f, \"current\": %05.2f, \"frequency\": %.2f}\n",
            stats->acdata.srcid, stats->acdata.L3_rms_voltage * .001,
            stats->acdata.L3_current * .01, stats->acdata.L3_frequency * .01);
        break;
        default:
        break;
    }

    UnlockShm(shm);
}

Share this post


Link to post
Share on other sites

More sidetracking, but good news . . .

william@debian-can:~/refactor$ valgrind --leak-check=yes test
==2572== Memcheck, a memory error detector
==2572== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al.
==2572== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info
==2572== Command: test
==2572==
==2572==
==2572== HEAP SUMMARY:
==2572==     in use at exit: 0 bytes in 0 blocks
==2572==   total heap usage: 30 allocs, 30 frees, 1,985 bytes allocated
==2572==
==2572== All heap blocks were freed -- no leaks are possible
==2572==
==2572== For counts of detected and suppressed errors, rerun with: -v
==2572== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 11 from 6)

Was just reading yet another book "21st century C" , and while reading chapter2 "Valgrind" was brought back to my attention. So decided to take a detour and check for memory leak status.

 

Anyway, I'm reading all these books in hopes of filling in the gaps in my C knowledge. Which in places seems to be very extensive. Such as I know my "modules" are all wrong. e.g. all the source in located in header files, which I think is creating a problem for me in relation to static functions, and their scope . . . Nothing critical, but I'd rather that scope was limited to the actual module when the modifier static was used . . .  Looking for a good read on the subject, but have yet to find anything.

 

Share this post


Link to post
Share on other sites

Quick update:

 

Ran into some trouble with the IPC client accessing the shared file too fast. So I had to iron that out. I knew that I would have to "throttle" the IPC client / web server, to keep it form reading the file too fast, and flooding out the web browser client. But was not sure how to do that until I got to that part in the code. Pretty much, it just locks the file, compares the first byte. Then if not what it is looking for, it reads from the file, then writes the comparison character back to the file. The IPC server is oblivious to this point. and it does not really matter. Since neither the IPC server, or client can access the file data at the same time.

 

Another aspect I was a bit worried about but turned out to be moot. Was how much CPU I was going to be using. It was a big surprise to me that canplayer was using up 59% CPU, where as the two halves of my application use only 8% CPU between the two processes. But we'll see how that pans out once the code is compiled and running on the beaglebone black. Big surprise since one cycle through my control loop on the IPC server takes around 239ms. For sure though, once I start tracking multiple PGNs at one time, I *will* be using more CPU. The bonus here though is that I can completely ignore the CPU % used by canplayer. Since all this will be handled by the CAN cape hardware on the BBB. The IPC server uses ~5% CPU, where the client uses ~3%.

 

As reported by atop: "test" is the IPC server, and "run" is the IPC client.

30719 william  william     1   2.36s   0.00s     0K     0K     0K     0K --   - R     0  60% canplayer
 4035 william  william     1   0.19s   0.00s     0K     0K     0K     0K --   - S     0   5% test
 4614 william  william     1   0.10s   0.00s     0K     0K     0K     0K --   - S     0   3% run
    3 root     root        1   0.02s   0.00s     0K     0K     0K     0K --   - S     0   1% ksoftirqd/0
28152 william  william     1   0.01s   0.00s     0K     0K     0K     0K --   - S     0   0% sshd
    6 root     root        1   0.01s   0.00s     0K     0K     0K     0K --   - S     0   0% watchdog/0
 4364 root     root        1   0.00s   0.00s     0K     0K     0K     0K --   - R     0   0% atop

I do have to say, this project sure is taking me a long time to get right. But I feel in the end it will be well worth it. If not for anything else - The challenge. I'm also learning *a lot* . . .

Share this post


Link to post
Share on other sites

Update:

 

Ok, so I let both processes run over night, and they both ran without a single problem. However, I also ran a web browser page pointing to the http + websocket address, and it worked for a while ( probably several hours ), then stopped working. Pretty sure it had to do with my badly formed javascript, using global variables, No um, what are they called ? Enclosures ?

 

Anyway, I was testing some formatting options for the text ( JSON object ) being output to the web browser. Trying to get things ordered, and dynamically created. Which I think I have most of the niggles I had with my browser output ironed out. So Now, I'm going to work on the html / javascript aspect of this project. Until I arrive at something that resembles passable.

 

Once all that is done, I will make a screencast of my Nexus 7 connecting to the http server. So I can create a video to "show off" to everyone - on youtube. Proof of concept sort of thing. Then after that is all done, I will dive back into my C code and start banging out the complex data structures for various PGNs. Then probably move this series of post to the projects sections, and share the data structure code I can prove correct. I'll share more if people are interrested. e.g. my IPC / websocket + http server code. Which honestly is nothing( the http stuff ). I basically just stripped out a bunch of unneeded code from one of the libmongoose examples, made a few adjustments, and added in some IPC shared memory stuff. The main source file for this process( which I dubbed canweb.c ) is exactly 70 lines of code . . .Nothing to see here, move along ;)

 

Much thanks @@oPossum for your help. It is always good to get someone else to take a look at various things, and mention things you ( me in this case ) may have missed. The sequence number problem helped me immensely, not to mention sorting out the CANid to PGN masking.

Share this post


Link to post
Share on other sites

Quick screenie of the demo: https://picasaweb.google.com/106867156582775247949/July252015?authuser=0&authkey=Gv1sRgCMPY_sP7kdPoRA&feat=directlink

 

But a screenshot does not really do it justice. Watching it update each sourceID ~2 times a second in real time is much better ;)

Looking good :thumbsu:

Share this post


Link to post
Share on other sites

Thanks @@bluehash ;)

 

Just a minor update. I've been getting acquainted  with  jQuery again . . . coming from a C project, I'm starting to feel like I'm devolving . . . function chaining, triple equal signs, $ code warts. . . Yeah.  But jQuery is probably smarter than I am with javascript memory management. and I've noticed a difference in html render speed already. e.g. jQuery is faster than stock javascript / DOM calls in many cases. Which is important for how fast this data is changing in my project. I also like the fact that when using the module pattern, I can pass in jQuery, and keep all my stuff in private scope. Nifty . . .

 

So kind of taking it easy, and found a good open source screen casting app that seems to work great on Windows 8. Have been busy most of the day, but have been procrastinating doing a demo vid . . . Not sure why, just am. In the meantime I've been working on the html page, trying to make it look better. Instead of just "blah" raw text with no visual - This sort of thing always bugs me.

Share this post


Link to post
Share on other sites

Update: OK ! I "ported" everything over to the Beaglebone black, and it is using even less CPU for canplayer, and my code. Not sure why, but perhaps the generic nature of an i386 virtual machine, or perhaps just i386 period ? No idea. Anyway I quoted ported, because it was a simple matter of moving files over to, and setting up the beaglebone black - Then it just compiled, and worked :)  . .

 

See for yourself on the CPU usage though:

PRC | sys    0.26s | user   0.02s | #proc     69 | #trun      1 |  #tslpi    71 | #tslpu     0 | #zombie    0 | clones     0 | #exit      0 |
CPU | sys       1% | user      0% | irq       0% | idle     98% |  wait      0% | steal     0% | guest     0% | avgf 1.00GHz | avgscal 100% |
CPL | avg1    0.02 | avg5    0.04 | avg15   0.05 |              |               | csw    24014 | intr    9947 |              | numcpu     1 |
MEM | tot   495.5M | free  292.4M | cache 146.3M | dirty   0.0M |  buff    0.0M | slab   38.5M |              |              |              |
SWP | tot     0.0M | free    0.0M |              |              |               |              |              | vmcom  52.9M | vmlim 247.8M |
NET | transport    | tcpi      81 | tcpo      81 | udpi      15 |  udpo      15 | tcpao      0 | tcppo      0 | tcprs      0 | udpip      0 |
NET | network      | ipi       99 | ipo       97 | ipfrw      0 |  deliv     99 |              |              | icmpi      0 | icmpo      0 |
NET | eth0      0% | pcki     120 | pcko      99 | si    7 Kbps |  so   11 Kbps | erri       0 | erro       0 | drpi       0 | drpo       0 |
NET | vcan0   ---- | pcki    2492 | pcko    2492 | si   14 Kbps |  so   14 Kbps | erri       0 | erro       0 | drpi       0 | drpo       0 |

  PID   RUID       EUID        THR     SYSCPU    USRCPU    VGROW    RGROW     RDDSK    WRDSK   ST   EXC    S   CPUNR    CPU   CMD         1/1
 9533   william    william       1      0.18s     0.01s       0K       0K        0K       0K   --     -    S       0     2%   canplayer
 9634   root       root          1      0.04s     0.00s       0K       0K        0K       0K   --     -    R       0     0%   atop
 9664   william    william       1      0.03s     0.01s       0K       0K        0K       0K   --     -    S       0     0%   test
 9640   william    william       1      0.01s     0.00s       0K       0K        0K       0K   --     -    S       0     0%   sshd

One of the processes( run ) doesn't even show up in atop half the time . . .

 

Share this post


Link to post
Share on other sites

SO if anyone is interested in the workflow to what I've done to get here let me know. I can even provide a candump logfile for those who do not have the can cape to play right away. This would atleast allow you to have a vcanx running for testing code . . .

Share this post


Link to post
Share on other sites

Well I ran into a couple problems, and one good thing - I guess.

 

After ~3 days my processes mysteriously go missing. Not sure why, but I think I can trap signals and figure out why. The reason I think this is that despite the fact that valgrind reports no memory leaks, it appears to me that Linux's OOM killer for some reason is triggering on the two processes. At least I can not think of why else they would "arbitrarily" stop. Granted I've been keeping a close eye on memory usage, and it never goes above 60M total memory use. Odd. Also, there is nothing in /var/log/messege, and dmesg reports nothing. In fact I checked every file in /var/log, and nothing. but rsyslog is probably disabled, since these images are meant to run on flash media.

 

The other problem isn't so much of a problem as it is me trying to refactor my code to something simpler. I've been exploring a few avenues when time permits.

 

The upside, well kind of - Is that a person I met on another forums yesterday had a copy of Xantrexs' PGN's. And I mean every single last one of them. The downside here is that, well it's no longer a mystery to me. The obvious upside is that now I know, or can very easily figure out each and every data value for every PGN- 100% accurate. Another less than obvious upside is that I was able to verify that all the PGN data that we've thus far reversed was pretty darned close. Meaning we had reversed the PGN's fairly accurately except that some of the fields were slightly off - bit wise. Which I already expected.

 

Anyway this PDF is very extensive, and 279 pages long . . . Looks like I'll be spending months figuring out how to track all this in real time, as well as tackle the current problems with my code that I have. Then those that will surely follow. So while still a challenge, most of the fun for me unfortunately is gone :(

 

EDIT:

 

Well also I'm currently using an experimental kernel. 4.2.x, and as it is relatively new, my process disappearing act could be related. However, I'm not sure how I could track that down . . . I will have to look into it. But short of a git bisect, or perhaps strace / ltrace . . . yeah I shudder at the thought.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×