Inline assembly in callback

The official pyboard running MicroPython.
This is the reference design and main target board for MicroPython.
You can buy one at the store.
Target audience: Users with a pyboard.
Post Reply
stromgald
Posts: 4
Joined: Fri Jan 19, 2018 4:57 am

Inline assembly in callback

Post by stromgald » Wed May 30, 2018 7:04 pm

Hi,
I was wondering if it's possible to get some inline assembly to work in a callback. I'd like to toggle a GPIO line.
I read in the documentation that an instance of object creation occurs when a reference to a bound method is created. So i am trying a few of the work around methods. The "test" function below does work if i pass the reference to the ISR. But it's tricky for the assembler function since arguments must be named r0, r1 etc. Any ideas if something like this can work? Thanks!

Code: Select all

class Motor(object):
    """
    Motor class
    timers run at 2mHz
    """
    def __init__(self, name, timer_num, pin_id, mdir=0, steps=0):
        self.name = name
        self.steps = steps
        self.motor_step_ref=self.motor_step
        self.timer_num = timer_num
        self.pin_id = pin_id
        self.mdir = mdir

        @micropython.asm_thumb
        def motor_step():
            movwt(r0, stm.GPIOA)
            movw(r1, 1 << 6)
            strh(r1, [r0, stm.GPIO_BSRRL])
            movwt(r4, 30)
            label(delay_off)
            sub(r4, r4, 1)
            cmp(r4, 0)
            bgt(delay_off) 
            strh(r1, [r0, stm.GPIO_BSRRH])

        motortim = pyb.Timer(timer_num, prescaler = 41, period = 15000)
        motortim.callback(self.cb)        
   
    def test(self, _):
        self.pin_id.high()
        self.pin_id.low()
    
    @micropython.asm_thumb
    def motor_step():
        movwt(r0, stm.GPIOA)
        movw(r1, 1 << 6)
        strh(r1, [r0, stm.GPIO_BSRRL])
        movwt(r4, 30)
        label(delay_off)
        sub(r4, r4, 1)
        cmp(r4, 0)
        bgt(delay_off) 
        strh(r1, [r0, stm.GPIO_BSRRH])
    
    def speed_change(self, motperiod):
        pyb.Timer(self.timer_num, prescaler = 41, period = motperiod)

    def cb(self, tim):
        if self.mdir != 0:
            self.motor_step()

    def dir_change(self,_dir):
        self.mdir = _dir

User avatar
Roberthh
Posts: 3667
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: Inline assembly in callback

Post by Roberthh » Wed May 30, 2018 7:32 pm

If the naming in assembler is too tricky, you could use viper code. It typically needs twice the time of assembler code, but you can create simple variables, give them the names you like and use the control structure of Python-

stromgald
Posts: 4
Joined: Fri Jan 19, 2018 4:57 am

Re: Inline assembly in callback

Post by stromgald » Wed May 30, 2018 11:49 pm

Thanks Robert. Viper did the trick!
*edit original code i posted wasn't doing what i wanted. The whole port was changing state. This one works. For loop gives ~1us delay.

Code: Select all

def motor_step(self):
        gpioa = ptr16(stm.GPIOA + stm.GPIO_BSRR)
        x7bit = 1 << 6  # X7 is Bit 6 of Port A
        gpioa[0] = x7bit
        for i in range(1, 6):
            i
        gpioa[1] = x7bit
is what i used for the callback function.
One more question, I need the pulse to be just over 1us and right now it's maybe 20ns. In the assembler i was using

Code: Select all

movwt(r4, 30)
label(delay_off)
sub(r4, r4, 1)
cmp(r4, 0)
bgt(delay_off) 
Is there a way to do something similar in Viper? Sleep_us takes a bit too long. I haven't been able to find too much documentation/examples on Viper. Thanks.
Last edited by stromgald on Sat Jun 02, 2018 8:48 pm, edited 1 time in total.

User avatar
Roberthh
Posts: 3667
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: Inline assembly in callback

Post by Roberthh » Thu May 31, 2018 7:15 am

You can do the same in viper with a short loop. You may have to disable irq for that, to make to stable.
There are a few words about viper in the docs: http://docs.micropython.org/en/latest/p ... de-emitter

Post Reply