slviajero / tinybasic

A BASIC interpreter for Arduino, ESP, RP2040, STM32, Infineon XMC and POSIX with IoT and microcontroller features.
GNU General Public License v3.0
203 stars 31 forks source link

Xmc1100 (xmc2go) Hardware Support #42

Closed devweblab closed 1 year ago

devweblab commented 1 year ago

Hi Stefan Cool project, Thank you for sharing. I have it now running on the xmc2go from infineon: https://www.infineon.com/cms/en/product/evaluation-boards/kit_xmc_2go_xmc1100_v1/ https://github.com/Infineon/XMC-for-Arduino For now Memory/Save is not working. Maybe it is possible to implement it in future with this: https://github.com/Infineon/mtb-example-xmc-flash-eeprom Feel free to include my changes from my branch (XMC1100_XMC2GO). Thank you and regards Florian

slviajero commented 1 year ago

Thank you! Very interesting! Just had a brief look on the code. Will look into this more deeply. Will sure include the platform. Thank you for contributing!

Am 22.12.2022 um 22:09 schrieb devweblab @.***>:

Hi Stefan Cool project, Thank you for sharing. I have it now running on the xmc2go from infineon: https://www.infineon.com/cms/en/product/evaluation-boards/kit_xmc_2go_xmc1100_v1/ https://www.infineon.com/cms/en/product/evaluation-boards/kit_xmc_2go_xmc1100_v1/ https://github.com/Infineon/XMC-for-Arduino https://github.com/Infineon/XMC-for-Arduino For now Memory/Save is not working. Maybe it is possible to implement it in future with this: https://github.com/Infineon/mtb-example-xmc-flash-eeprom https://github.com/Infineon/mtb-example-xmc-flash-eeprom Feel free to include my changes from my branch (XMC1100_XMC2GO). Thank you and regards Florian

You can view, comment on, or merge this pull request online at:

https://github.com/slviajero/tinybasic/pull/42 https://github.com/slviajero/tinybasic/pull/42 Commit Summary

04d4280 https://github.com/slviajero/tinybasic/pull/42/commits/04d4280283fc7b8cf1acff85da53d82b08029618 Update TinybasicArduino.ino d74de58 https://github.com/slviajero/tinybasic/pull/42/commits/d74de580788c9a31d563305a662a11ec405b9995 Update hardware-arduino.h File Changes (2 files https://github.com/slviajero/tinybasic/pull/42/files) M TinybasicArduino/TinybasicArduino.ino https://github.com/slviajero/tinybasic/pull/42/files#diff-0aff6a97b571b92625a281112a2134a5aa8bb13c2d01c1c9d8aac4de26a5d63f (2) M TinybasicArduino/hardware-arduino.h https://github.com/slviajero/tinybasic/pull/42/files#diff-f81f47c86629545e16b492a41574982f0a68427c4e8cc8c773686bcc797d1def (21) Patch Links:

https://github.com/slviajero/tinybasic/pull/42.patch https://github.com/slviajero/tinybasic/pull/42.patch https://github.com/slviajero/tinybasic/pull/42.diff https://github.com/slviajero/tinybasic/pull/42.diff — Reply to this email directly, view it on GitHub https://github.com/slviajero/tinybasic/pull/42, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACSY56ALQ3I2T27PRSTSDZLWOS7RTANCNFSM6AAAAAATHD3P6Q. You are receiving this because you are subscribed to this thread.

slviajero commented 1 year ago

I merged the two changes now in the master branch, but there are a few things I don't understand right now

MEMSIZE is set to 12k in the BASIC main file, but then again there is an autodetect of the memory later in hardware-arduino.h. Why is this done in the two places? The MEMSIZE directive will always override the autodetection. Does the autodetection not work?

delay(0) is disables in byield(). Is there a problem with delay(0) on this platform? Usually this can be very platform dependent. delay(0) on ESP is a true yield and needed on 8266. On AVR 8bit it is essentially nop. Is there anything special on the Infinineon platform?

pinMode is set to numerical values 0xc0UL, 0x80UL instead of INPUT/OUTPUT. I assume the macros INPUT and OUTPUT are not defined on the XMC?

devweblab commented 1 year ago

Wow, thank you very much.

I have not looked deeper into the MEMSIZE Problem. It worked automatically with another version made from Release 1.31. Needs further inverstigation: Prints "Stefan's Basic 1.4a Memory 129 0" instead of "Stefan's Basic 1.3 Memory 12000 0" when MEMSIZE not set.

