tabemann/zeptoforth

Serial over USB for rp2040

leahneukirchen opened this issue Β· 42 comments

Other rp2040 software like MicroPython or Fusix provides a serial console to the system over USB, would that be hard to add for zeptoforth? It would simplfy usage as it wouldn't require another USB-Serial cable.

Having USB terminal support for zeptoforth is one of those nice-to-haves, but I am currently working on other things, such as adding SDHC card support and FAT32, as well as PWM and I2C support. I will get to it eventually, but I cannot promise anything at this point.

Upvote for this feature. It's probably a pain to implement, but i think it lowers the barrier to entry, and makes quick jobs avoid adding a converter - especially on things like the Pico, (but would be useful for me on the black pill as well.)

Micro Python and others just work. Forth's on these embedded targets don't have that. This would be a serious differentiator for Zeptoforth. I think we need to maintain UART0 as well on the standard build - otherwise Bluetooth serial is hard.

When I filed this issue, I didn't realize one has to implement (significant parts of) a USB stack. So I can understand it's not so easy. ;)

This is one of those "I will get to it when I get to it" kind of things. For the STM32F407 and possibly the STM32F411 (as it is essentially a cut-down STM32F407) I can borrow Jan Bramkamp's code (but even there it will take a good amount of work to fit it into the zeptoforth multitasking model), whereas for the RP2040 I will essentially have to work from scratch. One must remember that this is my side project outside of my day job, so I have only so much time to work on it (and time spent working in one area is time not spent working in another).

Leahneukirchen wrote:

When I filed this issue, I didn't realize one has to implement (significant parts of) a USB stack. So I can understand it's not so easy. ;)

Agreed.

Tabemann wrote:

This is one of those "I will get to it when I get to it" kind of things. [...] One must remember that this is my side project outside of my day job, so I have only so much time to work on it (and time spent working in one area is time not spent working in another).

Totally understood. I was just giving this ticket my 'up-vote'. I'm aware this isn't trivial.

znmeb commented

The new Raspberry Pi Debug Probe kit https://www.raspberrypi.com/products/debug-probe/ will do this and more. My standard setup these days is a Raspberry Pi Pico H breadboarded to a second Pico running picoprobe. This new device will make the breadboarding easier.

hmm .. I know it wouldn't be "pure" but could a stopgap solution be built with FFI and linking in something like tinyusb?

Still looks like one heck of a pain ... sheesh USB is huge ...

znmeb commented

hmm .. I know it wouldn't be "pure" but could a stopgap solution be built with FFI and linking in something like tinyusb?

Still looks like one heck of a pain ... sheesh USB is huge ...

I buy my Picos in pairs now - a debug probe and a Pico H. :-) But seriously, you only need one debug probe for each active Pico, and once you get past breadboarding and start building PCBs the serial interface with a connector is pretty simple.

Even without TinyUSB an FFI interface would be useful, but it has to be portable to all the other boards - it can't depend on the Pico C/C++ SDK.

I have been working on a USB CDC layer for the RP2040 that will just serve as a serial console rather than a general-purpose USB layer that does everything under the sun (and consequently is significantly larger). I admittedly have been distracted by things such as implementing a pending operation mechanism which the USB CDC layer will use (and which will be able to serve as a split interrupt mechanism on a more general level).

Even without TinyUSB an FFI interface would be useful, but it has to be portable to all the other boards - it can't depend on the Pico C/C++ SDK.

True, and avoid letting the foreign code accidentally clobbering parts of the forth system.

The key thing is that zeptoforth expects to own the entire system; it probably wouldn't play nice with a external library that also wants to control things like interrupts.

USB CDC console support has been added to the full_usb build of zeptoforth 1.0.0 on the RP2040, just so you guys know.

USB CDC console support has been added to the full_usb build of zeptoforth 1.0.0 on the RP2040, just so you guys know.

What did you have to do to get it to work?

@robzed I simply had to implement USB support, and USB CDC support on top of that, using the RP2040's built-in USB peripheral. I was guided in part by example code and tinyusb code online and in part by Jan Bramkamp's and Jeelabs' USB CDC console code for the STM32F407. There were some catches, e.g. the initial input and output are horribly corrupted when using Linux on the host if you transmit data prior to receiving DTR, which I had to resolve (by blocking transmit until DTR is received). All in all, though, it turned out to be simpler than I expected.

