tabemann/zeptoforth

Ok, where do I find the binaries??

bmentink opened this issue · 31 comments

HI,
I would love to try the recent release of the fullusb version for the rp2040, but I cannot find a link anywhere from this repo.
What am I not seeing?

Many Thanks & great work!

Never mind, finally found it here: https://github.com/tabemann/zeptoforth/releases/

Couple of quick questions:

  1. I can connect with screen to the board, but when I try with zetoforth.js (on macos) connect button does nothing. I don't see anywhere to set the serial port.
  2. Is there a turnkey function, so that you upload code that compiles to flash and then executes on boot. I am struggling to find that in the docs.

Many Thanks.

I found the turnkey info in the wiki, so that is great.

Still cannot use zetoforth.js either on your server or on a local server. The connect button does not pop up a gui to connect to a detected port. Nothing happens. Have you tried this on macos? Thanks.

Hi, thanks for the reply. I am using the brave browser, it is based on chromium engine. So it should work. I will try installing chromium itself and see if it is the same..

Ok, just tried the latest stable build of chromium for macos arm64 and it works fine ..

On a different topic, where do I find examples of adc handling. I am having trouble for example:

adc import  ok
0 26 adc-pin invalid ADC
1 26 adc-pin invalid ADC
2 26 adc-pin invalid ADC
3 26 adc-pin invalid ADC

