Union supported by compiler?

Do these functions even exist on the spark? I don't think any kind of standard file access is supported; even the arduino seems to require a special SD class for file handling on an SD card.

I went through the code and I can’t find anything exotic except for the use of the Stream class. Could those functions be related to that? Could Stream be causing all the problems?

Hi @peekay123

You are definitely running out of flash room and I think it is because you are dragging in some big chuck of code that you didn’t mean to (and this doesn’t happen in Arduino).

There are a bunch of things in this genie code that are unusual from what I have seen of Arduino code (like the pointer to the serial port handling) but all of that would be run time problems, not compile time problems. I would not have had my own _serial global var for instance due to possible name collision–a class might have been nicer.

The Unix file system helpers I think have to be included in libg.a with GCC even if you are not using them. In other words, if your embedded system doesn’t need these, when :spark: or whoever built libg.a for the cross-compiler, they should have included empty definitions for these rather than omit them.

I think that this is clue that what is being pulled in and making your code so large is file system related but I can’t see it. Maybe start commenting out big sections and see if you can get it to compile and link?

Beyond this, I am stumped and you need someone with more GCC debugging experience.

The arduino version of this code was written to work on several board types. Given that this is Spark specific, I’m going to start ripping some of that generic serial port stuff out to see if it helps.

@bko is correct (& thanks for pointing me to this topic, btw).

I’ve been working a little with 4D on cleaning up the library code (putting it into a class and fixing how they interface with the serial ports). They’ve been a little conservative because they don’t want to break backwards compatibility. Some of my recent improvements are in there (under Clinton Keith), but there is more to be done.

Based on the @bko’s observations, I changed all the serial pointers to use the hardcoded Serial1. It made no difference. There is still a huge overflow of flash and the read/write/etc link errors.

I’ll try commenting out large sections as suggested…

OK, I have to do other stuff for several hours, but I found the source of the overflow/link errors.

I changed:
static unsigned long waitPeriod = millis();

inside the loop() function to
unsigned long waitPeriod = millis();

outside the loop (made it global). Now it compiles and links. No idea why. I’ll try to get something running later today.

I would have never predicted that in a million years!

Good find, but a real puzzle now.

ClintonKeith, that is freakingly weird!! I have not had time to work on the library since my last post. Any chance you can share what you have so far so we have another pair of hands on it? :smile:

I see the line at the bottom of loop:

waitPeriod = millis() + 50;

this should be:

waitPeriod = millis() + 50UL;

I wonder if it works that way with the static var?

Hmm, looks like maybe that function is cranky before setup() is called. I'll add a bug for that.

Thanks!
David

Hi @Dave

Here is the loop() code in question from @peekay123 version, so we are way past setup(). It seems that there are other static vars that are not problematic. It will be interesting to see what the bug turns out to be.

void loop()
{
  static unsigned long waitPeriod = millis();
  static int gaugeAddVal = 1;
  static int gaugeVal = 50;

  genieDoEvents();

  if (millis() >= waitPeriod)
  {
    // Write to CoolGauge0 with the value in the gaugeVal variable
    genieWriteObject(GENIE_OBJ_COOL_GAUGE, 0x00, gaugeVal);
    gaugeVal += gaugeAddVal;
    if (gaugeVal == 99) gaugeAddVal = -1;
    if (gaugeVal == 0) gaugeAddVal = 1;

    // The results of this call will be available to myGenieEventHandler() after the display has responded
    // Do a manual read from the Slider0 object
    genieReadObject(GENIE_OBJ_SLIDER, 0x00);

    waitPeriod = millis() + 50; // rerun this code to update Cool Gauge and Slider in another 50ms time.
  }
} 
1 Like

bko, Dave, I have not had a chance to compile this code locally to look at the resource consumption cause I don’t have shinny new command line utility I can use in windows yet! :stuck_out_tongue: However,it does compile in the web IDE. Has the serial1 buffer fix been merged with the master yet? If so, I will hook up my 4D display and test it out.