Note - it turns out there was a bug in USB support for the RP2040, which is fixed in release 1.0.0.1.

@tabemann I have loaded 1.0.0.1 and have connected over the usb using Zeptocomm.

This statement fails :

create test ," 12345" unable to parse: ,"

I haven't used Zeptocomm before, what am I doing wrong ?

@ctrilsbach Nothing is wrong with zeptocom.js there. The issue is that you used ," (with a comma) rather than ." (with a period/full stop). And if your intention is to use a word that simply writes an arbitrary string to the current dictionary (whether flash or RAM) named ," (with a comma), it simply does not exist, even though you could always create it.

@tabemann ," is in all my Forth books, with the definition " Compiles a string terminated by " as a counted string. Typically used to build a string data structure." I thought this was one of the base dictionary words in any Forth and it works in all the other Forths I have available.

@ctrilsbach
The Forth 1994 ANSI standard uses S" and C" https://www.greenarraychips.com/home/documents/dpans94.pdf
The Forth 2012 Standard also uses S" and C" https://forth-standard.org/
The equivalent for ," is C" in standard compliant Forths (address of a counted Forth), although address and count on the stack is often more flexible
I suspect the standards didn't use ," to avoid confusion.

Zeptoforth supports both S" and C"

  • s" ( β€œtext” – ) ( compiled: – b-addr u ) Compile a non-counted string
  • c" ( β€œtext” – ) ( compiled: – b-addr ) Compile a counted-string

NOTE: In most Forth's these can only be used inside a definition, not during with the interpreter. I don't remember whehter.

More info:
A.3.1.3.4 Counted strings

Forth 94 moved toward the consistent use of the "c-addr u" representation of strings on the stack. The use of the alternate "address of counted string" stack representation is discouraged. The traditional Forth words WORD and FIND continue to use the "address of counted string" representation for historical reasons. The new word C", added as a porting aid for existing programs, also uses the counted string representation.

Counted strings remain useful as a way to store strings in memory. This use is not discouraged, but when references to such strings appear on the stack, it is preferable to use the "c-addr u" representation.

@ctrilsbach I've just check Forth-79, Forth-83 and Fig-Forth and I don't see ," defined in those standards (and I also checked and Jupiter Ace Forth and gForth). As @tabemann said it's easy enough to define yourself, but I suspect from your description that you could just replace it with C" directly.

I would be interested to know which books mention it out of interest.

@robzed The books are,
Forth Programmers handbook - Edward Conklin & Elizabeth Rather.
Forth Applications techniques - Elizabeth Rather.
Starting Forth - Leo Brodie ( in example code).
I didn't know of the existance of C" and S" but it seems that they can only be used in definitions.
I know that Forth is not a standard but as a beginner it is an uphill battle when you don't know what the best word to use is and if it happens to be in the Forth you are using. Also that you look at code examples in books and they often don't work.
I don't need this to work I was just running a small bit of code I wrote for Mecrisp to test the USB setup.
What do you think is the best Forth reference book ?

I should note that s" and c", and their escaped counterparts s\" and c\", normally compile code to push said strings, as is standard, except for when used in interpreter mode, where then they add said strings to a temporary buffer rather than compile them (which is non-standard).

@ctrilsbach The normal way to create a compiled constant counted string in zeptoforth is with : <my-name> c" <my-string>" ;. Note that this does not merely append the counted string to the dictionary but rather compiles code to push its address.

@ctrilsbach - I have those books. I'll have to check them.
Potentially storing a raw counted string with a word ." in interpreted mode wouldn't be too hard to add to Zeptoforth if you'd care to try. You could parse the input then write the string with maybe cstring, or c,

@tabemann - is there an equivalent of https://forth-standard.org/standard/core/WORD or something similar?

We should probably move this into a Discussions area - and out of @tabemann's "Serial over USB" issue :-)

@ctrilsbach @robzed I have created a discussion under Discussions where I have a simple ," implementation.

