BASIC for Teensy 3.0/3.1

Status
Not open for further replies.
I've found that (for USB), (!Serial) rarely or never evaluates to True, on the Teensy 3's.

For now, with Teensy 3 and C/C++, I just put in a 5 second delay before sending debug info out the USB/serial port, and assume that I will open a terminal window in that time.
well, I tried this altered example on the Teensy 3.1
Code:
void setup()
{
  Serial.begin(9600); // USB is always 12 Mbit/sec
  while (!Serial)
    ;
}

void loop()
{
  Serial.println("Hello World...");
  delay(1000);  // do not print too fast!
}
And it did not hang in the while loop.
I've seen it hang so many times that I stopped using it. And others have reported it on the forum.
Must be some situation of some other code involved.
(Win 7/74 bit).
I dunno.
 
I've taken the setupBASICbeta download down for now, but it will be back up in a day or two.

The good news is that I have worked out what it takes to get a Teensy working in the BASIC IDE environment for the first time. Originally we kind of stumbled on how to sync up a Teensy with Windows USB and also our IDE. After lots of trial and error, I've come up with the sequence to always get back to the start.

Among the things we noticed are Teensy can report as an available USB device, but then crash and Windows won't really know it has crashed until it tries to access it.

I looked though the usb_serial code and see the usb_cdc_line_rtsdtr variable, but haven't really tried to see if Windows can affect that. We may use that in the future, but don't need it now. FYI in the NXP boards we do; we do use both DTR and RTS to control reset and startup of the ARM.

We also noticed that pushing the button on the Teensy will reload the last code loaded, IF the teensy.exe is running. But we also noticed if teensy.exe is not running it does load something that does not enable the USB driver and the board does not ID itself as a serial device. While this may seem bad, from our perspective it is good because we are then in a known state and we can get back to in synchronization.

So all we have to do now is put the sequence into a set of user prompts and go from there.

Now that we know how to control the environment we can also start the user code on any reset, so it will do a load and go rather than having to use the RUN button. The RUN button will still be there and will re-execute a loaded program if it stops, or can be useful when you are typing in a program a line at a time. While we wouldn't recommend that for any big program, we find it very useful for doing quick checks of code to control ARM peripherals.
 
I feel like the best way for Coridium Basic to work is to automatically merge the pre-compiled (as needed) run time support code with the user's code, to yield a single .hex. That .hex would be just like a 100% self-contained C/C++ program. Then the natural ways of Teensy.exe would work the same - no special listener code runing on the Teensy module to create an always-open serial connection via USB - which is where the integration complexity comes up, rather than just having a single self-contained .hex, all-in-one. I would not rely on/use the DTR mechanism at all.

Yes, if the user program crashes in the wrong manner, you have to push the button on the teensy module. This happens to me only with early immature code, which does system things. So such a crash is rare in most uses. I would not let that situation drive things.

Please be sure to leave in the means to "check" compile for errors but don't download. Equivalent of the Arduino IDE "check" button vs. download button. And same on big-boy IDEs with "build" but don't download. Or Build All.

Looking forward to another version to try.
 
Last edited:
Merging 2 .hex files is fairly easy. Just remove the last line from the first file, and then concatenate the 2 files together.

Here's the last few lines of a .hex file.

Code:
:1084F40090FEFF1F90FEFF1F98FEFF1F98FEFF1FB8
:10850400A0FEFF1FA0FEFF1FA8FEFF1FA8FEFF1F67
:10851400B0FEFF1FB0FEFF1FB8FEFF1FB8FEFF1F17
:08852400FFFFFFFF0000020051
:00000001FF

That last line with ":00000001FF" is the end-of-file marker. All you have to do is remove that line, and then add all the lines from the other file, which should have its own EOF marker.
 
Easy... right. This enables one download. Removes the need for the special download of the library when choosing the target CPU. And all that rot.
Click 'load' or 'reload' to compile user code, check for syntax errors. (Even name it 'check' as Arduino users are accustomed to?). Then the 'run' button (equivalent to the Arduino right-arrow button) to push the code down using Teensy.exe and reboot and the other tools.

And/or do what Arduino does.. compile from source to .o once at the beginning of the user work session, instead of using a pre-compiled .hex.

That might be a better way for the BasicTool to work?
 
Actually I am merging files now, so that is working fine.

Paul-- there are 3 different ways to indicate an extended address record in Intel hex format. For our stuff we have been using a 02 record, but seems like you are looking for a different one to address beyond 64K. So which one is it.