Yes true, i think it is a problem with that platform. Unnfortuantely i cannot debug from arduino with jlink. But device hangs if delay is set to 0.

Maybe there is a better solution to do this. But PINM is not working with 0 and 1 (as defined in your code, not INPUT/OUTPUT i think), i had to use the numbers defined here https://github.com/Infineon/XMC-for-Arduino/blob/0dcbd5822cb59d12a7bdae776d307fae9c607ed7/cores/xmc_lib/XMCLib/inc/xmc1_gpio.h (XMC_GPIO_MODE_OUTPUT_PUSH_PULL and XMC_GPIO_MODE_OUTPUT_OPEN_DRAIN)

(I also found out that the RND/TRND function is not working, dont know why for now.)

slviajero commented 1 year ago

Wow, thank you very much.

I have not looked deeper into the MEMSIZE Problem. It worked automatically with another version made from Release 1.31. Needs further inverstigation: Prints "Stefan's Basic 1.4a Memory 129 0" instead of "Stefan's Basic 1.3 Memory 12000 0" when MEMSIZE not set.

I checked the code. There was one directive missing in the memory part. The version now in the repo has this fixed it should be able to detect the memory size automatically.

Yes true, i think it is a problem with that platform. Unnfortuantely i cannot debug from arduino with jlink. But device hangs if delay is set to 0

This is very strange. I looked at the core, it seems to be pretty standard but they have done a lot of odd things in the timing part. They use a systick mechanism instead of timers. Need to check this more.

Maybe there is a better solution to do this. But PINM is not working with 0 and 1 (as defined in your code, not INPUT/OUTPUT i think), i had to use the numbers defined here https://github.com/Infineon/XMC-for-Arduino/blob/0dcbd5822cb59d12a7bdae776d307fae9c607ed7/cores/xmc_lib/XMCLib/inc/xmc1_gpio.h https://github.com/Infineon/XMC-for-Arduino/blob/0dcbd5822cb59d12a7bdae776d307fae9c607ed7/cores/xmc_lib/XMCLib/inc/xmc1_gpio.h (XMC_GPIO_MODE_OUTPUT_PUSH_PULL and XMC_GPIO_MODE_OUTPUT_OPEN_DRAIN)

I rewrote this as well. It might work now.

(I also found out that the RND/TRND function is not working, dont know why for now.)

Can you tell me what exactly does not work? I checked rnd on the Seeduino Xiao which is the same CPU and it works fine.

Currently I don’t have a board to check this. Will probably have one after Christmas. If you find the time, could you please check the code in the repo right now and give me feedback?

Best, Stefan

devweblab commented 1 year ago

The memory detection works now. Thank you very much! Stefan's Basic 1.4a Memory 10343 0

No, the PINM Function does not work anymore. The Device is hanging after calling it.

Here the output of the RND command. Or am I doing something wrong?

RND(100) Syntax Error TRND(100) Syntax Error

With delay(0) the output after start is only:

S

I bought the board on mouser (cheapest i think?). I wrote them because the datasheet is wrong. It has only 32kB Flash instead of 64kB. So if you order one - there are differen Versions with 32 or 64 kB (see newer Datasheets) (For FLOAT the 64kB Version would be needed.) And no, the Seeduino XIAO is a SAMD21 (Atmel) and the XMC is a XMC1100 (Infineon) as far as i can remember. But cortex/arm, etc (I use the XIAO for cmsis and micropython) so you are correct, mostly identical. The infineon xmc-arduino is different/special i think.

Happy christmas

slviajero commented 1 year ago

Am 23.12.2022 um 18:15 schrieb devweblab @.***>:

The memory detection works now. Thank you very much! Stefan's Basic 1.4a Memory 10343 0

Good! Thank you! The 10343 is probably very convervative. I used the 4k safety margin of the other 32 bit platforms. Without much subsystems, one would probably be good with 12 kB.

No, the PINM Function does not work anymore. The Device is hanging after calling it.

Ok! This means they have not properly ported the INPUT and OUTPUT macros. I could not find them in the core headers. Interestingly, I just checked this on the XIAO and it also doesn’t work - controller hangs after PINM. On the MKR it works.

Here the output of the RND command. Or am I doing something wrong?

RND(100) Syntax Error TRND(100) Syntax Error

Ah, ok. RND is a function not a command.

A=RND(100)

should work. To set the random number seed, RND cannot be used. There is a special variable for it.

