Why is this so hard?
Re: Why is this so hard?
I'm not that familiar with the assembler stuff, so I can't really comment.
However, if you really want 2 usec pulses on some period, you're much better off to use one of the Timers to generate the pulses.
There are some examples on this page: http://wiki.micropython.org/platforms/b ... r-Examples
However, if you really want 2 usec pulses on some period, you're much better off to use one of the Timers to generate the pulses.
There are some examples on this page: http://wiki.micropython.org/platforms/b ... r-Examples
Re: Why is this so hard?
No, you don't understand. I want to generate a fixed 1..2us pulse at variable frequencies for 8 outputs. These outputs will have the pulses in sequence ... I can't do that with timers.
What is wrong with my assembly that it won't work in a timer interrupt?
(NB: .. every timer interrupt/callback I want the sequence to run ..)
What is wrong with my assembly that it won't work in a timer interrupt?
(NB: .. every timer interrupt/callback I want the sequence to run ..)
Re: Why is this so hard?
The timer callback is supposed to take a single parameter, like this example:
https://github.com/dhylands/upy-example ... eat_irq.py
(which unfortunately uses a class).
This example has ic_cb as a free function:
https://github.com/dhylands/upy-example ... ic_test.py
When dealing with interrupts, adding these lines to your python script will get more detailed information about the exception (interrupt handlers aren't allowed to allocate memory. Unfortunately, throwing an exception requires allocating memory). With those two lines, I now get this error:
With this version: I had to add the Pin statement to get the pin configured as an output (they're configured as an input by default), then I get this output:
1.875 usec corresponds to 315 CPU cycles (at 168 MHz), which is about 6 cycles per loop. There's 1 for the SUB, 1 for the CMP, 1 for BGT and presumably 3 for the pipeline reload for taking the branch (the ARM documents say it takes 1 to 3 depending on alignment, width of instruction, and whether the processor managed to speculate the address properly or not).
https://github.com/dhylands/upy-example ... eat_irq.py
(which unfortunately uses a class).
This example has ic_cb as a free function:
https://github.com/dhylands/upy-example ... ic_test.py
When dealing with interrupts, adding these lines to your python script will get more detailed information about the exception (interrupt handlers aren't allowed to allocate memory. Unfortunately, throwing an exception requires allocating memory).
Code: Select all
import micropython
micropython.alloc_emergency_exception_buf(100)
Code: Select all
>>> import flash_int
>>> uncaught exception in Timer(4) interrupt handler
TypeError: function takes 0 positional arguments but 1 were given
Code: Select all
from pyb import Timer, Pin
import stm
import micropython
micropython.alloc_emergency_exception_buf(100)
@micropython.asm_thumb
def flash_int(r0):
movwt(r1, stm.GPIOC)
# get the bit mask for PAC6
movw(r2, 1 << 6)
# Turn on
strh(r2, [r1, stm.GPIO_BSRRL])
# delay for a bit
movwt(r4, 50) #50 = 2.5us
label(delay_on)
sub(r4, r4, 1)
cmp(r4, 0)
bgt(delay_on)
#turn off
strh(r2, [r1, stm.GPIO_BSRRH])
pin = Pin('C6', Pin.OUT_PP)
tim4 = Timer(4, freq=200)
tim4.callback(flash_int)
Re: Why is this so hard?
ahh, seems I had the following missing bits:
1. The "import stm" ... shame the parser did not pop an error when that was missing ..
2. missed the "r0" in the asm function call .. e.g "flash_int(r0):" ... that was not at all apparent ..
I did have the pin setup for output push-pull earlier in my code. (which I should have shown )
Thanks for that, it now works just as I had hoped .. will add the other outputs now.
Cheers,
1. The "import stm" ... shame the parser did not pop an error when that was missing ..
2. missed the "r0" in the asm function call .. e.g "flash_int(r0):" ... that was not at all apparent ..
I did have the pin setup for output push-pull earlier in my code. (which I should have shown )
Thanks for that, it now works just as I had hoped .. will add the other outputs now.
Cheers,
Re: Why is this so hard?
It seems that the import of stm isn't required. I just assumed it was. I haven't really played with the asm stuff very much.
The timer callback is documented here: http://docs.micropython.org/en/latest/l ... r.callback
The emergency buffer thing is a little more obscure, and is documented here:
http://docs.micropython.org/en/latest/l ... eption_buf
I think its on my todo list to flesh out some more information about interrupts.
The timer callback is documented here: http://docs.micropython.org/en/latest/l ... r.callback
The emergency buffer thing is a little more obscure, and is documented here:
http://docs.micropython.org/en/latest/l ... eption_buf
I think its on my todo list to flesh out some more information about interrupts.
Re: Why is this so hard?
Hi,
Performance seems to be the issue now.
If I have the interrupt go as fast as 50Khz with assembly toggling two outputs (not even the 8 I want eventually) then REPL stops responding. (The output is just fine though)
Is there anything that can be done there? Change priority of and REPL interrupt?
Performance seems to be the issue now.
If I have the interrupt go as fast as 50Khz with assembly toggling two outputs (not even the 8 I want eventually) then REPL stops responding. (The output is just fine though)
Is there anything that can be done there? Change priority of and REPL interrupt?
Re: Why is this so hard?
ok,
Code: Select all
@micropython.asm_thumb
def pulser_int(r0):
movwt(r1, stm.GPIOC)
b(loop_entry)
movw(r3,5) # one less than starting bit
label(loop1)
# get the bit mask for PAC6
movw(r2, 1)
lsl(r2,r3)
# Turn on
strh(r2, [r1, stm.GPIO_BSRRL])
# delay for a bit
movwt(r4, 50) #50 = 2.5us
label(delay_on)
sub(r4, r4, 1)
cmp(r4, 0)
bgt(delay_on)
#turn off
strh(r2, [r1, stm.GPIO_BSRRH])
# loop on r3
add(r3, r3, 1)
label(loop_entry)
cmp(r3, 8) # one more than end bit required
blt(loop1)
pin = Pin('C6', Pin.OUT_PP)
pin = Pin('C7', Pin.OUT_PP)
tim4 = Timer(4, freq=50000)
tim4.callback(pulser_int)
Re: Why is this so hard?
I decided to add some instrumentation to the timer_irq. I used 2 GPIOs.
I turned X1 on at he beginning of timer_irq_handler and turned it off at the end.
I turned X2 on just before calling mp_call_function_1 (the C function which calls the timer callback) and turned it off just after returning.
I then ran the "corrected" flash_int.py from my previous post with a freq of 50kHz. Here's my scope capture: What I'm seeing is that time spent in timer_irq_handler is 5.625 usec.
The time spent inside mp_call_function_1 is 4.167 usec (included in the 5.625usec) and the time that the line toggled by the python assembler routine is 1.833 usec.
This gives an upper bound of 200,000 timer IRQs/sec. This would cause 100% of CPU to be used for handling timer IRQs and the REPL will not be able to run.
What exactly are you trying to do?
To go faster than the above, you're going to have to use a different technique or code it in C.
I turned X1 on at he beginning of timer_irq_handler and turned it off at the end.
I turned X2 on just before calling mp_call_function_1 (the C function which calls the timer callback) and turned it off just after returning.
I then ran the "corrected" flash_int.py from my previous post with a freq of 50kHz. Here's my scope capture: What I'm seeing is that time spent in timer_irq_handler is 5.625 usec.
The time spent inside mp_call_function_1 is 4.167 usec (included in the 5.625usec) and the time that the line toggled by the python assembler routine is 1.833 usec.
This gives an upper bound of 200,000 timer IRQs/sec. This would cause 100% of CPU to be used for handling timer IRQs and the REPL will not be able to run.
What exactly are you trying to do?
To go faster than the above, you're going to have to use a different technique or code it in C.
Re: Why is this so hard?
I ran your 2-channel code with the instrumentation and I'm seeing this:
However, if you look at the 2nd line (high time is 17 usec, which means that about 15 usec is being spent in your assembler routine.
The bottom 2 are where the asm routine is writing. C6 is the 3rd line, C7 is the 4th line.
However, if you look at the 2nd line (high time is 17 usec, which means that about 15 usec is being spent in your assembler routine.