What is the correct adc for pin26 on rp2040? (There are 3 external adc's pin26,pin27,pin28)

In your docs on the adc, you mention:
On the RP2040 and STM32F411 there is only a single ADC peripheral, numbered 0 on the RP2040
However there is 4 adc channels on the rp2040, so what does the above mean.
(3 external adc's and temperaure)

Okay, adc-pin on the RP2040 is garbage, don't use it; it was meant only for compatibility with STM32 platforms, but as I never used it, I did not realize it was broken. And even with that in mind, there is only one ADC peripheral on the RP2040 even though there are four ADC channels. Anyways, using the ADC is as simple as:

adc import  ok
temp-adc-chan default-adc adc@ . 870  ok
temp-adc-chan default-adc adc@ . 865  ok
temp-adc-chan default-adc adc@ . 866  ok
temp-adc-chan default-adc adc@ . 866  ok
temp-adc-chan default-adc adc@ . 865  ok
temp-adc-chan default-adc adc@ . 865  ok

etc.

where default-adc is 0 and temp-adc-chan is 4. (There are four ADC pins shared with GPIO's, corresponding to GPIO's 26 through 29, and a fifth ADC channel that measures the internal temperature.)

Many thanks for that. I did not realise there was a pin29 ADC, what does that read VSYS?

Just quickly on another isssue with pwm's:
I have 6 channels pwm working but trying to get an interrupt vector added to slice 0 (or any 0,1,2)
I did the following:

: pwm_wrap_int ( -- )   \ interrupt routine

 ;

......
['] pwm_wrap_int pwm-vector!  
 %00000001 enable-pwm-int
%00000111 enable-pwm 

However, when I do the last line it hangs up the console, have to pysically remove power from the board, not even a reboot get's it working again, what have I done wrong?
The above snippet is in a pwm setup word..

What is happening is that you are not calling %00000001 clear-pwm-int within pwm_wrap_int so pwm_wrap_int keeps on getting called in a tight loop forever, such that the USB interrupt handler never gets called so the Reboot button, i.e. Control-C over the console, never is handled.

Travis

Ahh, thanks Travis.

The other bother I have with pwm , is setting the duty with pwm-counter-compare-b! and pwm-counter-compare-a!.

If these channels(a/b) are alternate phases of a top/bottom fet, then controlling the duty for each fet individually, there will be small instants of time where you can get both on at the same time causing shoot-through current. Is there a way to alter the duty of an a/b pair at the same time? I can't see one in your PWM API.

I am doing:

: set-duty ( n - )
      dup 0 pwm-counter-compare-b!  
      dup 0 pwm-counter-compare-a!
      dup 1 pwm-counter-compare-b!   
      dup 1 pwm-counter-compare-a!
      dup 2 pwm-counter-compare-b!   
          2 pwm-counter-compare-a!
    ;

Thanks,
Bernie

No, in my API I did not provide a means for setting both the A and B compare fields at once. However, there is a way of doing it:

: pwm-counter-compare-both! ( b a index -- )
  -rot $FFFF and swap 16 lshift or swap pwm::pwm-internal::CH_CC !
;

I have confirmed that the above code compiles, but I have not really tried it out.

Oh, btw, about GPIO pin 29, one thing to remember is not all of the GPIO pins are exposed to the user on the Raspberry Pi Pico, and IIRC that is one of those which are not.

Travis

That worked great, thanks... I had a look at some of the drivers including PWM to understand what you were doing. I love the concept of being able to have modules/sub-modules etc keeps everything very tidy ..

Have you any thoughts about supporting the ADC FIFO? At times it would be useful to trigger conversion of say 3 adc channels then wait on fifo interrupt to read them out all at once. I am doing a hard real-time project (Sensorless BLDC motor control) where there is some time critical things to do every PWM cycle ..

Cheers

Thanks, will do ...

Can you help with a macos alternative to "gas"? Macos has "as" for arm64 but I do not know if it cross assembles for other arm cores..

Not a problem at all. I am going to have to do some raw adc stuff anyway as your function takes 54us to read a channel.
(0 0 adc@ drop)

Did you have any idea's about macos compiling of your code.. i.e gas equivelent for macos cross-assembly?

Can you pleas tell me where where I can find info on location of gpio interrupt vectors? I do not see any reference
to those in gpio.md or gpio.fs .... probably me being blind though ..... an example would be great, thanks.

An example of the GPIO interrupt in action can be found at https://github.com/tabemann/zeptoforth/blob/master/test/rp2040/lmt01_test_ssd1306.fs - note that io-irq is the IRQ number for the GPIO interrupt, io-vector is the vector index for the GPIO interrupt, PROC0_INTS_GPIO_EDGE_LOW@ is used for testing for low edge events on core 0, INTR_GPIO_EDGE_LOW! is used for clearing low edge events, and PROC0_INTE_GPIO_EDGE_LOW! is used for enabling (and disabling) edge low events on core 0.

Travis

Thanks. Mach appreciated.

By the way, what is the correct way to do init's. I notice you call init in your drivers, what is the correct way to handle init's at the module level?

Thanks
Bernie

Thanks. Sorry about all the questions. A couple more :)

I notice in the timer module there is a delay-us function, does that do a pause ?

Also, not knowing any better, I am continuously doing reboot/connect/send file, as I don't see away to forget words I am developing. Is there a better way? (I have been using the zeptoforth.js tool for small code snippet testing)

Thanks. Not sure on the rational of marker and cornerstone if they involve a reset of the device. The whole idea of forth forget or marker is that you can try a piece of code, then remove that code with forget or marker, and then reload, without resetting your machine or loosing connection to the device .. it makes development so much faster ..

(Also, when I develop code, i write code with a marker at the top, then leave it there in ram/flash when I am happy, and go on to developing the next bit of code, with a marker ... so you can do a lot of programming without having to reset)

Is there a reason why your version of marker reset's the device?
What is the difference between marker cornerstone and restore-state if they all reset the device?

The purpose of marker and cornerstone is to enable erasing words that have been compiled into flash selectively. Note that they are specifically for words in flash. The thing is that this puts the device into a potentially undefined state, hence the reset. (For instance, the flash dictionary index, aka the "minidictionary", is invalidated by these operations.)

About restore-state, that is just a specific word created with cornerstone than comes with the non-STM32F411 full builds. You can create your own cornerstones just like it (e.g. I do that if I have compiled code that I would like to preserve in case code I compile code after it which turns out to be bad, so I don't have to load all my code again from scratch.)

ok, so there is no way to erase a group of words compiled into ram without reboot ... that's a shame.

Can you tell me what is your process for development then, is it all compiled into flash?
I had assumed that development could be done in ram, then flashed when it all was tested..

Thanks, totally understand your reasons.

In the past when I have developed into RAM then it if you have code go wrong, it is normally stack underflow issues and you have that fully protected. If I am developing a driver that talks to registers etc and I put the peripheral in a weird state, then sure I would reboot back to a safe state, but that is very rare.

Personally I would add RAM support for marker so that it does not reboot when you use it, and leave that decision with the user, after all they should know enough to make that decision themselves. That would speed up development greatly.
I assume, that doing that would be less work for you than adding a new word forget ... Cheers Bernie

Thanks for all your help. I have managed to get a BLDC motor working in sensorless mode using zeptoforth. I re-wrote the adc read function, it now executes in 5us instead of 50us, it is good enough if I read one ADC channel per PWM cycle. Ideally I would like to read all three in one PWM cycle by using the ADC fifo and interrupt in continous mode, then just read the results in the PWM. I will look at adding fifo support to the ADC driver.

But the motor works well from 200rpm to over 4000rpm, it is a 100KV motor.

By the way, can any of your existing STM platforms work on the STM32G431 boards?