Going nuts! What am I doing wrong?
photomankc
Posts: 943
This code should, as I understand things, work. But the whole function is acting crazy. No matter what value I place in the array, even if I directly assign it in the function, I never get that going out the bus, its always a fixed value that has no relation almost like It sent the address and not the value. mailbox.buffer is a pointer to type uint8_t. So if I create an array of those named bytes and give that to the stucture that should work yes?
Thing is that any function variable I create acts the same. I get some bogus value and not the value I put in the variable. This for instance should produce a write of 0x0000 but instead gave me 0x280C.
This works fine and sends the bytes I call it with but in the reverse order of what I need them to be:
Then interestingly this has no effect what-so-ever despite the fact that as I understood it I should have passed wd by value so that I should be able to alter the value. The result is that it sends the bytes the function was called with completely ignoring the fact that I reset the variable to 0? WTH?
I'm totally stumped. So long as the buffer is one that is not created in the fuction then the write code in the cog driver works perfectly. It's when I try to use a buffer that is created within the function that it's writing out the garbage values and I can't figure out why at all.
int i2cTXWordReg(I2C_STATE *dev, int address, uint16_t reg, uint8_t rcnt, uint16_t wd) { // write 0x1A2B -- high byte first; uint8_t bytes[2]; bytes[1] = 0x2B; bytes[0] = 0x1A; dev->mailbox.hdr = (address << 1) | I2C_WRITE; dev->mailbox.buffer = bytes; dev->mailbox.count = 2; dev->mailbox.reg = reg; dev->mailbox.reg_count = rcnt; dev->mailbox.cmd = I2C_CMD_REG_SEND; while (dev->mailbox.cmd != I2C_CMD_IDLE) ; return dev->mailbox.sts == I2C_OK ? 0 : -1; }
Thing is that any function variable I create acts the same. I get some bogus value and not the value I put in the variable. This for instance should produce a write of 0x0000 but instead gave me 0x280C.
int i2cTXWordReg(I2C_STATE *dev, int address, uint16_t reg, uint8_t rcnt, uint16_t wd) { uint16_t temp = 0; dev->mailbox.hdr = (address << 1) | I2C_WRITE; dev->mailbox.buffer = (uint8_t*)&temp; }
This works fine and sends the bytes I call it with but in the reverse order of what I need them to be:
int i2cTXWordReg(I2C_STATE *dev, int address, uint16_t reg, uint8_t rcnt, uint16_t wd) { dev->mailbox.hdr = (address << 1) | I2C_WRITE; dev->mailbox.buffer = (uint8_t*)&wd; }
Then interestingly this has no effect what-so-ever despite the fact that as I understood it I should have passed wd by value so that I should be able to alter the value. The result is that it sends the bytes the function was called with completely ignoring the fact that I reset the variable to 0? WTH?
int i2cTXWordReg(I2C_STATE *dev, int address, uint16_t reg, uint8_t rcnt, uint16_t wd) { wd = 0; dev->mailbox.hdr = (address << 1) | I2C_WRITE; dev->mailbox.buffer = (uint8_t*)&wd; }
I'm totally stumped. So long as the buffer is one that is not created in the fuction then the write code in the cog driver works perfectly. It's when I try to use a buffer that is created within the function that it's writing out the garbage values and I can't figure out why at all.
Comments
I added a small delay in the while loop and suddenly the low byte made it out correctly but the highbyte was gibberish. Added double the delay and bingo the bytes all made it out. Used a printf to verify that the dev->mailbox.cmd was not becoming 0 before the while loop and confirmed that. So why then was it just plowing on through and returning anyway? I turned off all optimization and then the code works with or without the delay code within the while loop. For some reason the optimizer is deciding that while loop is not required and seems to be snatching it out during compile time. I guess I see that, but a while loop to poll something is used all over so why just here.
I'll get the code up tonight.
Eric
The volatile keyword must be used to let the optimizer know that the code/data should not be optimized away - this is a standard embedded coding practice with C.
If you never use optimization this is not a problem - someone else using your code may stumble over it though.
That's exactly what happened here. The declarations of the structures are straight out of propboe I2C code.
Now it's the opposite problem. If I compile without optimization the code dies at line 46-48. Hangs and never comes back. If I set it to -Os then it will run. I've been having a great deal of issues when passing the instantiated I2C object down the chain as a reference. Earlier it would die just like this if I tried to perform any read or write on the accel/gyro/or compass objects from inside the MiniIMU9 constructor. So accessing them through members of the MiniIMU9 seems to trigger the issues but I don't understand what the issues are.
I need to be able to share the bus with numerous other objects as that was the point of the exercise. The correct address for the bus is getting all the way down to the accel/compass/gyro for them to store but somehow it's falling apart otherwise. I've attached the project if anyone has time to waste looking at my mess.
-Tor
Using built-in specs.
COLLECT_GCC=c:\propgcc\bin\propeller-elf-gcc
COLLECT_LTO_WRAPPER=c:/propgcc/bin/../libexec/gcc/propeller-elf/4.6.1/lto-wrappe
r.exe
Target: propeller-elf
Configured with: ../../propgcc/gcc/configure --target=propeller-elf --prefix=/op
t/parallax --disable-nls --disable-libssp --disable-lto --with-pkgversion=propel
lergcc_v0_3_5_1523 --with-bugurl=http://code.google.com/p/propgcc/issues
Thread model: single
gcc version 4.6.1 (propellergcc_v0_3_5_1523)
Adding a volatile to the local integer (n) declaration in the same function it's used in and my program terminated correctly if I commented out the cog start code to force a failure. Why on earth would I need volatile to keep it from eating a variable in the same function? I'm feeling a little uncomfortable that it's rubbing out my conditions in places I sure would not expect it to do so in.
So, in I2CDriver main, mailbox->cmd gets set to IDLE at startup (after you've set it to INIT).
Then I2CDriver main waits for something other than IDLE. So ....
Shouldn't you wait for IDLE to happen rather than not IDLE after cognew?
Since the first INIT is basically ignored, set INIT and wait for IDLE again.
That's the way I read it. Maybe I missed something though.
--Steve
What happens if you move the mailbox m_dev out of the I2C class to a global variable?
BTW, I can't explain the other behavior. Someone else will have to answer that one.
Scope errors maybe? Perhaps m_dev should be a pointer in the class and get initialized with an i2c.setMailbox() call. I don't think we should be using the stack for this mailbox interface (i2c instance is on the stack). Give me some time and I'll make a similar project to see what's happening. I have a similar project that uses PASM cogs that works fine, but not cogc (COGC stack related?) - should be easy to convert. Too tired to do this today ....
I've made the change to make the I2C_STATE structure a global... finally figured that one out. That seemed to work for a while so I went on and made a few changes dealing with computing some values from the sensors and then after adding in some simple code to do some subtraction it came unglued again. The prop is not just locking up, it's executing data I'm sure as the QuickStart LEDs will start to light up now and then after the display quits and every now and then it may cause the main program COG to restart. I checked this out and the code should run on any QuickStart even minus the I2C connections. It will just mistakenly believe the device has ACK'd and the clock-stretch timeouts will cuase it to read all 0's so the program should run and start a loop printing values of all zeros from the sensors.
At -Os the zipped project will run and give you output from the loop. To create the failure uncomment the correction factor subtraction in MiniIMU9::GetAccelVector()
Once you uncomment those subtractions the whole thing crashes at -Os. Now leave them in and set the project to -O0 and once again it will run just fine.
I guess I'm done for a while on this. One of the play time sessions running around in memory must have got some actual bytes out to the reserved values in the Magnotometer because it's now heavily negative biased and was not that way yesterday afternoon. I can probably correct in software later on but for now I'm not realy confident in going much further. Consequences of some of tmy robots I/O lines and random writting to OUTA could be smoke.
I can't seem to get past the first cognew on 3 different XMMC capable boards including Quickstart
Changed the board to C3 and memory model to XMM-SPLIT, and the program runs fine with or without the comments mentioned.
I've tried reducing the Cache size for XMMC on Quickstart and C3F, but that doesn't seem to have any affect. That doesn't void changing to memory model XMM-SPLIT for boards with such support, but it does call into question how the cache driver seems to get loaded.
Thanks,
--Steve
So the I2C_STATE variable that is global gets an address of 0x97C (2428). I figure that is created early in the program. Then I create a few integers and the first object I make in main is the I2c bus object and it has an address of 5f58 (24408). As I understand it the stack should start at the top and grow down, and I wouldn't think the addresses are random so it *looks* like before I even start to move that 24K is chewed up.
Using Simple Printf Produces a 21KB executable when compiled as C++. If compiled as C then it's only 7KB. I still cant figure out what is filing up 20+KB of RAM in my program.
The GCC map file is listed by linker section. There is a perl script that makes it prettier on propgcc.googlecode.com assuming you have perl installed - simple ide doesn't install perl. Usually the cog images are last in the image. SimpleIDE search works on the map file .... As I recall, the last (highest address) data symbol is heap_start ... there is a bunch of .debug sections in there for some reason though.
When I was experimenting with cache sizes I forgot to change the cache-size in the .cfg file. I'll have to look at it again.
The 0x5F40 number is definitely in the stack region. More exploring to do ....
ETA: Consulted the wise and powerful Google. So I converted all the other base functions to non-leaf by adding the function call to check for clock stretch so now the only leaf function is the i2cStretchHold. I have to check for clock stretching because my motor driver will do it now and then durring transfers. I did not want to make it a define because that would bloat out the code adding it in everywhere.
Never-the-less symtoms remain the same with the _NATIVE tags removed. -Os and it locks up when a call is made to the get the corrected acceleration values. -O0 operates as normal but is pushing 60KB.