A data point on DTR/RTS. Seems like any time DTR changes the state of both DTR and RTS are reflected in usb_cdc_line_rtsdtr. But if only RTS is changed whatever value was in RTS the last time DTR changed is what is reported. Fine for us for now.

Always something, as I need to use that to impliment load and go, because one of the buttons on our IDE is STOP, and we need to load and not go in that case.

plugging away...
 
Paul-- there are 3 different ways to indicate an extended address record in Intel hex format. For our stuff we have been using a 02 record, but seems like you are looking for a different one to address beyond 64K. So which one is it.

Teensy Loader looks for either 02 or 04 records. Whatever the 3rd way is, Teensy Loader doesn't support it.

In fact, here's the code which parses the intel hex:

Code:
        if (line[0] != ':') return 0;
        if (strlen(line) < 11) return 0;
        ptr = line+1;
        if (!sscanf(ptr, "%02x", &len)) return 0;
        ptr += 2;
        if ((int)strlen(line) < (11 + (len * 2)) ) return 0;
        if (!sscanf(ptr, "%04x", &addr)) return 0;
        ptr += 4;
          /* printf("Line: length=%d Addr=%d\n", len, addr); */
        if (!sscanf(ptr, "%02x", &code)) return 0;
        if (addr + extended_addr + len >= MAX_MEMORY_SIZE) return 0;
        ptr += 2;
        sum = (len & 255) + ((addr >> 8) & 255) + (addr & 255) + (code & 255);

        if (code != 0) {
                if (code == 1) {
                        end_record_seen = 1;
                        return 1;
                }
                if (code == 2 && len == 2) {
                        if (!sscanf(ptr, "%04x", &i)) return 1;
                        ptr += 4;
                        sum += ((i >> 8) & 255) + (i & 255);
                        if (!sscanf(ptr, "%02x", &cksum)) return 1;
                        if (((sum & 255) + (cksum & 255)) & 255) return 1;
                        extended_addr = i << 4;
                        //printf("ext addr = %05X\n", extended_addr);
                }
                if (code == 4 && len == 2) {
                        if (!sscanf(ptr, "%04x", &i)) return 1;
                        ptr += 4;
                        sum += ((i >> 8) & 255) + (i & 255);
                        if (!sscanf(ptr, "%02x", &cksum)) return 1;
                        if (((sum & 255) + (cksum & 255)) & 255) return 1;
                        extended_addr = i << 16;
                        //printf("ext addr = %08X\n", extended_addr);
                }
                return 1;       // non-data line
        }
 
...
A data point on DTR/RTS. Seems like any time DTR changes the state of both DTR and RTS are reflected in usb_cdc_line_rtsdtr. But if only RTS is changed whatever value was in RTS the last time DTR changed is what is reported. Fine for us for now.

Always something, as I need to use that to impliment load and go, because one of the buttons on our IDE is STOP, and we need to load and not go in that case.

plugging away...
I suggest not using / disabling the STOP button when in Teensy mode. Instead, the user just corrects the code, compile and start a new download. This works except for the rare case where the amok user program left the CPU in such a state that the Teensy board's button has to be pushed. For me, this is quite rare. And too, if the program was amok, the STOP button wouldn't work either!
 
In a prior project where my 128KB ARM7 downloaded updates from a TFTP server, I parsed only record types 0, 1, 4 and 5. The "extended linear address space" record is 4. Endian is defined in that Intel hex spec.

That TFTP server based download, remotely triggered, did an in-place update of the code in the second sector and higher. No SD card or big RAM to store the whole new version of 120K of code. Sector 0 in flash code "secondary bootloader using TFTP" did the download and code replacement, repeatedly until success. I had a 100 of these in the field in 3 countries, unattended and this scheme worked well. I tested the heck out of it so we didn't have to get on airplanes to do updates. No one on site could do it, technically and politically.
 
Last edited:
Teensy Loader definitely does not recognize the 05 record type.

In fact, I have no idea how to interpret this description (in the context of Teensy3's ARM processor) from the wikipedia page:

05, Start Linear Address Record. The address field is 0000, the byte count is 04. The 4 data bytes represent the 32-bit value loaded into the EIP register of the 80386 and higher CPU.

Maybe someone more familiar with the X86 processors could explain what this means?
 
Record 5 is simply passing a 32 bit address where to begin execution of the loaded code. Of course, it's optional. And the linker usually handles this symbolically, or there's an implicit JMP 0 or JMP 0x40 or some such for bare-metal startups. I never used record type 5, but I parse/ignore so I can get a valid end of file condition.
 
as Bullwinkle use to say...

"This time for sure"

www.coridium.us/files/setupBASICbeta.exe

This handles the online/offline nature of the Teensy at least in a couple cases, there may be some time tuning we need to do. That is the kind of feedback we need. I don't want to make the delay arbitrairly long, and if you're running on a 286 machine you really need to upgrade :)