I just tested it, and it works! But somehow I got the Pico into a state where I really needed to unplug it to reset, else it would turn into a loop that reset USB everytime I tried to access the serial connection.

@leahneukirchen Could you give me more details about how this came about? I am very interested in seeing what is happening, but without further information I don't really know where to start. I should note that if you sufficiently wedge your Pico reboot and control-C in a terminal emulator or Reboot button in zeptocom.js will not work because they assume you having a working and responsive Pico (control-C and the Reboot button in zeptocom.js require interrupts to be serviced to function).

@leahneukirchen @arlaneenalra What I'm really interested in is the possibility of problems persisting across multiple reboots; I had some problems of this sort early on with the RP2040 when I was trying to bring up both cores. But simply not being able to reboot without a power cycle is something that will never be solved, because zeptoforth by design is not a protected memory OS (as this would be very difficult to implement given its general runtime model, which has no notion of a kernel space).

The device node is there, screen connects, but instantly quits.

In the dmesg it looks like this:

[Mon May 22 17:50:15 2023] cdc_acm 1-4.1.4:1.0: ttyACM0: USB ACM device
[Mon May 22 17:50:15 2023] usbcore: registered new interface driver cdc_acm
[Mon May 22 17:50:15 2023] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters
[Mon May 22 17:50:33 2023] usb 1-4.1.4: reset full-speed USB device number 33 using xhci_hcd
[Mon May 22 17:50:34 2023] usb 1-4.1.4: USB disconnect, device number 33
[Mon May 22 17:50:34 2023] usb 1-4.1.4: new full-speed USB device number 34 using xhci_hcd
[Mon May 22 17:50:39 2023] usb 1-4.1.4: New USB device found, idVendor=0483, idProduct=5740, bcdDevice= 2.00
[Mon May 22 17:50:39 2023] usb 1-4.1.4: New USB device strings: Mfr=0, Product=0, SerialNumber=0
[Mon May 22 17:50:39 2023] cdc_acm 1-4.1.4:1.0: ttyACM0: USB ACM device
[Mon May 22 17:50:44 2023] usb 1-4.1.4: reset full-speed USB device number 34 using xhci_hcd
[Mon May 22 17:50:44 2023] usb 1-4.1.4: USB disconnect, device number 34
[Mon May 22 17:50:44 2023] usb 1-4.1.4: new full-speed USB device number 35 using xhci_hcd
[Mon May 22 17:50:50 2023] usb 1-4.1.4: New USB device found, idVendor=0483, idProduct=5740, bcdDevice= 2.00
[Mon May 22 17:50:50 2023] usb 1-4.1.4: New USB device strings: Mfr=0, Product=0, SerialNumber=0
[Mon May 22 17:50:50 2023] cdc_acm 1-4.1.4:1.0: ttyACM0: USB ACM device
[Mon May 22 17:50:56 2023] usb 1-4.1.4: reset full-speed USB device number 35 using xhci_hcd
[Mon May 22 17:50:57 2023] usb 1-4.1.4: USB disconnect, device number 35
[Mon May 22 17:50:57 2023] usb 1-4.1.4: new full-speed USB device number 36 using xhci_hcd
[Mon May 22 17:51:02 2023] usb 1-4.1.4: New USB device found, idVendor=0483, idProduct=5740, bcdDevice= 2.00
[Mon May 22 17:51:02 2023] usb 1-4.1.4: New USB device strings: Mfr=0, Product=0, SerialNumber=0
[Mon May 22 17:51:02 2023] cdc_acm 1-4.1.4:1.0: ttyACM0: USB ACM device
[Mon May 22 17:51:08 2023] usb 1-4.1.4: reset full-speed USB device number 36 using xhci_hcd
[Mon May 22 17:51:08 2023] usb 1-4.1.4: USB disconnect, device number 36
[Mon May 22 17:51:08 2023] usb 1-4.1.4: new full-speed USB device number 37 using xhci_hcd
[Mon May 22 17:51:13 2023] usb 1-4.1.4: New USB device found, idVendor=0483, idProduct=5740, bcdDevice= 2.00
[Mon May 22 17:51:13 2023] usb 1-4.1.4: New USB device strings: Mfr=0, Product=0, SerialNumber=0
[Mon May 22 17:51:13 2023] cdc_acm 1-4.1.4:1.0: ttyACM0: USB ACM device
[Mon May 22 17:51:18 2023] usb 1-4.1.4: reset full-speed USB device number 37 using xhci_hcd
[Mon May 22 17:51:19 2023] usb 1-4.1.4: USB disconnect, device number 37
[Mon May 22 17:51:19 2023] usb 1-4.1.4: new full-speed USB device number 38 using xhci_hcd
[Mon May 22 17:51:24 2023] usb 1-4.1.4: New USB device found, idVendor=0483, idProduct=5740, bcdDevice= 2.00
[Mon May 22 17:51:24 2023] usb 1-4.1.4: New USB device strings: Mfr=0, Product=0, SerialNumber=0
[Mon May 22 17:51:24 2023] cdc_acm 1-4.1.4:1.0: ttyACM0: USB ACM device
[Mon May 22 17:51:41 2023] usb 1-4.1.4: USB disconnect, device number 38
[Mon May 22 17:51:46 2023] usb 1-4.1.4: new full-speed USB device number 39 using xhci_hcd
[Mon May 22 17:51:52 2023] usb 1-4.1.4: New USB device found, idVendor=0483, idProduct=5740, bcdDevice= 2.00
[Mon May 22 17:51:52 2023] usb 1-4.1.4: New USB device strings: Mfr=0, Product=0, SerialNumber=0
[Mon May 22 17:51:52 2023] cdc_acm 1-4.1.4:1.0: ttyACM0: USB ACM device
[Mon May 22 17:51:54 2023] usb 1-4.1.4: reset full-speed USB device number 39 using xhci_hcd
[Mon May 22 17:51:54 2023] usb 1-4.1.4: USB disconnect, device number 39
[Mon May 22 17:51:55 2023] usb 1-4.1.4: new full-speed USB device number 40 using xhci_hcd
[Mon May 22 17:52:00 2023] usb 1-4.1.4: New USB device found, idVendor=0483, idProduct=5740, bcdDevice= 2.00
[Mon May 22 17:52:00 2023] usb 1-4.1.4: New USB device strings: Mfr=0, Product=0, SerialNumber=0
[Mon May 22 17:52:00 2023] cdc_acm 1-4.1.4:1.0: ttyACM0: USB ACM device
[Mon May 22 17:52:22 2023] usb 1-4.1.4: reset full-speed USB device number 40 using xhci_hcd
[Mon May 22 17:52:22 2023] usb 1-4.1.4: USB disconnect, device number 40
[Mon May 22 17:52:22 2023] usb 1-4.1.4: new full-speed USB device number 41 using xhci_hcd
[Mon May 22 17:52:27 2023] usb 1-4.1.4: New USB device found, idVendor=0483, idProduct=5740, bcdDevice= 2.00
[Mon May 22 17:52:27 2023] usb 1-4.1.4: New USB device strings: Mfr=0, Product=0, SerialNumber=0
[Mon May 22 17:52:27 2023] cdc_acm 1-4.1.4:1.0: ttyACM0: USB ACM device
[Mon May 22 17:52:35 2023] usb 1-4.1.4: reset full-speed USB device number 41 using xhci_hcd
[Mon May 22 17:52:35 2023] usb 1-4.1.4: USB disconnect, device number 41
[Mon May 22 17:52:35 2023] usb 1-4.1.4: new full-speed USB device number 42 using xhci_hcd
[Mon May 22 17:52:40 2023] usb 1-4.1.4: New USB device found, idVendor=0483, idProduct=5740, bcdDevice= 2.00
[Mon May 22 17:52:40 2023] usb 1-4.1.4: New USB device strings: Mfr=0, Product=0, SerialNumber=0
[Mon May 22 17:52:40 2023] cdc_acm 1-4.1.4:1.0: ttyACM0: USB ACM device
[Mon May 22 17:53:16 2023] usb 1-4.1.4: USB disconnect, device number 42
[Mon May 22 17:53:44 2023] usb 1-2: new full-speed USB device number 43 using xhci_hcd
[Mon May 22 17:53:49 2023] usb 1-2: New USB device found, idVendor=0483, idProduct=5740, bcdDevice= 2.00
[Mon May 22 17:53:49 2023] usb 1-2: New USB device strings: Mfr=0, Product=0, SerialNumber=0
[Mon May 22 17:53:49 2023] cdc_acm 1-2:1.0: ttyACM0: USB ACM device
[Mon May 22 17:56:59 2023] usb 1-2: USB disconnect, device number 43
[Mon May 22 17:57:00 2023] usb 1-2: new full-speed USB device number 44 using xhci_hcd
[Mon May 22 17:57:05 2023] usb 1-2: New USB device found, idVendor=0483, idProduct=5740, bcdDevice= 2.00
[Mon May 22 17:57:05 2023] usb 1-2: New USB device strings: Mfr=0, Product=0, SerialNumber=0
[Mon May 22 17:57:05 2023] cdc_acm 1-2:1.0: ttyACM0: USB ACM device
[Mon May 22 17:57:09 2023] usb 1-2: reset full-speed USB device number 44 using xhci_hcd
[Mon May 22 17:57:09 2023] usb 1-2: USB disconnect, device number 44
[Mon May 22 17:57:09 2023] usb 1-2: new full-speed USB device number 45 using xhci_hcd
[Mon May 22 17:57:15 2023] usb 1-2: New USB device found, idVendor=0483, idProduct=5740, bcdDevice= 2.00
[Mon May 22 17:57:15 2023] usb 1-2: New USB device strings: Mfr=0, Product=0, SerialNumber=0
[Mon May 22 17:57:15 2023] cdc_acm 1-2:1.0: ttyACM0: USB ACM device
[Mon May 22 17:57:16 2023] usb 1-2: USB disconnect, device number 45
[Mon May 22 17:57:20 2023] usb 1-2: new full-speed USB device number 46 using xhci_hcd
[Mon May 22 17:57:25 2023] usb 1-2: New USB device found, idVendor=0483, idProduct=5740, bcdDevice= 2.00
[Mon May 22 17:57:25 2023] usb 1-2: New USB device strings: Mfr=0, Product=0, SerialNumber=0
[Mon May 22 17:57:25 2023] cdc_acm 1-2:1.0: ttyACM0: USB ACM device
[Mon May 22 17:59:29 2023] usb 1-2: USB disconnect, device number 46