@R= would set the random number seed. @R will always contain the next integer the random number generator will use. This is portable across platforms as a very simple 16 bit random number generator is built in.

With delay(0) the output after start is only:

S

Ok! I look into the core code a bit. This means that also delay() is not properly ported.

I bought the board on mouser (cheapest i think?). I wrote them because the datasheet is wrong. It has only 32kB Flash instead of 64kB. So if you order one - there are differen Versions with 32 or 64 kB (see newer Datasheets) (For FLOAT the 64kB Version would be needed.)

I ordered from Mouser. A 64. Hope I will get one.

And no, the Seeduino XIAO is a SAMD21 (Atmel) and the XMC is a XMC1100 (Infineon) as far as i can remember. But cortex/arm, etc (I use the XIAO for cmsis and micropython) so you are correct, mostly identical. The infineon xmc-arduino is different/special i think

What I meant is that it looked to me at first glance, that the XMC1100 core looks like the XIAO- Suspected that they took it because both are ARM cortex M0. As the PINM bug seems to be the same, I assume I am not completely wrong. Delay, however, works on the Xiao as delay(0).

Best Regards, Merry Christmas!

slviajero commented 1 year ago

PS: just made a bug fix for pinmode, code had a stupid mistake,

Am 23.12.2022 um 18:15 schrieb devweblab @.***>:

The memory detection works now. Thank you very much! Stefan's Basic 1.4a Memory 10343 0

No, the PINM Function does not work anymore. The Device is hanging after calling it.

Here the output of the RND command. Or am I doing something wrong?

RND(100) Syntax Error TRND(100) Syntax Error

With delay(0) the output after start is only:

S

I bought the board on mouser (cheapest i think?). I wrote them because the datasheet is wrong. It has only 32kB Flash instead of 64kB. So if you order one - there are differen Versions with 32 or 64 kB (see newer Datasheets) (For FLOAT the 64kB Version would be needed.) And no, the Seeduino XIAO is a SAMD21 (Atmel) and the XMC is a XMC1100 (Infineon) as far as i can remember. But cortex/arm, etc (I use the XIAO for cmsis and micropython) so you are correct, mostly identical. The infineon xmc-arduino is different/special i think.

Happy christmas

— Reply to this email directly, view it on GitHub https://github.com/slviajero/tinybasic/pull/42#issuecomment-1364126100, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACSY56CSW35GZKVTGQYAWFLWOXM4LANCNFSM6AAAAAATHD3P6Q. You are receiving this because you modified the open/close state.

devweblab commented 1 year ago

Yes, the memory detection is perfect. Ok, now the RND does work, my fault, thanks for clarification. And also the PINM works now! Ok, yes you are correct, cortex-m0 and the xiao is cortex-m0+. So i will try some examples now and have fun. Very cool! Thank you again. Yes, hopefully a 64kB. I ordered the 64kB too and received the 32kB.

devweblab commented 1 year ago

Found out why it is not working with delay(0). setInterval() does set the interval of the task to 0: https://github.com/Infineon/XMC-for-Arduino/blob/0dcbd5822cb59d12a7bdae776d307fae9c607ed7/cores/wiring_time.c#L229 startTask() does check if the interval is 0 and return -2 instead of starting the task. https://github.com/Infineon/XMC-for-Arduino/blob/0dcbd5822cb59d12a7bdae776d307fae9c607ed7/cores/wiring_time.c#L505 So not sure if that is a bug or a feature ;)

slviajero commented 1 year ago

Very interesting! They did not bother to check for the delay(0) case. AVR always checks if 0 and then returns with „no operation“. The reason why the delay(0) is there is ESP8266 which does

void __delay(unsigned long ms) { if(ms) { os_timer_setfn(&delay_timer, (os_timer_func_t*) &delay_end, 0); os_timer_arm(&delay_timer, ms, ONCE); } else { esp_schedule(); } esp_yield(); if(ms) { os_timer_disarm(&delay_timer); } }

Delay(0) calls esp_schedule() to activate the scheduler of background tasks and then esp_yield() to give these background tasks the chance to run. Without this, an ESP8266 crashes once enough I/O buffers have been filled. It took me a long time to find this out and get I/O with BASIC on an ESP8266 stable.

I checked the other platforms, XMC seems to be the only one with this behaviour of blocking on delay(0). So your #ifdef … #endif makes sense. Probably I could just as well change if to #ifdef ESP8266 #endif but I don’t dare to touch this right now.