Anyway, I've got it doing load and go. The popup window comes up while BASICtools thinks the Teensy is offline. We really should lock out the user at that point, but we don't for now. What that means is typing or pushing buttons should be disabled.

I know Steve doesn't like STOP, but it really is useful, except we can't really do a STOP yet on Teensy. In our other systems, it actually stops the program and you can go out an peek at variables and ARM registers and figure out what the heck your program was doing. We'll be working on that, and will probably use DTR.

BASICtools also integrates notepad++ as the default editor (you can still override that with any editor of your choosing). BT also now copies the compiled .hex file into the same directory that the source came from and renames it to your_source_name.hex
 
Great progress. As said below, I did manage to get the led blinker to run on T3.1.

Logic problem:
I tell BT to "Load test.bas".
It correctly displays "Analyzing C:/Users/steve/Desktop/Coridium T3/Coridium/test.bas"
It then downloads successfully without me asking it to! Well OK.
But Teensy.exe says it downloaded a different .hex: "HelloWorld.cpp.hex", unrelated to the "load" that I did, above. (cpp??).
Ah, I see that Teensy.exe is using the last .hex it worked with which in the temp dir.
Kind of looks like BT didn't tell Teensy.exe what .hex to use.

So I told Teensy.exe to use 'test.hex' which this new BT does create in the same folder as the source (good). That test.hex is 40KB (looks like a lot of dormant run time cod is present).
After it downloaded, there were no LED blinks from my test program. Sigh.
I replugged the USB cable (power cycle) and my code began to blink the LED. So BT didn't tell Teensy to reboot/run.

I did this and that, edited, did reload with BT, and it then began to work, perhaps as intended: that being each time I do a load or reload it compiles and downloads all in one step. And runs.

File test.bas has:
Code:
for i=1 to 20
io(13) = 1
wait(1)
io(13) = 0
wait(500)
next i

GUI
Doing a 'load' or 'reload' menu command causes a compile then a download/run. I really don't care for the idea that there's no "compile without download" (check). I need the ability to tell the IDE when I am ready to write the flash and test. Most of us edit code and every now and then, save and compile to see if typos are present in the last bit of work.

The last thing displayed in the BT window, even after downloading, is
Analyzing C:/Users/steve/Desktop/Coridium T3/Coridium/test.bas
Programming Flash 0031...
as if there's supposed to be more info displayed.
Later in my fumbling, it began to display the full messages as it should have.

Minor:
Installation script created directory "notepad++" whereas BT wants "notepad". I renamed the folder and the edit menu worked. Good idea to use 'notepad++' for dir name due to confusing with the program named 'notepad'. Both were already on this PC. (Would the ++ in a dir name be legit in other operating systems?)
 
Last edited:
Does Coridium BASIC have a compiler option like VB6: "option explicit" so that variables must be declared before use?
Python, Javascript and I hope not this BASIC don't require declaration and that leads to lots of wasted time debugging what turns out to be a typo.
Python is nice enough to say at run time: "Variable used before value is set" for misspelled variable names. This is in lieu of mandatory declaration of variables as an option.
 
from bottom (easy to top)

notepad++ fixed right after I noticed it too.

Missing display after the Programming Flash has to do with the time between USB serial becoming available and it actually running (which is where the next messages come from). There is no good indication that the serial port is ready and this may require some additional delay. Or maybe some in system learning.

Before Teensy we would compile and load as one step and run as a second step
Reload would do another compile and load of the the last program (typical use case is you did some edits in the original file)

I guess we could offer--
Open -- which still selects a new program -- other users (offline here) like the new load and go feature
Compile -- which would compile and produce the .hex file if no errors -- would be a new option
Run (compile, load and go)

Right now the .ini saved by the BT keeps track of the last program selected. I guess if BT was just started, then Compile or Run would force an Open, though that to me seems to be an extra step since we go to the trouble of keeping the last program opened in the .ini There is never a perfect solution and different users expect different things

I have seen Teensy.exe not loading the right program (especially on a slow XP system), and it may be some timing issue, we did run into executing teensy_post_compile and teensy_reboot too close together causing problems in Win8 (seems like exec x in Win8 is actually the equivalent of exec x & in Win7)

From my perspective, I always compile and run, hardly ever do re-compiles in between except to resolve compile errors. Like I said everyone has a different way of working. Some people even like vi :)
 
Yes we do have an explicit option in BASIC.

