Notice. New forum software under development. It's going to miss a few functions and look a bit ugly for a while, but I'm working on it full time now as the old forum was too unstable. Couple days, all good. If you notice any issues, please contact me.
|
Forum Index : Microcontroller and PC projects : PIO explained PICOMITE
Page 8 of 8 | |||||
Author | Message | ||||
Volhout Guru Joined: 05/03/2018 Location: NetherlandsPosts: 4256 |
Hi Peter, That is it. Now it works. And yes, you are right. It is faster to poll the status. But that forces you to do so frequently. And if you use PIO just as another peripheral (i.e. a UART) it is convenient when you have the interrupts. Just take action when something happens... Thanks, Volhout p.s. Why is the restriction that FIFO should have been previously full ? What if the PIO can keep up with MMBasic (very likely given the speed of PIO), and the fifo never gets full ? Did I overlook something obvious. Please tell. PicomiteVGA PETSCII ROBOTS |
||||
matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 9139 |
An interrupt has to happen on a state change otherwise it will continually trigger. I could change it so that it triggers whenever the FIFO has reduced by 1. Then you would only need to seed it with one value. I could trigger when it has gone from more than half full to half full... etc. Since the focus of this release is PIO I might (but only might) next look at PIO DMA IN nbr, A%() PIO DMA OUT nbr, a%() A%() would be integer arrays but you would need to use the PACK and UNPACK to convert 64 bit arrays to 32bit |
||||
Volhout Guru Joined: 05/03/2018 Location: NetherlandsPosts: 4256 |
Aha, that explains it. I was in the understanding that before starting interpreting a new MMBasic command you would look at the staus bit in FSTAT, and when 0 trigger the interrupt. But you need achange of state.... OK... Clear. On DMA I am not educated. I know how it works, but not how it could work in MMBasic. If DMA is a means to handle data transfers at ARM / BUS speed in the background (not interpreter speed) then it will be very beneficial. Sending data to an array of WS2812 will be piece of cake then. Just prepare an array, and push the button. This will also allow the picomite to work as logic analyzer (with trigger programmed in PIO) or a suffisticated AWG (Arbitrary waveform generator). PicomiteVGA PETSCII ROBOTS |
||||
Bleep Guru Joined: 09/01/2022 Location: United KingdomPosts: 512 |
An interrupt has to happen on a state change otherwise it will continually trigger. I could change it so that it triggers whenever the FIFO has reduced by 1. Then you would only need to seed it with one value. I could trigger when it has gone from more than half full to half full... etc. Since the focus of this release is PIO I might (but only might) next look at PIO DMA IN nbr, A%() PIO DMA OUT nbr, a%() A%() would be integer arrays but you would need to use the PACK and UNPACK to convert 64 bit arrays to 32bit Hi Peter, My vote, if nothing else changes, is for interrupt to be at half empty, so when 2 (or 4) items left. Otherwise your proposed, possible, changes look interesting, packing & unpacking are very fast & easy, would these transfer 'nbr' data items out of/into the FiFo to or from the array indicated? Would the array always be read/written from element 0? or would you envisage PIO DMA in 3, a%(4) being feasable, so the transfer starts at element 4 then 5 etc.I appreciate this may not happen. Regards Kevin. Edited 2023-01-17 00:57 by Bleep |
||||
matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 9139 |
Volhout Please could you do me a version of this that returns an incrementing counter rather than zero. Needed for DMA testing - thanks 'PIO clear pio clear 1 'the PIO program 'address code mnemonics comment ' 0 2000 WAIT GP0=0 ' 1 2080 WAIT GP0=1 ' 2 8000 PUSH noblock ' 3 0000 JMP 0 'program pio1 pio program line 1,0,&h2000 pio program line 1,1,&h2080 pio program line 1,2,&h8000 PIO program line 1,3,&h0000 |
||||
Volhout Guru Joined: 05/03/2018 Location: NetherlandsPosts: 4256 |
Here you go..... ' demo program to deomnstrate the use of the PIO interrupt ' the PIO is programmed to push 1 word into FIFO at every rising edge of the GP0 pin. ' the GP0 pin is controlled from MMBasic in this demo, but could also be driven from ' an external source. '-------------------------------- PIO state machine ----------------------------------- 'PIO clear pio clear 1 'the PIO program 'address code mnemonics comment ' 0 A02B MOV X=-NULL ' 1 2000 WAIT GP0=0 ' 2 2080 WAIT GP0=1 ' 3 A0C9 MOV ISR=-X ' 4 8000 PUSH noblock ' 5 0041 JMP (X<>0) 1 X-- ' 6 0000 JMP 0 'program pio1 pio program line 1,0,&hA02B pio program line 1,1,&h2000 pio program line 1,2,&h2080 pio program line 1,3,&hA0C9 pio program line 1,4,&h8000 PIO program line 1,5,&h0041 pio program line 1,6,&h0000 'write the configuration, running 100kHz (data in FIFO 10us after rising edge GP0) PIO init machine 1,0,1e5,0,,,0 '-------------------------------- MMBasic MAIN --------------------------------------- 'Halt the PIO from GP0 from MMBasic before it fills the FIFO out of control setpin gp0,dout pin(gp0)=0 'variables dim d% dim newdata%=0 'start the pio1 code, state machine 1.0 will be waiting for a rising edge on the GP0 pin 'then it will push 1 word into fifo. Then it will wait for the falling edge. The cycle repeats. PIO start 1,0 'interrupt format PIO INTERRUPT PIO,SM,RX_SUB,TX_SUB ' PIO interrupt 1,0,GetIt,0 'freguently feed data into the fifo Settick 100,FeedFifo 'Main: check if data, when yes, then print do do loop while (pio(fstat 1) and 256) PIO READ 1,0,1,d% print d% loop '----------------------------------- SUBS --------------------------------------- 'in this sub we toggle the GP0 pin to force the PIO to put data in the FIFO sub FeedFifo pin(gp0)=1:pause 1:pin(gp0)=0:pause 1 end sub For whatever reason the PIO INTERRUPT 1,0,RX,0 gives a "Line Error", even with an applicable SUB that does the reading of the fifo. Did not take the time to find out why. This version is polling the FSTAT. You are interested in the incrementing value only I guess. Tomorrow I will look into why the RX Interrupt does not work. Volhout PicomiteVGA PETSCII ROBOTS |
||||
matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 9139 |
I'm loving this PicoMite.zip Try these two examples (PicoMite only) Reading data by DMA ' demo program to deomnstrate the use of the PIO interrupt ' the PIO is programmed to push 1 word into FIFO at every rising edge of the GP0 pin. ' the GP0 pin is controlled from MMBasic in this demo, but could also be driven from ' an external source. '-------------------------------- PIO state machine ----------------------------------- 'PIO clear PIO clear 1 'the PIO program 'address code mnemonics comment ' 0 A02B MOV X=-NULL ' 1 2000 WAIT GP0=0 ' 2 2080 WAIT GP0=1 ' 3 A0C9 MOV ISR=-X ' 4 8000 PUSH noblock ' 5 0041 JMP (X<>0) 1 X-- ' 6 0000 JMP 0 'program pio1 PIO program line 1,0,&hA02B PIO program line 1,1,&h2000 PIO program line 1,2,&h2080 PIO program line 1,3,&hA0C9 PIO program line 1,4,&h8000 PIO program line 1,5,&h0041 PIO program line 1,6,&h0000 'write the configuration, running 100kHz (data in FIFO 10us after rising edge GP0) PIO init machine 1,0,1e5,0,,,0 '-------------------------------- MMBasic MAIN --------------------------------------- 'Halt the PIO from GP0 from MMBasic before it fills the FIFO out of control SetPin gp0,dout Pin(gp0)=0 'variables Dim d% Dim newdata%=0 Dim a%(15),b%(31) 'start the pio1 code, state machine 1.0 will be waiting for a rising edge on the GP0 pin 'then it will push 1 word into fifo. Then it will wait for the falling edge. The cycle repeats. PIO DMA_IN 1,0,32,a%(),recvdone 'interrupt format PIO INTERRUPT PIO,SM,RX_SUB,TX_SUB ' PIO interrupt 1,0,GetIt,0 'freguently feed data into the fifo SetTick 100,FeedFifo 'Main: check if data, when yes, then print Do ' Do ' Loop While (Pio(fstat 1) And 256) ' PIO READ 1,0,1,d% ' Print d% Loop Sub recvdone Memory unpack Peek(varaddr a%()),Peek(varaddr b%()),32,32 For i=0 To 31 Print b%(i) Next i end End Sub '----------------------------------- SUBS --------------------------------------- 'in this sub we toggle the GP0 pin to force the PIO to put data in the FIFO Sub FeedFifo Pin(gp0)=1:Pause 1:Pin(gp0)=0:Pause 1 End Sub And writing data by DMA ' demo program to demonstrate the use of the PIO interrupt ' the PIO is programmed to pull 1 word from FIFO at every rising edge of the GP pin. ' the LSB 5 bits are shown on GP1..GP5 (diagnostics) ' the GP0 pin is controlled from MMBasic in this demo, but could also be driven from ' an external source. '-------------------------------- PIO state machine ----------------------------------- 'PIO clear, and attach pins to PIO 1 PIO clear 1 SetPin gp1,pio1 SetPin gp2,pio1 SetPin gp3,pio1 SetPin gp4,pio1 SetPin gp5,pio1 Dim integer unpacked%(31),packed%(15) Dim integer packedadd=Peek(varaddr packed%()) Dim integer unpackedadd=Peek(varaddr unpacked%()) For i=0 To 31 unpacked%(i)=i Next Memory pack unpackedadd,packedadd,32,32 'the PIO program 'address code mnemonics comment ' 0 E09F SET pindirs &b11111 GP1..GP5 out ' 1 2000 WAIT GP0=0 wait for external trigger on GP0 to pull ' 2 2080 WAIT GP0=1 ' 3 8080 PULL noblock pulls data off fifo ' 4 6005 OUT OSR > pins 5 shift 5 bits to GP1..5 pins ' 5 0001 JMP 1 repeat PIO program line 1,0,&hE09F PIO program line 1,1,&h2000 PIO program line 1,2,&h2080 PIO program line 1,3,&h8080 PIO program line 1,4,&h6005 PIO program line 1,5,&h0001 'write the configuration, running 1MHz f=1e6 p=Pio(pinctrl 0,5,5,gp0,,gp1,gp1) 'pins GP1...GP5 = out, GP0 = in ' s=PIO(shiftctrl 0,0,0,0,1,1) 'default value ' e=PIO(execctrl gp0,0,31) 'default value: wrap defaults, GP0 = cond JMP pin ' PIO init machine 1,0,f,p,e,s,0 'PIO 1 SM 0 start adress = 0 PIO init machine 1,2,f,p,,,0 'PIO 1 SM 0 start adress = 0 '-------------------------------- MMBasic MAIN --------------------------------------- 'Halt the PIO from GP0 from MMBasic before it fills the FIFO out of control SetPin gp0,dout Pin(gp0)=0 'variables Dim d%=0 'start the pio1 code, state machine 1.0 will be waiting for a rising edge on the GP0 pin 'then it will pull 1 word from fifo. Then it will wait for the falling edge. The cycle repeats. PIO DMA_OUT 1,2,32,packed%(),dmadone 'freguently PIO pull data from the fifo SetTick 500,PullFifo 'Main: interrupt free loop polling the NOT TX_FULL flag in FSTAT Do If a% Then SetTick 0,0 End EndIf Loop End '----------------------------------- SUBS --------------------------------------- 'in this sub we toggle the GP0 pin to force the PIO to fetch data from the FIFO Sub PullFifo Pulse gp0,10 End Sub Sub dmadone Print "All done" a%=1 End Sub Edited 2023-01-17 03:23 by matherp |
||||
Volhout Guru Joined: 05/03/2018 Location: NetherlandsPosts: 4256 |
@Peter, This is beta 3. There is something wrong with RX interrupt. > RUN [50] PIO interrupt 1,0,RX_Int,0 Error : Line number > ?mm.ver 5.070703 This is the code (basically the same you use for DMA...) ' demo program to deomnstrate the use of the PIO interrupt ' the PIO is programmed to push 1 word into FIFO at every rising edge of the GP 0 pin. ' the GP0 pin is controlled from MMBasic in this demo, but could also be driven from ' an external source. '-------------------------------- PIO state machine --------------------------- -------- 'PIO clear PIO clear 1 'the PIO program 'address code mnemonics comment ' 0 A02B MOV X=-NULL ' 1 2000 WAIT GP0=0 ' 2 2080 WAIT GP0=1 ' 3 A0C9 MOV ISR=-X ' 4 8000 PUSH noblock ' 5 0041 JMP (X<>0) 1 X-- ' 6 0000 JMP 0 'program pio1 PIO program line 1,0,&hA02B PIO program line 1,1,&h2000 PIO program line 1,2,&h2080 PIO program line 1,3,&hA0C9 PIO program line 1,4,&h8000 PIO program line 1,5,&h0041 PIO program line 1,6,&h0000 'write the configuration, running 100kHz (data in FIFO 10us after rising edge G P0) PIO init machine 1,0,1e5,0,,,0 '-------------------------------- MMBasic MAIN -------------------------------- ------- 'Halt the PIO from GP0 from MMBasic before it fills the FIFO out of control SetPin gp0,dout Pin(gp0)=0 'variables Dim d% Dim newdata%=0 'start the pio1 code, state machine 1.0 will be waiting for a rising edge on th e GP0 pin 'then it will push 1 word into fifo. Then it will wait for the falling edge. Th e cycle repeats. PIO start 1,0 'interrupt format PIO INTERRUPT PIO,SM,RX_SUB,TX_SUB PIO interrupt 1,0,RX_Int,0 'freguently feed data into the fifo SetTick 100,FeedFifo 'Main: check if data, when yes, then print Do Pause 10 ' Do ' Loop While (Pio(fstat 1) And 256) ' PIO READ 1,0,1,d% ' Print d% Loop '----------------------------------- SUBS ------------------------------------- -- 'in this sub we toggle the GP0 pin to force the PIO to put data in the FIFO Sub FeedFifo Pin(gp0)=1:Pause 1:Pin(gp0)=0:Pause 1 End Sub Sub RX_int PIO read 1,0,1,d% Print d% End Sub When you remove the trailing ",0" it works. But that implies that you cannot stop the TX_Int when the RX_Int is running. Today I will try the DMA stuff. Looks promising... Edited 2023-01-17 18:21 by Volhout PicomiteVGA PETSCII ROBOTS |
||||
matherp Guru Joined: 11/12/2012 Location: United KingdomPosts: 9139 |
Easy fix. Will post b4 with the full DMA for both variants on the main thread in an hour or so |
||||
disco4now Guru Joined: 18/12/2014 Location: AustraliaPosts: 900 |
Here is how I think the IRQ and WAIT interrupt flags work in regard to the "If the MSB is set, the state machine ID (0…3) is added to the IRQ index, by way of modulo-4 addition on the two LSBs" thing. The following clues from the data sheet are relevant. From the WAIT instruction: The flag index is decoded in the same way as the IRQ index field: if the MSB is set, the state machine ID (0…3) is added to the IRQ index, by way of modulo-4 addition on the two LSBs. For example, state machine 2 with a flag value of '0x11' will wait on flag 3, and a flag value of '0x13' will wait on flag 1. This allows multiple state machines running the same program to synchronise with each other. From the IRQ instruction: The modulo addition bit allows relative addressing of 'IRQ' and 'WAIT' instructions, for synchronising state machines which are running the same program. Bit 2 (the third LSB) is unaffected by this addition. I am looking at this from the point of view of compiling instructions for WAIT and IRQ. I initially thought I would need this Modulo-4 thing and apply it to the index, but I think this is not the case. This is a job for the PIO, NOT the programmer. This view is supported when I put instructions into the official PIOASM compiler. It doesn't know which State Machine it is compiling for, if you ask for interrupt 7, it gives you interrupt 7. The MSB of the index (B4) is set when the rel parameter is added to IRQ instruction. e.g. IRQ <irq-num> rel B0 to B2 hold the IRQ number 0-7. I guess B3 is unused. The programmer's/coder's job is not to modify the index, but just set B4 to tell the PIO State Machine it is running code that is shared by another state machine. When a PIO State Machine sees B4 set it knows one of two things a) the programmer is making life difficult for no good reason or b) it is running the same code as another (or more ) state machine. So B4 set tells a State Machine it its sharing code, it can't literally use the interrupt in the instruction as SM0 (adding 0 doesn't change it) will use that interrupt. It must do the Modulo-4 thing and get another value. The WAIT does the same thing so they end up with the same new interrupt and all is well. The only thing you would need to watch out for as a programmer would be when you want to use multiple interrupts when running shared code. Your just need to ensure any IRQ numbers selected don't resolve to the same IRQ as each other when the modulo-4 thing is done for any of the state machine sharing the code. @Pluto's table above shows the various combinations that could result in the same IRQ value and have state machines confusing each other. Latest F4 Latest H7 |
||||
Pluto Guru Joined: 09/06/2017 Location: FinlandPosts: 359 |
Thanks disco4now for your valuable comments and explanations. My excercise is more about decoding existing PIO-instructions than creating. The target is to explain the instructions in more detail in order to make it easier (for me) to follow the PIO-program flow without having to constantly check the PR2040 datasheet for the instruction details. The only nut that I so far couldn't crack is the IRQ & WAIT modulo-4 addition stuff. I am also a bit suspicious about my understanding of the modulo-4 addition; strange that bit B3 in the index register is not used. Even when it seems that efforts are made to sqeeze in "more info than possible" into 5 bits. I agree with you that as long as IRQ & WAIT Index B4 is 0, it is straight forward to understand the purpose of the instruction. B4=1 case is still a some kind of mystery. May be we will enter the B4=1 topic again when more PIO codes are created on the forum. |
||||
Volhout Guru Joined: 05/03/2018 Location: NetherlandsPosts: 4256 |
Update for PicoMite V5.07.07b28 and newer Since PIO assembler is integrated in PicoMite V50707b28, the training can also be followed using the build in assembler. It is still usefull to understand manual assembly, but below programs show how to do things now. Chapter 1 'disconnect ARM from GP0 setpin gp0,pio1 'configure pio1 p=Pio(pinctrl 0,1,,,,gp0,) f=2029 '2029Hz is compatible with picomite 133MHz 'pio program assemble and write to memory pio assemble 1,".program chapter1" pio assemble 1,".line 0" pio assemble 1,"set pindirs,1" pio assemble 1,"label:" pio assemble 1,"set pins,1" pio assemble 1,"set pins,0" pio assemble 1,"jmp label" pio assemble 1,".end program list" 'write the configuration: PIO, state machine, frequency,pincontrol,,,start address PIO init machine 1,0,f,p,,,0 'start the pio1 code PIO start 1,0 Chapter 2 program 1 'disconnect ARM from GP0 setpin gp0,pio1 'configure pio1 p=Pio(pinctrl 0,1,,,,gp0,) f=2029 '2029Hz is compatible with picomite 133MHz 'pio program assemble and write to memory pio assemble 1,".program chapter2a" pio assemble 1,".line 0" pio assemble 1,"set pindirs,1" pio assemble 1,"label:" pio assemble 1,"set pins,1 [1]"  '[1] means delay = 1 pio assemble 1,"set pins,0" pio assemble 1,"jmp label" pio assemble 1,".end program list" 'write the configuration: PIO, state machine, frequency,pincontrol,,,start address PIO init machine 1,0,f,p,,,0 'start the pio1 code PIO start 1,0 ' check the GP0 pin from MMbasic setpin gp6,fin 'wait a bit pause 1100 'measure frequency and show print pin(gp6);" Hz" 'stop pio PIO STOP 1,0 END Chapter 2 program 2 'disconnect ARM from GP0 setpin gp0,pio1 'configure pio1 p=Pio(pinctrl 0,1,,,,gp0,) f=2029 '2029Hz is compatible with picomite 133MHz 'pio program assemble and write to memory pio assemble 1,".program chapter2b" pio assemble 1,".line 0" pio assemble 1,"set pindirs,1" pio assemble 1,"label:" pio assemble 1,"set pins,1 [1]"  '[1] means delay = 1 pio assemble 1,"set pins,0" pio assemble 1,"jmp label" pio assemble 1,".end program list" 'write the configuration: PIO, state machine, frequency,pincontrol,,,start address PIO init machine 1,0,f,p,,,0 'start the pio1 code PIO start 1,0 ' check the GP0 pin from MMbasic 'array to store 101 samples taken from GP0 dim v%(100) 'sample the GP0 pin into the array 101 samples for i%=0 to 100  v%(i%)=pin(gp0)  pause 0.1     'limit the speed a bit next i% math v_print v%()  'print the whole array to the screen 'stop pio PIO STOP 1,0 END Exercise chapter 2 'disconnect ARM from GP0 setpin gp0,pio1 'configure pio1 p=Pio(pinctrl 0,1,,,,gp0,) e=PIO(execctrl gp2,0,31) f=1000 * 6 'Hz 'pio program assemble and write to memory pio assemble 1,".program chapter3" pio assemble 1,".line 0" pio assemble 1,"set pindirs,1"     'gp0=out pio assemble 1,"label1:" pio assemble 1,"set pins,1 [2]"    'gp0=1 delay 2 pio assemble 1,"jmp pin label2" pio assemble 1,"set pins,1"      pio assemble 1,"label2:" pio assemble 1,"set pins,0"      'gp0=0 pio assemble 1,"jmp label1" pio assemble 1,".end program list" 'write the configuration (note we added "e") PIO init machine 1,0,f,p,e,,0 'start the pio1 code PIO start 1,0 'toggle GP2 in MMBasic Setpin gp2,dout do  pin(gp2) = 1 - pin(gp2) 'toggle pin GP2  pause 100 loop END Chapter 3 'disconnect ARM from GP0 setpin gp0,pio1 setpin gp1,pio1 'configure pio1 p=Pio(pinctrl 0,2,,,,gp0,) f=2000 * 5.4 'Hz 'pio program assemble and write to memory pio assemble 1,".program chapter2a" pio assemble 1,".line 0" pio assemble 1,"set pindirs,&b11"   '&b11 = gp1=out, gp0=out pio assemble 1,"label:" pio assemble 1,"set pins,&b01 [1]"   '&b01 = gp1=0, gp0=1 pio assemble 1,"set pins,&b10"     '&b10 = gp1=1, gp0=0 pio assemble 1,"jmp label" pio assemble 1,".end program list" 'write the configuration: PIO, state machine, frequency,pincontrol,,,start address PIO init machine 1,0,f,p,,,0 'start the pio1 code PIO start 1,0 ' check the GP0 pin from MMbasic setpin gp6,fin 'measure frequency and show do  pause 1100  print pin(gp6);" Hz" loop while inkey$="" 'stop pio PIO STOP 1,0 END When time permits I will also prepare the other chapters. For now, you grasp the idea how things are easier thanks to Peter.... Volhout Edited 2023-03-25 02:03 by Volhout PicomiteVGA PETSCII ROBOTS |
||||
Page 8 of 8 |
Print this page |