Best, Stefan

Am 23.12.2022 um 19:54 schrieb devweblab @.***>:

Found out why it is not working with delay(0). setInterval() does set the interval of the task to 0: https://github.com/Infineon/XMC-for-Arduino/blob/0dcbd5822cb59d12a7bdae776d307fae9c607ed7/cores/wiring_time.c#L229 https://github.com/Infineon/XMC-for-Arduino/blob/0dcbd5822cb59d12a7bdae776d307fae9c607ed7/cores/wiring_time.c#L229 startTask() does check if the interval is 0 and return -2 instead of starting the task. https://github.com/Infineon/XMC-for-Arduino/blob/0dcbd5822cb59d12a7bdae776d307fae9c607ed7/cores/wiring_time.c#L505 https://github.com/Infineon/XMC-for-Arduino/blob/0dcbd5822cb59d12a7bdae776d307fae9c607ed7/cores/wiring_time.c#L505 So not sure if that is a bug or a feature ;)

— Reply to this email directly, view it on GitHub https://github.com/slviajero/tinybasic/pull/42#issuecomment-1364192335, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACSY56ERWNVH2LBEQVPOODDWOXYOBANCNFSM6AAAAAATHD3P6Q. You are receiving this because you modified the open/close state.

devweblab commented 1 year ago

Interesting, thanks for the explanation. Yes, such problems with porting/microcontroller can take a lot research and time. This basic is really cool and good hardware abstraction layer. Now i can do something with the device. Just for information - found that not all examples are working. For example DIM in animal.bas: 70: Args Error I will test/play/investigate more.

slviajero commented 1 year ago

Am 23.12.2022 um 20:56 schrieb devweblab @.***>:

Interesting, thanks for the explanation. Yes, such problems with porting/microcontroller can take a lot research and time. This basic is really cool and good hardware abstraction layer. Now i can do something with the device. Just for information - found that not all examples are working. For example DIM in animal.bas: 70: Args Error I will test/play/investigate more.

Are you using BASICSIMPLE as language set? BASICSIMPLE has no string arrays and animal.bas needs this. BASICINTEGER would have string arrays. More specific, it is the HASMULTIDIM and the HASSTRINGARRAYS setting that you need.

slviajero commented 1 year ago

PS: if you need storage, consider an external I2C EEPROM. 4k and 32k models are built-in. Simply connect it to SDA and SCL and compile with ARDUINOI2CEEPROM. If you have a 32k model, you could also use ARDUINOEFS. With this, the EEPROM has multiple files.

Am 23.12.2022 um 20:56 schrieb devweblab @.***>:

Interesting, thanks for the explanation. Yes, such problems with porting/microcontroller can take a lot research and time. This basic is really cool and good hardware abstraction layer. Now i can do something with the device. Just for information - found that not all examples are working. For example DIM in animal.bas: 70: Args Error I will test/play/investigate more.

— Reply to this email directly, view it on GitHub https://github.com/slviajero/tinybasic/pull/42#issuecomment-1364278555, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACSY56FLCU4RYWZ4NCIFY33WOX7XVANCNFSM6AAAAAATHD3P6Q. You are receiving this because you modified the open/close state.

devweblab commented 1 year ago

Yeah, found out that. I forgot to change that after checkout the new version form github. Multidimensional is working fine. Nice tip with the eeprom. I think i have a little i2c eeprom (256kbit), maybe i will try that. (But i would prefere saving to flash.)

I know basic from the C64/vice/frodo and some other interpreters. I ported the SAM (Simple Assembler and Monitor) for this project https://github.com/Schuemi/c64-go With that you can manipulate/control/watch the cpu/emulator directly.

Is there a way to write to registers in tinybasic? For example in https://github.com/billroy/bitlash there is a simple function to set AVR registers with inb() and outb(). (Like peek/poke on the Commodore 64 are) numvar func_inb(void) { reqargs(1); return (volatile byte ) arg1; } numvar func_outb(void) { reqargs(2); (volatile byte ) arg1 = (byte) arg2; return 0;} As far as i see and read in the documentation you protected the program space and limit access with peek/poke to the memory only? So maybe better a seperate evil function for doing that?

slviajero commented 1 year ago

Yeah, found out that. I forgot to change that after checkout the new version form github. Multidimensional is working fine. Nice tip with the eeprom. I think i have a little i2c eeprom (256kbit), maybe i will try that. (But i would prefere saving to flash.)