As soon as you declare one integer type variable, then following that ALL integer variables must be declared.

So--

x = 123 ' auto declares x
DIM z(20) ' declares an array
y = 456 ' auto declared as the array is not an integer variable
DIM i as integer ' aha the first declared integer variable
j =455 ' will be flagged as an undeclared variable

I'm not into #pragma kind of things
 
OK in the implicit explicit (!).

It's fun to see a decent BASIC on the itty-bitty Teensy!
 
Last edited:
Oopsi, I guess I should believe you Steve

I was able to duplicate the file not readable error by teensy.exe, and it had to do with the clue you gave me on loading the last file chosen. That is fixed in version 5.24 and has been updated at the link above. It should also fix that last file loaded issue

Should I admit the error -- yeah sure, I often don't install into the /Program Files (x86) directory because Win7/8 keeps me from editing files there, and the spaces in that name were incompatable with one of exec batch files we create, so it was failing and we weren't flagging it. So this should be stable now while we mull over menu changes. We might build a specific version for Teensy that starts up configured for it.

Right now we use the standard interface, and to select Teensy for the first time choose that in >Options >Control >Teensy3.0/1

After that it pares back some of the unused options in the menus
 
(I never make mistakes. I thought I made one once, but ... I was wrong.)

The handshakes still aren't correct...
I'm editing, downloading, running, LED blinky variations.
I exit BT and Teensy.exe.
I re-launch BT. It doesn't launch Teensy.exe. When I RELOAD, it does launch Teensy.exe. Well, OK. Maybe that's how it is intended.

I exit BT.
I copy my .hex to newname.hex. I tell Teensy.exe to use newname.hex. (As if newname.hex was from a cpp program).
I push the button on the Teensy module to force a download. OK.
I launch BT.
Things are confused now. It lost track of COM16, so it reverted to not using the Teensy3.1 target choice in the menu.
I re-choose teensy 3.1 in the target.
BT says no COM16, error.
and so on.

The logic isn't quite right. I'd think it would stay with the target choice of Teensy 3.1 until I (me) tell it otherwise. No matter the COM port availability.
It seems that BT has to follow the Teensy downloader protocol just as is done for Teensyduino produced .hex files. That is, when the .hex is produced, do whatever to invoke the gateway.exe/download/reboot.

This is since the BASIC runtime code is in the same .hex as the user's program. Thus, there's no difference.
Perhaps you're hanging on to the run-time being there and opening the USB virtual serial (COM16 for me) so the BT logic for hardware serial can be used - for the RUN/STOP commands that aren't in the Teensyduino concept. I have a feeling this can never be intuitive for the average user when using the Teensy.exe protocol.
It isn't for me, and I admit to not being average. :eek::eek:
 
Last edited:
when my program is running, and I use
print "hello world"
what I/O is used?
I see that COM16 remains open - I suppose the run-time keeps it open. Therefore, as we're accustomed to with Teensyduino, with BT, we don't use a terminal program to open COM16 (et al)? That can be the terminal built into Teensyduino's IDE (Arduino), or any external of our choice. Normally, after the download, the USB/serial is closed. It is reopened only if (in C/C++) we use the class 'Serial', which is always created automatically in Teensyduino programs. So the class instance Serial is used merely by initializing it with Serial.begin(baud) where baud is N/A for USB serial. Same goes for hardware serial, which are pre-instantiated as Serial1 and so on.

So does BT read COM16 and copy text to the BT display window? I'm not seeing output from Basic print statements.
 
Try to update again, this time it actually has the fix in it, and that may fix your PRINT as well. It should work as you would expect.

BT keeps Com16 (in your case) open for PRINT and DEBUGIN which is the "console". The BASIC also has support for the 2 UARTs that can be accessed as RXD(1)/RXD(2) and TXD... Though I haven't checked them out yet.

Once you have working .hex file, you can use any other terminal emulator program TeraTerm or yuck-HyperTerm.

BT doesn't launch teensy.exe until it needs to, and can't kill it when it exits. BT should (sometime soon) remember Teensy3.0 / 3.1 on launch, its not kept in the .ini right now
 
Ah so! I re-downloaded, installed as you suggested.
Now PRINT works, where the output goes to the BasicTools window.

Good.
 
In this early beta stage, is it true that libraries such as rtc.bas or hardware serial haven't been K20'd yet?
 
Last edited:
I believe hardware UARTs support is done but not tested. The Freescale RTC is different from NXPs, so we have not looked at that yet. As we have to add some components to get the RTC to work that is probably pretty low priority.
 
Status
Not open for further replies.
Back
Top