tabemann / zeptoforth

A not-so-small Forth for Cortex-M
MIT License
160 stars 13 forks source link

Ok, where do I find the binaries?? #100

Open bmentink opened 3 weeks ago

bmentink commented 3 weeks ago

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!

bmentink commented 3 weeks ago

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.

bmentink commented 3 weeks ago

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.

tabemann commented 3 weeks ago

On Thu, May 9, 2024 at 3:38 PM bmentink @.***> wrote:

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

You caught me just while I was writing a response about that.

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.

Which web browser are you using? zeptocom.js does not work with Safari or Firefox because it requires the Web Serial API, which is only provided by Chrome, Chromium, or other web browsers derived from them.

Travis

bmentink commented 3 weeks ago

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..

bmentink commented 3 weeks ago

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

tabemann commented 3 weeks ago

On Thu, May 9, 2024, 17:21 bmentink @.***> wrote:

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

Good to hear!

Travis

bmentink commented 3 weeks ago

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)

tabemann commented 3 weeks ago

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.)

bmentink commented 3 weeks ago

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..

tabemann commented 3 weeks ago

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

bmentink commented 3 weeks ago

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

tabemann commented 3 weeks ago

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

bmentink commented 3 weeks ago

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

tabemann commented 3 weeks ago

On Fri, May 10, 2024 at 3:38 PM bmentink @.***> wrote:

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 of 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 ..

Currently I do not support the ADC FIFO, partly because the ADC API is currently essentially a lowest-common-denominator that also covers a number of STM32 microcontrollers (and partly because I have never had any projects which required more advanced control of the ADC). However, there is nothing stopping you from implementing this, especially because the ADC API as currently implemented does not use interrupts and thus would not be broken by writing your own ADC interface which does use the ADC FIFO interrupt. It would probably be better if you implemented it, actually, because you know exactly what your needs are, whereas I would just be guessing, which might not be helpful if you are working on a hard real-time project. Of course, I would be open to including your code in zeptoforth once you are done with it.

Travis

Message ID: @.***>

bmentink commented 3 weeks ago

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..

tabemann commented 3 weeks ago

On Fri, May 10, 2024 at 4:47 PM bmentink @.***> wrote:

Thanks, will do ...

Sorry for not offering more, but as you are doing hard real time that is an area where you likely have special needs for what you are doing, particularly if you are doing things on a per-PWM-clock basis.

Travis

bmentink commented 3 weeks ago

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?

tabemann commented 3 weeks ago

On Fri, May 10, 2024 at 7:14 PM bmentink @.***> wrote:

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

This requires the GNU arm-none-eabi toolchain, which is maintained by the people at ARM. I have no expectation that it will compile with any toolchain provided by Apple.

Travis

Message ID: @.***>

bmentink commented 3 weeks ago

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.

tabemann commented 2 weeks ago

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

bmentink commented 2 weeks ago

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

tabemann commented 2 weeks ago

On Sun, May 12, 2024, 23:33 bmentink @.***> wrote:

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?

The best way to do this in new code is to define INIT-FOO or like and do:

: init-foo ( -- ) \ your code here ;

initializer init-foo

This can be anywhere in your code and will work correctly both when compiled to flash and to RAM.

Travis

bmentink commented 2 weeks ago

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)

tabemann commented 2 weeks ago

On Mon, May 13, 2024, 17:59 bmentink @.***> wrote:

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 ?

DELAY-US specifically does not do a PAUSE by design, as it is meant for short, high-resolution delays.

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?

zeptoforth does not have FORGET by design (there are reasons for this), even though it has MARKER and CORNERSTONE for the flash dictionary (note that these will reboot the MCU).

Travis

bmentink commented 2 weeks ago

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?

tabemann commented 2 weeks ago

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.)

bmentink commented 2 weeks ago

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..

tabemann commented 2 weeks ago

On Tue, May 14, 2024 at 10:22 PM bmentink @.***> wrote:

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..

The development process is to first compile my code into RAM (which is the default), rebooting any time I run into an issue, and reloading my code into RAM again. Note that I hadn't thought of adding a FORGET for code in RAM in part because if something fails at this point, I normally treat the system as being in an undefined state, and I reboot to be on the safe side once I am done diagnosing the issue.

Then, once my code is finished, I issue COMPILE-TO-FLASH, compile my code (into flash), adding a CORNERSTONE to allow erasing more code compiled to flash after this code without disturbing this code, and then (this is important, because it is needed to ensure many things are initialized properly) rebooting.

Then I cycle back to my original state of compiling code to RAM to test more code.

Travis

bmentink commented 2 weeks ago

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

bmentink commented 1 week ago

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?

tabemann commented 1 week ago

On Mon, May 20, 2024 at 3:17 AM bmentink @.***> wrote:

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 4000rpm, it is a 100KVa motor.

Good to hear it worked for you!

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

I currently do not support any STM32Gxxx platforms at the present, as I have not seen any particular demand for them (so I have been focused for the last couple years on the RP2040, which has had by far the most demand). If you feel like investing the time in a port, though, I would welcome it!

Travis

Message ID: @.***>