Shop OBEX P1 Docs P2 Docs Learn Events
Accidental self-modifying code, not so fun — Parallax Forums

Accidental self-modifying code, not so fun

XlogicXXlogicX Posts: 18
edited 2009-09-17 14:37 in Propeller 1
I originally posted this to the tricks and traps thread. In avoidance of getting off topic of that (useful) thread, here is a branch.
I said...

This is my first post. I got trapped (for 2 days) and finally got out of it, so I figured I would share. I hope this hasn’t been posted about somewhere else (because I could have used it so much sooner)
I was trying to pass information from one cog to another, not a new concept. I was pretty sure I didn’t need semephores (though I experimented with them) since I was only passing one long at a time (using to send status flags back and forth between cogs).
Here’s what I was doing (wrong):
One cog would be reading a variable from main memory (to see if there was any pending tasks in the form of a flag in the variable). I passed the variable using par and indexed appropriately.
Something like:
:start    Mov    variable, par        ‘get address of variable
Rdlong    local_var, variable    ‘put the value of that address in local_var
…..(program)
Jmp    #:start            ‘do it all over again (check flags again)
Local_var    long    0



My other program would toggle the data on that same memory location (just as a test, a test that failed). The code would do some waitcnt stuff, then toggle the data on that memory, then loop. The command I used for writing was in the form of:
Wrlong        cogvar, mem_loc   ‘where the mem_loc is the same as variable in previous cog



This actually worked fine for a while of execution (of which I watched in GEAR). The symptom that this cuased baffled me. I practically watched what every relevant thing was doing in GEAR to try and pinpoint what was going wrong. At around clock tick 25000 or so, the main memory would just clear itself, almost all of it, including the cog0 program itself. In the end, I really couldn’t find out what exactly was causing the issue. But I did do something to erradicate it.
Instead of having my shared value in main memory declared in the VAR section. I declared it in a DAT section. I’m sure someone else could have told me this, but the forums overwhelmed me, it felt like it would have taken longer to search for it then just start hacking it myself.
Anyone know why this happened exactly (or if I may still be doing something wrong and am just lucky for now)?

The moral of the story (so far), declare shared memory between cogs using DAT, not VAR
Phil Pilgrim said...

There's nothing wrong with using VAR variables in the way you describe. It's done all the time. The only catch is that you have to make sure that both cogs are working with the same variable, since VARs are replicated among instances of the same object. But if both cogs are started with a pointer to the VARiable from the same object instance that delares the VARiable, that's not a problem. I suspect there's something else going on in your program that caused the problem you saw and, as you say, you just got lucky when switching to a DAT variable. I would suggest starting a new thread and posting your entire program thre so others can help you debug it.

-Phil
Clock Loop said...
XlogicX said...
XlogicX
The moral of the story (so far), declare shared memory between cogs using DAT, not VAR


Thats how I did it in my projects program.

http://forums.parallax.com/forums/default.aspx?f=21&m=376422&p=1&ord=a

Using DAT for variable space is a topic that DOES NOT get enough attention in the manual or education kit.

My issue absolutely was dumb luck. I even completely understand the WHY of the problem and was able to revert back to VAR space instead of DAT. In fact, you were absolutely correct Phil, rdlong, wrlong, and where they were reading and writing to had nothing at all to do with the problem.
I’m writing audio driver software (4-channel sample based). I’m doing 16-bit audio (128 pieces each sample). To save space, I put two samples per 32-bit word (compressed in a way). One of my cogs takes a 32-bit word from main memory, parses it into two separate 16-bit values, and puts them back into a dedicated area of memory for holding a 32-bit sample. I then use this 32-bit sample for the frqa register (for the pulse width modulation). This sounds like too much work, but when you start collecting several 32-bit samples, it adds up (vs many 16 bit samples that can be converted to a 32-bit space when needed).
Anyway, the problem is that I reserved this DAT space before VAR and PUB (not the generally accepted style, but shouldn’t bother anything with code that isn’t poor like mine was). I obviously had to do some indirect indexing in my assembly;
    Grab sample from memory
    Parse
    Put back into memory
    Add to index



Woops on the forgetting to reset the index! After enough loops, the index would eventually plow right through VAR and PUB, rewriting the main program memory with audio data. Quite the epic fail for such a simple mistake.
I will get there eventually though, I already wrote a 1 channel version of my audio driver, and it actually works beautifully. Not to say that I didn’t get enjoyment and use out of Nick Sabalausky’s driver, I just wanted something I could call my own smile.gif .

Comments

  • photomankcphotomankc Posts: 943
    edited 2009-09-17 13:19
    Whenever I have code that runs for a bit and then all $%#^ breaks loose that's the first thing I look at. Indexes to arrays.
  • XlogicXXlogicX Posts: 18
    edited 2009-09-17 14:37
    I have definitely started learning certain checklists of things to check when I mess up, because I mess up all of the time in PASM. The good thing is I can fix my mistakes 10 times faster now. Even the concept of indexing in PASM took me some getting used to, because it is already self-modifying code in a way (the movd and movs commands). movs/d blew my mind when I figured it out, now it seems so simple.
Sign In or Register to comment.