@peekay123 - Yeah, that was unexpected and weird. I’m going to hook up the Spark, see if I can get the 4D to work. If I can, I might back out some of the hardcoded Serial1 changes. Then I’ll put a fork up on Github.

ClintonKeith, I just noticed that the Serial1 fix WAS merged so it now has a receive and transmit ring buffer. That should work really well now. I’ll be testing the less modified version later this evening. Let me know how it goes! :slight_smile:

@peekay123 Sounds good. Flashing this to a Spark isn’t working. Just goes back to blue strobing cyan, but no longer connects.

@ClintonKeith @bko Some of the first code I wrote after getting my Core was very similar to the the line of code in this thread:

static unsigned long waitPeriod = millis();

The static variable definition was inside of of a function called by loop(). Unfortunately, it resulted in local build errors with the resulting code being too large to fit in the Core flash/memory. I finally figured out that assigning the result of millis() to a static variable was what was causing the problem - but not why - and just refactored the code to avoid the issue.

However, when I compile equivalent code today against the latest spark / core-firmware master branch, it builds and works fine. This commit may have fixed it but there have been other commits in the last week related to millis(), so I’m not sure.

Bottom line: I think this issue is already fixed if you build locally using the latest master branch.

1 Like

ClintonKeith, I connected my 4D to the spark TX/RX and had a protocol analyzer hooked up just to make sure they were correct and the display was sending data. I was able to download the code to the core and it rebooted with a breathing cyan so all was good. BUT, even though the 4D was sending data, the core did nothing. So, I added a Serial.begin() and Serial.print() lines to see what was happening. Those did not work. Then, I commented out the all the genie code in setup() and loop() leaving a bunch of Serial.print() lines. The terminal prints did NOT work! So something is weird. I think I will take this to my command line compile environment to see if I can get more info.

I was helping 4D when they ā€œwroteā€ that new library. They actually contract it out. The way the code works with the serial.read() may be an issue so I will look at that. It was very arduino dependent. I also told them that they should wrap it in a class to follow arduino guidelines but I suspect they did not want to spend the money! :monkey_face:

1 Like

OooHHHH! I see! So the commit you pointed to, which adds minimal thread safe one-time initialization guards was NOT there before, so some library the linker has access to was trying to provide an implementation for those guards and we were overfilling flash.

Looking around, I see that teensy had this bug too for a time because these guards were commented out.

Very interesting bug.

@peekay123 I offered to wrap it in a class myself for free, but they didn’t get back to me. It sounds like they are a bit overwhelmed supporting all the tools and internal stuff.

I stripped out all those enumerated functions (one for each serial port) and put in the serial pointer. It was a joy to remove about 1/3 of that code. What are you seeing with the serial read that might be a problem?

One odd thing is that the 4Ddisplay didn’t even boot up. I’m supplying it with a separate 5V supply. The problem might be electrical. The digital lines from the 4D are 5V. I’ve read that’s OK with the Spark, but at the very least the VisGenie widgets should have displayed even without serial read/write working.

bko, ya, what you said! I was looking through the genie code and found out why nothing seemed to happen with serial data INTO the Spark. They had this code for the getchar() function:

///////////////////////////////////////////////////////////////////
// Serial port 0 (Serial) Rx  handler
// Return ERROR_NOCHAR if no character or the char in the lower
// byte if there is.
//
uint16_t _genieGetchar_Serial (void) {
#ifdef SERIAL
	if (_serial->available() == 0) {
		_genieError = ERROR_NOCHAR;
		return ERROR_NOCHAR;
	}
	return (uint16_t) _serial->read() & 0xFF;
#endif
}

It’s all perdy like but one problem… SERIAL is not defined anywhere!! So basically nothing ever gets received. WTF! Also they have a couple of functions not called anywhere:

_genieFlushSerialInput() and genieResync(). They were supposed to be used in an error handler they never used. Problem is _genieFlushSerialInput() is written to loop forever! I guess they ran out of budget to finish the code. I’ll be testing some more in the morning with the changes I made and hopefully, it will live. Muahaha! :smiley: