From: Enoch <ix...@ho...> - 2013-02-13 04:39:04
|
Hello Matthias and all, I'd like to see this forum also offering code snippets, so here's my first humble attempt of harnessing the atomic bit manipulation instructions. : port:hi ( portadr bitno -- ) \ SBI swap $20 - 3 lshift or $9A00 or code , end-code ; : port:lo ( portadr bitno -- ) \ CBI swap $20 - 3 lshift or $9800 or code , end-code ; example: PORTB 7 port:hi green.hi PORTB 7 port:lo green.lo Thanks, Enoch. |
From: Enoch <ix...@ho...> - 2013-02-13 05:21:21
|
I guess that to make it into Matthias recipe book I have to add input testing and perhaps more... : _bitio dup $1F U> if &-9 throw then over $7 U> if &-9 throw then ; : port:hi ( portadr bitno -- ) \ SBI swap $20 - _bitio 3 lshift or $9A00 or code , end-code ; : port:lo ( portadr bitno -- ) \ CBI swap $20 - _bitio 3 lshift or $9800 or code , end-code ; Enoch <ix...@ho...> writes: > Hello Matthias and all, > > I'd like to see this forum also offering code snippets, so here's my > first humble attempt of harnessing the atomic bit manipulation > instructions. > > : port:hi ( portadr bitno -- ) \ SBI > swap $20 - 3 lshift or $9A00 or code , end-code > ; > > : port:lo ( portadr bitno -- ) \ CBI > swap $20 - 3 lshift or $9800 or code , end-code > ; > > example: > > PORTB 7 port:hi green.hi > PORTB 7 port:lo green.lo > > Thanks, Enoch. > > > > > ------------------------------------------------------------------------------ > Free Next-Gen Firewall Hardware Offer > Buy your Sophos next-gen firewall before the end March 2013 > and get the hardware for free! Learn more. > http://p.sf.net/sfu/sophos-d2d-feb |
From: Matthias T. <mt...@we...> - 2013-02-14 19:14:26
|
hi Enoch, > I'd like to see this forum also offering code snippets, so here's my > first humble attempt of harnessing the atomic bit manipulation > instructions. > > : port:hi ( portadr bitno -- ) \ SBI > swap $20 - 3 lshift or $9A00 or code , end-code Did you actually test this code? CODE is a parsing word that starts a new dictionary entry. There is currently no way to switch between forth and machine code (that would be ;CODE btw) Puzzled Matthias |
From: Michael K. <mi-...@t-...> - 2013-02-14 22:40:03
|
Hi Matthias. ... > There is currently no > way to switch between forth and machine code (that would > be ;CODE btw) You may go from low to high level and back: code <name> (some code) ; -- jump to high level: ldi XL,low(pfa_forthISR) ldi XH,high(pfa_forthISR) jmp DO_NEXT pfa_forthISR: .dw XT_MAINWORD ; -- back to low level: .dw PC+1 ; next IP .dw PC+1 ; next cfa (more code ) end-code But be shure to save all registers you use if you do so. --- Enochs code is a macro, assembling one single instruction SBI into dictionary and naming it. Calling that word will execute the SBI instruction. Michael Am 14.02.2013 um 20:14 schrieb Matthias Trute: > hi Enoch, > > >> I'd like to see this forum also offering code snippets, so here's my >> first humble attempt of harnessing the atomic bit manipulation >> instructions. >> >> : port:hi ( portadr bitno -- ) \ SBI >> swap $20 - 3 lshift or $9A00 or code , end-code > > Did you actually test this code? CODE is a parsing word > that starts a new dictionary entry. There is currently no > way to switch between forth and machine code (that would > be ;CODE btw) > > Puzzled > Matthias > > > ---------------------------------------------------------------------- > -------- > Free Next-Gen Firewall Hardware Offer > Buy your Sophos next-gen firewall before the end March 2013 > and get the hardware for free! Learn more. > http://p.sf.net/sfu/sophos-d2d-feb > _______________________________________________ > Amforth-devel mailing list for http://amforth.sf.net/ > Amf...@li... > https://lists.sourceforge.net/lists/listinfo/amforth-devel |
From: Enoch <ix...@ho...> - 2013-02-15 00:47:29
|
"Michael Kalus" <mi-...@t-...> writes: > Hi Matthias. > > ... >> There is currently no >> way to switch between forth and machine code (that would >> be ;CODE btw) > > > You may go from low to high level and back: > > code <name> > (some code) > ; -- jump to high level: > ldi XL,low(pfa_forthISR) > ldi XH,high(pfa_forthISR) > jmp DO_NEXT > pfa_forthISR: > .dw XT_MAINWORD > ; -- back to low level: > .dw PC+1 ; next IP > .dw PC+1 ; next cfa > (more code ) > end-code > > But be shure to save all registers you use if you do so. > > --- > > Enochs code is a macro, assembling one single instruction SBI into > dictionary and naming it. > Calling that word will execute the SBI instruction. > > Michael I confirm, the code works. I was not aware we have ;code as in other implementations. The idea came when examining lib/assembler-test.frt I suggest that these simple macros would become standard library offerings. Without these atomic bit set/clear one needs to wrap code by -int/+int if register bits are shared by different interrupt routines. In my current project (at90can128 based) the AVR also has a recommended general purpose register, GPIOR0 [0x1E (0x3E)], for this very purpose. Thank you, Enoch. ---------------------------------------------------------------------- : _bitio dup $1F U> if &-9 throw then over $7 U> if &-9 throw then ; : port:hi! ( portadr bitno -- ) \ SBI swap $20 - _bitio 3 lshift or $9A00 or code , end-code ; : port:lo! ( portadr bitno -- ) \ CBI swap $20 - _bitio 3 lshift or $9800 or code , end-code ; ---------------------------------------------------------------------- > > > > > Am 14.02.2013 um 20:14 schrieb Matthias Trute: > >> hi Enoch, >> >> >>> I'd like to see this forum also offering code snippets, so here's my >>> first humble attempt of harnessing the atomic bit manipulation >>> instructions. >>> >>> : port:hi ( portadr bitno -- ) \ SBI >>> swap $20 - 3 lshift or $9A00 or code , end-code >> >> Did you actually test this code? CODE is a parsing word >> that starts a new dictionary entry. There is currently no >> way to switch between forth and machine code (that would >> be ;CODE btw) >> >> Puzzled >> Matthias >> >> >> ---------------------------------------------------------------------- >> -------- >> Free Next-Gen Firewall Hardware Offer >> Buy your Sophos next-gen firewall before the end March 2013 >> and get the hardware for free! Learn more. >> http://p.sf.net/sfu/sophos-d2d-feb >> _______________________________________________ >> Amforth-devel mailing list for http://amforth.sf.net/ >> Amf...@li... >> https://lists.sourceforge.net/lists/listinfo/amforth-devel > > > ------------------------------------------------------------------------------ > Free Next-Gen Firewall Hardware Offer > Buy your Sophos next-gen firewall before the end March 2013 > and get the hardware for free! Learn more. > http://p.sf.net/sfu/sophos-d2d-feb |
From: Matthias T. <mt...@we...> - 2013-02-15 18:41:28
|
Hi Enoch, >> Enochs code is a macro, assembling one single instruction SBI into >> dictionary and naming it. >> Calling that word will execute the SBI instruction. >> >> Michael > > I confirm, the code works. Well. I think its definitly worth some documentation. It is not obvious how to use it. > I suggest that these simple macros would become standard library > offerings. I'll think about it. see above ;) > Without these atomic bit set/clear one needs to wrap code by > -int/+int if register bits are shared by different interrupt > routines. Any given and active forth ISR is never interrupted itself by another interrupt. The communication between ISR and the main program is close but different (IMHO). Matthias |
From: Enoch <ix...@ho...> - 2013-02-15 19:23:37
|
Matthias Trute <mt...@we...> writes: Hello Matthias, > Hi Enoch, > >>> Enochs code is a macro, assembling one single instruction SBI into >>> dictionary and naming it. >>> Calling that word will execute the SBI instruction. >>> >>> Michael >> >> I confirm, the code works. > > Well. I think its definitly worth some documentation. It is > not obvious how to use it. Easy: Suppose we have a relay connected to PORTA.0 PORTA 0 port:hi! relay_on PORTA 0 port:lo! relay_off We can do the same of-course via bitnames.frt but the above is accomplished through a single instruction. BTW, bitnames.frt, IMO, needs to be simplifed in two respects: 1. It is extremely rare for a port to be of bidirectional use. 2. Port address can be limited to 0..255. My own version follows: ---------------------------------------------------------------------- \ define a port: 0 ≤ portadr ≤ $FF, 0 ≤ bitno ≤ 7. : port: create ( portadr bitno -- ) 1 swap lshift \ make it a bitmask >< or , \ mask at high byte does> ( -- portmask portadr ) @i dup >< $ff and swap $ff and ; : hi? ( portmask portadr -- f ) c@ and 0> ; : lo? ( portmask portadr -- f ) c@ and 0= ; synonym port@ hi? : hi! ( portmask portadr -- ) dup >r c@ or r> c! ; : lo! ( portmask portadr -- ) dup >r c@ swap invert and r> c! ; : port! ( portmask portadr f -- ) if hi! else lo! then ; : toggle ( portmask portadr -- ) over over lo? port! ; \ PORTx.y is output : out! ( portmask portadr -- ) 1- hi! ; \ PINx.y is input : in! ( portmask portadr -- ) 1+ lo! ; ---------------------------------------------------------------------- >> I suggest that these simple macros would become standard library >> offerings. > > I'll think about it. see above ;) > >> Without these atomic bit set/clear one needs to wrap code by >> -int/+int if register bits are shared by different interrupt >> routines. > > Any given and active forth ISR is never interrupted itself by > another interrupt. The communication between ISR and the > main program is close but different (IMHO). That's no good. Interrupt routines MUST BE interruptible or otherwise they would introduce unacceptable latency. For example, suppose we are doing some signal processing and we need to take A/D samples at regular intervals... By the way, let the programmer worry about avoiding re-entrancy. The docs gave me the impression that this is the case... i.e., until the T flag is set the interrupt system is off but later we invoke the interrupt service word just as usual... I'll have to visit your asm code :-( If the above is corrected the importance of those atomic (uninterruptible) SBI/CBI instructions becomes clear. Thanks, Enoch. > Matthias > > > ------------------------------------------------------------------------------ > The Go Parallel Website, sponsored by Intel - in partnership with Geeknet, > is your hub for all things parallel software development, from weekly thought > leadership blogs to news, videos, case studies, tutorials, tech docs, > whitepapers, evaluation guides, and opinion stories. Check out the most > recent posts - join the conversation now. http://goparallel.sourceforge.net/ |
From: Matthias T. <mt...@we...> - 2013-02-16 17:53:08
|
Hi Enoch, >> Well. I think its definitly worth some documentation. It is >> not obvious how to use it. > > Easy: > > Suppose we have a relay connected to PORTA.0 > > PORTA 0 port:hi! relay_on > PORTA 0 port:lo! relay_off ok. Now I understand what you intent. I think that your code is a pretty good example to demonstrate how to use machine code without loading the full assembler. > BTW, bitnames.frt, IMO, needs to be simplifed in two respects: > 1. It is extremely rare for a port to be of bidirectional use. I've recently came across 1-wire devices. They switch very frequently. > 2. Port address can be limited to 0..255. That is what earlier releases had. Now look at the ardiuno Mega devices and what can we find there? PORTJ (261) and PORTK (264). >> Any given and active forth ISR is never interrupted itself by >> another interrupt. The communication between ISR and the >> main program is close but different (IMHO). > > That's no good. Interrupt routines MUST BE interruptible or otherwise > they would introduce unacceptable latency. Interrupts are per se not interruptable, guess why the I flag is cleared upon ISR start. A programmer may re-enable interrupts within the ISR, but that's up to him/her. > By the way, let the programmer worry about avoiding re-entrancy. If (s)he takes care of re-entrancy (s)he will be capable to enable it properly. I'm sure. The other way is far more troublesome. Matthias |
From: Enoch <ix...@ho...> - 2013-02-15 21:09:25
|
Enoch <ix...@ho...> writes: > Matthias Trute <mt...@we...> writes: > > Hello Matthias, > >> Hi Enoch, >> >>>> Enochs code is a macro, assembling one single instruction SBI into >>>> dictionary and naming it. >>>> Calling that word will execute the SBI instruction. >>>> >>>> Michael >>> >>> I confirm, the code works. >> >> Well. I think its definitly worth some documentation. It is >> not obvious how to use it. > > Easy: > > Suppose we have a relay connected to PORTA.0 > > PORTA 0 port:hi! relay_on > PORTA 0 port:lo! relay_off > > We can do the same of-course via bitnames.frt but the above is > accomplished through a single instruction. > > BTW, bitnames.frt, IMO, needs to be simplifed in two respects: > 1. It is extremely rare for a port to be of bidirectional use. > 2. Port address can be limited to 0..255. > > My own version follows: > > ---------------------------------------------------------------------- > > \ define a port: 0 ≤ portadr ≤ $FF, 0 ≤ bitno ≤ 7. > : port: create ( portadr bitno -- ) > 1 swap lshift \ make it a bitmask > >< or , \ mask at high byte > does> ( -- portmask portadr ) > @i dup >< $ff and swap $ff and > ; > > : hi? ( portmask portadr -- f ) > c@ and 0> > ; > > : lo? ( portmask portadr -- f ) > c@ and 0= > ; > > synonym port@ hi? > > : hi! ( portmask portadr -- ) > dup >r c@ or r> c! > ; > > : lo! ( portmask portadr -- ) > dup >r c@ swap invert and r> c! > ; > > : port! ( portmask portadr f -- ) > if hi! else lo! then > ; > > : toggle ( portmask portadr -- ) > over over lo? port! > ; > > \ PORTx.y is output > : out! ( portmask portadr -- ) > 1- hi! > ; > > \ PINx.y is input > : in! ( portmask portadr -- ) > 1+ lo! > ; > > ---------------------------------------------------------------------- > >>> I suggest that these simple macros would become standard library >>> offerings. >> >> I'll think about it. see above ;) >> >>> Without these atomic bit set/clear one needs to wrap code by >>> -int/+int if register bits are shared by different interrupt >>> routines. >> >> Any given and active forth ISR is never interrupted itself by >> another interrupt. The communication between ISR and the >> main program is close but different (IMHO). > > That's no good. Interrupt routines MUST BE interruptible or otherwise > they would introduce unacceptable latency. For example, suppose we are > doing some signal processing and we need to take A/D samples at regular > intervals... By the way, let the programmer worry about avoiding re-entrancy. Sorry, correction: Re-enabling the interrupt system inside the interrupt routine is the programmer's responsibility (after clearing the appropriate interrupt flag, of-course). Thanks, Enoch. > The docs gave me the impression that this is the case... i.e., until the > T flag is set the interrupt system is off but later we invoke the > interrupt service word just as usual... > I'll have to visit your asm code :-( > > If the above is corrected the importance of those atomic > (uninterruptible) SBI/CBI instructions becomes clear. > > Thanks, Enoch. > >> Matthias >> >> >> ------------------------------------------------------------------------------ >> The Go Parallel Website, sponsored by Intel - in partnership with Geeknet, >> is your hub for all things parallel software development, from weekly thought >> leadership blogs to news, videos, case studies, tutorials, tech docs, >> whitepapers, evaluation guides, and opinion stories. Check out the most >> recent posts - join the conversation now. http://goparallel.sourceforge.net/ > > > ------------------------------------------------------------------------------ > The Go Parallel Website, sponsored by Intel - in partnership with Geeknet, > is your hub for all things parallel software development, from weekly thought > leadership blogs to news, videos, case studies, tutorials, tech docs, > whitepapers, evaluation guides, and opinion stories. Check out the most > recent posts - join the conversation now. http://goparallel.sourceforge.net/ > _______________________________________________ > Amforth-devel mailing list for http://amforth.sf.net/ > Amf...@li... > https://lists.sourceforge.net/lists/listinfo/amforth-devel |
From: Erich W. <ew....@na...> - 2013-02-20 08:01:46
|
Hi Enoch, since you asked for comments ... On 02/13/2013 05:38 AM, Enoch wrote: > Hello Matthias and all, > > I'd like to see this forum also offering code snippets, so here's my > first humble attempt of harnessing the atomic bit manipulation > instructions. > > : port:hi ( portadr bitno -- ) \ SBI > swap $20 - 3 lshift or $9A00 or code , end-code > ; > > : port:lo ( portadr bitno -- ) \ CBI > swap $20 - 3 lshift or $9800 or code , end-code > ; > > example: > > PORTB 7 port:hi green.hi > PORTB 7 port:lo green.lo > So you want to set or clear a bit in some register. What is wrong with the words found in bitnames.frt? include lib/bitnames.frt PORTB 7 portpin: green and later green pin_output green high \ do something here green low Sure, bitnames is doing read+modify+write on the memory mapped location of the register, while your solution uses sbi/cbi which does not work on the memory mapped location (hence $20 - ). But what exactly is better with using sbi/cbi? That sbi/cbi cannot be interrupted once the instruction is executing? But all the instructions leading up to the sbi/cbi can be interrupted, can't they? Do I miss the entire motivation of the code snippet? Would you dare to enlighten me?? As Matthias pointed out elsewhere: your snippet is intersting, because assembly instructions are coded in at compile time without loading the full assembler. That I can see. Cheers, Erich |
From: Enoch <ix...@ho...> - 2013-02-20 08:49:05
|
Erich Waelde <ew....@na...> writes: > Hi Enoch, > > since you asked for comments ... I certainly do! > On 02/13/2013 05:38 AM, Enoch wrote: >> Hello Matthias and all, >> >> I'd like to see this forum also offering code snippets, so here's my >> first humble attempt of harnessing the atomic bit manipulation >> instructions. >> >> : port:hi ( portadr bitno -- ) \ SBI >> swap $20 - 3 lshift or $9A00 or code , end-code >> ; >> >> : port:lo ( portadr bitno -- ) \ CBI >> swap $20 - 3 lshift or $9800 or code , end-code >> ; >> >> example: >> >> PORTB 7 port:hi green.hi >> PORTB 7 port:lo green.lo >> > > So you want to set or clear a bit in some register. > > What is wrong with the words found in bitnames.frt? > > include lib/bitnames.frt > PORTB 7 portpin: green > > and later > > green pin_output > green high > \ do something here > green low SBI/CBI can change bits in the 0..31 I/O range without needing a -int / +int protection. avr-gcc, for example, would use SBI when compiling PORTA |= _BV(0); > Sure, bitnames is doing read+modify+write on the memory mapped > location of the register, while your solution uses sbi/cbi which > does not work on the memory mapped location (hence $20 - ). > But what exactly is better with using sbi/cbi? That sbi/cbi > cannot be interrupted once the instruction is executing? But > all the instructions leading up to the sbi/cbi can be > interrupted, can't they? Do I miss the entire motivation of > the code snippet? Would you dare to enlighten me?? Well, let's try the following indirect argument: Atmel thought these instructions to be important enough to "spend" 2^10 opcodes out of their precious 2^16 RISC range. Don't we need to respect that engineering decision by suitable Amforth words? > As Matthias pointed out elsewhere: your snippet is intersting, > because assembly instructions are coded in at compile time > without loading the full assembler. That I can see. Yes, that DIY assembly approach can do things which lib/assembler.frt may find difficult to follow :-) Regards, Enoch. > > Cheers, > Erich > > ------------------------------------------------------------------------------ > Everyone hates slow websites. So do we. > Make your web apps faster with AppDynamics > Download AppDynamics Lite for free today: > http://p.sf.net/sfu/appdyn_d2d_feb |
From: Matthias T. <mt...@we...> - 2013-02-20 18:35:35
|
Hi Enoch, > Well, let's try the following indirect argument: > > Atmel thought these instructions to be important enough to "spend" 2^10 > opcodes out of their precious 2^16 RISC range. Don't we need to respect > that engineering decision by suitable Amforth words? No, we don't. Sounds too harsh? Well, yes. Atmel did a lot of at least strange design decisions, that later (for the atxmega line) got changed. The IO area with 32 possible addresses was fine for the very first controllers, but became later a real bottleneck. >> As Matthias pointed out elsewhere: your snippet is intersting, >> because assembly instructions are coded in at compile time >> without loading the full assembler. That I can see. > > Yes, that DIY assembly approach can do things which lib/assembler.frt > may find difficult to follow :-) Your SBI/CBI macros are an excellent and inspiring solution for a particular problem. I think it really deserves to be published. As a recipe in the cookbook. There are quite a few solutions, that do not go into the repository and are worth studying. I do hope, you can live with that. It has the advantage to have documentation and implementation in one document. The code in the lib/ directory is not that well documented. Matthias |
From: Matthias T. <mt...@we...> - 2013-02-20 19:40:28
|
Hi, > Your SBI/CBI macros are an excellent and inspiring solution for a > particular problem. I think it really deserves to be published. > As a recipe in the cookbook. A rough first shot is online: http://amforth.sourceforge.net/TG/recipes/Efficient-Bitmanipulation.html It will get links and much more text. But not tonight.. Matthias |
From: Enoch <ix...@ho...> - 2013-02-20 19:35:00
|
Hello Matthias, Matthias Trute <mt...@we...> writes: > Hi Enoch, > >> Well, let's try the following indirect argument: >> >> Atmel thought these instructions to be important enough to "spend" 2^10 >> opcodes out of their precious 2^16 RISC range. Don't we need to respect >> that engineering decision by suitable Amforth words? > > No, we don't. Sounds too harsh? Well, yes. Atmel did a lot of > at least strange design decisions, that later (for the atxmega > line) got changed. The IO area with 32 possible addresses was > fine for the very first controllers, but became later a real > bottleneck. Personally, if my Flash memory requirements would go beyond 128KB (64KW) I will choose a different µC architecture. > >>> As Matthias pointed out elsewhere: your snippet is intersting, >>> because assembly instructions are coded in at compile time >>> without loading the full assembler. That I can see. >> >> Yes, that DIY assembly approach can do things which lib/assembler.frt >> may find difficult to follow :-) > > Your SBI/CBI macros are an excellent and inspiring solution for a > particular problem. I think it really deserves to be published. > As a recipe in the cookbook. There are quite a few solutions, that > do not go into the repository and are worth studying. I do hope, > you can live with that. It has the advantage to have documentation I can certainly live with that :-) You are, as long as your contribution stream is sustained, the "Guido van Rossum" of this project. I state that as a fact, with true appreciation to your contribution. My sense of programming aesthetics requires critical sections to be as short as possible if not eliminated altogether. It's a result of a seminar I took years ago on programming cooperating processes, based on an E.W.Dijkstra paper. In my current project Atmel has even given me a GPIOR0 (a general purpose register) that I can apply SBI/CBI atomically to. Why should I give it up? > and implementation in one document. The code in the lib/ directory > is not that well documented. IMHO the asm code needs better docuemntation as a proirity as well. Your move to reST makes it easier to contribute. I consider it a personal obligation to help and hope that other Amforth users feel the same. Keep up the good work! Regards, Enoch. > > Matthias > > > ------------------------------------------------------------------------------ > Everyone hates slow websites. So do we. > Make your web apps faster with AppDynamics > Download AppDynamics Lite for free today: > http://p.sf.net/sfu/appdyn_d2d_feb |