The fun part is that the EEPROMs can be exchanged at runtime just like the program modules of the old times.

I know basic from the C64/vice/frodo and some other interpreters. I ported the SAM (Simple Assembler and Monitor) for this project https://github.com/Schuemi/c64-go https://github.com/Schuemi/c64-go With that you can manipulate/control/watch the cpu/emulator directly.

Nice! I never programmed much on C64 but the BASIC was fairly powerful. Had an Amstrad with Locomotive BASIC. In my view the best BASIC implementation ever.

Is there a way to write to registers in tinybasic? For example in https://github.com/billroy/bitlash https://github.com/billroy/bitlash there is a simple function to set AVR registers with inb() and outb(). (Like peek/poke on the Commodore 64 are) numvar func_inb(void) { reqargs(1); return (volatile byte ) arg1; } numvar func_outb(void) { reqargs(2); (volatile byte ) arg1 = (byte) arg2; return 0;} As far as i see and read in the documentation you protected the program space and limit access with peek/poke to the memory only? So maybe better a seperate evil function for doing that?

The easiest way is to use the USR function. BASIC syntax is A=USR(N, V). N is the function number and V is a value. In BASIC it ends up in xusr where N becomes the signed integer arg while V becomes the address_t i.e. unsigned integer fn. Arg then addresses a large switch(arg). If you want to use this, you should use N values from 32 onwards. They are reserved for user defined functions. Important: the function must return a value by pushing it to the stack. If you don’t want to return a value, simply push 0.

You can of course give an address into V. One could do

A$=„This is my stuff“ R=USR(32, FIND(A$))

FIND(A$) gives the heap address of A$ and then the function in xusr can use this to access data. This would be a possible evil way of doing it without changing a lot in BASIC.

Alternatively, you can use a special variable. They start with @ and also execute commands. The magic happens in getvar and setvar. Look at the display code in these function for an example how to do this. I recommend to use the letter U, i.e. @U for this. BASIC Syntax would simply

@U=10 or @.***

One calls getvar() and the other setvar().

There is also a special string variable prepared for this. This is @X$. The code is already in BASIC. Every time you access the string makemyxstring() is called and the result returned to BASIC. This is only good for read. I.e. you can feed data into sbuffer but you can’t transfer anything into it. Please read the comments of this functions carefully in the code. It is a bit mean as the same string operation can call makemyxstring() several times.

Best, Stefan

slviajero commented 1 year ago

PS: mixed it up, in xusr arg is the second argument of USR and fn the first. The first is the function number.

Am 24.12.2022 um 08:54 schrieb devweblab @.***>:

Yeah, found out that. I forgot to change that after checkout the new version form github. Multidimensional is working fine. Nice tip with the eeprom. I think i have a little i2c eeprom (256kbit), maybe i will try that. (But i would prefere saving to flash.)

I know basic from the C64/vice/frodo and some other interpreters. I ported the SAM (Simple Assembler and Monitor) for this project https://github.com/Schuemi/c64-go https://github.com/Schuemi/c64-go With that you can manipulate/control/watch the cpu/emulator directly.

Is there a way to write to registers in tinybasic? For example in https://github.com/billroy/bitlash https://github.com/billroy/bitlash there is a simple function to set AVR registers with inb() and outb(). (Like peek/poke on the Commodore 64 are) numvar func_inb(void) { reqargs(1); return (volatile byte ) arg1; } numvar func_outb(void) { reqargs(2); (volatile byte ) arg1 = (byte) arg2; return 0;} As far as i see and read in the documentation you protected the program space and limit access with peek/poke to the memory only? So maybe better a seperate evil function for doing that?

— Reply to this email directly, view it on GitHub https://github.com/slviajero/tinybasic/pull/42#issuecomment-1364482186, or unsubscribe https://github.com/notifications/unsubscribe-auth/ACSY56EHG5VIXVWTOMGGXMLWO2T3TANCNFSM6AAAAAATHD3P6Q. You are receiving this because you modified the open/close state.

devweblab commented 1 year ago

Ah, super idea to use the eeprom like a drive/storage :) I also like the old simple/direct systems. Very interesting the Locomotive BASIC, new for me. Have to study everything you wrote and make some test, read documentation, etc Thank you very much for the detailed explanation!

devweblab commented 1 year ago

And with lego lines i learned to control simple things. See http://lukazi.blogspot.com/2014/07/lego-legos-first-programmable-product.html :) Running on the C64 and intel 286.