Page 1 of 1

Inline assembly in callback

Posted: Wed May 30, 2018 7:04 pm
by stromgald
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

Re: Inline assembly in callback

Posted: Wed May 30, 2018 7:32 pm
by Roberthh
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-

Re: Inline assembly in callback

Posted: Wed May 30, 2018 11:49 pm
by stromgald
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.

Re: Inline assembly in callback

Posted: Thu May 31, 2018 7:15 am
by Roberthh
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