At first, it also didn't work when I plugged in the Pico via the USB3-hub of my monitor ("flashing" via FAT-mode worked fine tho).

I then plugged it in directly. Perhaps it's some USB2 vs USB3 issue?

@leahneukirchen I am wondering about what you did prior to its stuck-in-disconnect-connect-loop-forever, as that would be very helpful. As for what USB protocol zeptoforth on the RP2040 uses, it is just an ordinary Full Speed USB device.

@arlaneenalra What that points out to me is that the device was in an undefined state, but even still, the old OLED screen example simply should not have compiled (it should have just stated that set-string did not exist), which normally won't put your device in an undefined state. This is very curious indeed.

OK, what I'm seeing is that it hangs trying to do i2c to when there's nothing connected to the i2c bus ... (i.e. I had the oled on the wrong pins and that caused it to hang entirely until I plugged in the oled pins ... so that may be different than what @leahneukirchen was seeing.) I want to say it behaved slightly differently on the serial console than the usb one in this case. (i.e. there was an error message about i2c not responding etc.) But I'll have to wait till later to test that ...

@arlaneenalra @leahneukirchen I would suggest you hook up a USB-serial dongle in addition to the USB CDC console to pins 1 (UART0 TX) and 2 (UART0 RX) of your Pico because, in the event that zeptoforth crashes, it will often dump data to the serial console (not the USB CDC console) if it is not too far gone.

@arlaneenalra If it is dying inside an interrupt handler that could be causing this issue by rendering USB non-responsive; I would be very glad if you gave me whatever info you have available here, just in case we have a genuine bug that needs fixing somewhere.

@arlaneenalra I read your response again and definitely will investigate the I2C non-communication issue; it shouldn't be hanging when attempting to communicate with a nonexistent I2C device.