Home
JAQForum Ver 24.01
Log In or Join  
Active Topics
Local Time 21:23 05 Sep 2025 Privacy Policy
Jump to

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 : Question about PIO DMA TX interupt

Author Message
AlbertR
Newbie

Joined: 29/05/2025
Location: Germany
Posts: 26
Posted: 11:26am 31 Aug 2025
Copy link to clipboard 
Print this post

I make some tests with the Picomite PIO for the WS2812-Output.
Because the implemented function "Device WS2812" is blocking during output-time, I was looking for an other possibility. The PIO should be a candidate.

Option EXPLICIT
Option DEFAULT NONE
Dim integer leds(255)
Dim integer pack(127)
Dim integer Busy = 0'as Mutex: ready to send

SetPin gp22,pio1
' The PIO program - PIO WS2812 driver on GP22 --------------------------------
'       ____                 ________
'(0) __|    |______   (1) __|        |__
'  .2us .4us .6us       .2us  .8us   .2us
PIO CLEAR 1
PIO ASSEMBLE 1, ".program leds"
PIO ASSEMBLE 1, ".line 0"
PIO ASSEMBLE 1, "SET PINDIRS, 1"
PIO ASSEMBLE 1, ".wrap target"   'steps |delay
PIO ASSEMBLE 1, "OUT x, 1 "      '1 lo   0.2us
PIO ASSEMBLE 1, "SET PINS, 1 [1]"'2 hi   0.4us
PIO ASSEMBLE 1, "MOV PINS, x [1]"'2 data 0.4us
PIO ASSEMBLE 1, "SET PINS, 0 "   '1 lo   0.2us
PIO ASSEMBLE 1, ".wrap"          '6 sum  1.2us = 833kHz
PIO ASSEMBLE 1, ".end program list"

Dim integer ExeC = Pio(execctrl GP22,Pio(.wrap target),Pio(.wrap))
Dim integer PinC = Pio(pinctrl 0,1,1,,,gp22,gp22)
Dim integer ShiC = Pio(shiftctrl 0,24,0,1) 'Set Auto Pull at 24bits
Dim integer Freq = 5000000 '5MHz -> 1 step -> 0.2us
'setup the machine.
PIO init machine 1,0,Freq,PinC,ExeC,ShiC,0
'init
Math set &hf0,leds()'all blue
'test-pattern
leds(0)=&hcdabef <<8
leds(1)=&h341256 <<8
leds(2)=&haaaaaa <<8
leds(3)=&h555555 <<8
'main loop
Do
 Pause 100 'simulate some calculation with leds()

 Do :Loop While Busy              'wait for ready
 Memory pack leds(),pack(),256,32 'copy and pack
 Busy = 1
 'set busy-flag
 PIO DMA TX 1,0,4,pack() ',FinI

 Pause 1
 PIO stop 1,0
 PIO init machine 1,0,Freq,PinC,ExeC,ShiC,0
 Busy = 0 'ready to start
 'OutL()
Loop'end main
End

'subs/functions -------------------------------------------------------------
Sub FinI
 'stop the PIO and re-init for next run
 Pause 1
 PIO stop 1,0
 PIO init machine 1,0,Freq,PinC,ExeC,ShiC,0
 Busy = 0 'ready to start
End Sub

Sub OutL
Local integer i=0
PIO start 1,0  'start the PIO
Do While i < 4
  PIO WRITE 1,0,1,leds(i)
  Inc i
Loop
PIO stop 1,0   'stop the PIO
End Sub

For testing the PIO-program I use the "PIO WRITE" command, DMA with interupt and with
Pause. Thats the results:



1. PIO WRITE always kills the last bit. If CPUSPEED is only 150MHz it generates a "Break"
2. PIO with TX-DMA works very good but if I use the Ready-Interupt it stops the PIO, even if there is some data left in the OSR and even if there is no PIO STOP in the sub.
3. The version with "pause 1" works spable, but then I am blocking again. That is not what I expected when I use DMA.
I think I am not the only one who use PIO. Where did I thing wrong?

Greetings
Albert
 
AlbertR
Newbie

Joined: 29/05/2025
Location: Germany
Posts: 26
Posted: 12:31pm 31 Aug 2025
Copy link to clipboard 
Print this post

Ok, a non blocking solution could be, using a Timer-Interupt with precalculated delay.


'Do 'main loop
Do
 ' do something
 Do : Loop While Busy               'wait for ready
 Memory pack leds(),pack(),1024,32 'copy and pack
 Busy = 1                          'set busy-flag
 PIO DMA TX 1,0,1024,pack()',FinI
 SetTick 29,FinI,1 ' 29us/24bit
Loop
End

'subs/functions -------------------------------------------------------------
Sub FinI
 'stop the PIO and re-init for next run
 SetTick 0,FinI,1
 PIO stop 1,0
 PIO init machine 1,0,Freq,PinC,ExeC,ShiC,0
 Busy = 0 'ready to start
End Sub


But is this the right way/solution?

Albert
 
matherp
Guru

Joined: 11/12/2012
Location: United Kingdom
Posts: 10386
Posted: 12:54pm 31 Aug 2025
Copy link to clipboard 
Print this post

PIO DMA TX waits before firing the interrupt until the fifo is clear. It can't know the status of the OSR or any other PIO internals so there is no way it can wait until the PIO finishes before stopping the processing. Your workaround is probably as good as it gets. When the PIO is running a faster process then the inherent delay in the MMbasic interrupt firing masks the issue.
 
AlbertR
Newbie

Joined: 29/05/2025
Location: Germany
Posts: 26
Posted: 01:09pm 31 Aug 2025
Copy link to clipboard 
Print this post

Thanks for the quick answer.
I already thought to myself that the FIFO clear is the trigger, but why did the PIO stops by calling the Interupt. In the examples from the manual there is an additional "PIO STOP"? A "pause 1" before it has no effect.

Albert
 
Print this page


To reply to this topic, you need to log in.

The Back Shed's forum code is written, and hosted, in Australia.
© JAQ Software 2025