I thought I understood ldrex/strex thanks to your description, but now I'm not so sure. The following code shows that the interrupt handler is acquiring the lock when I'd have thought it should always fail.
Code: Select all
import pyb, micropython, array, uctypes
micropython.alloc_emergency_exception_buf(100)
class Foo:
def __init__(self):
self.lockword = array.array('i', (0,))
@micropython.asm_thumb
def _test(r0, r1): # Called from ISR context
ldrex(r0, [r1, 0])
strex(r0, r0, [r1, 0]) # Should always fail returning 1 (?)
def test(self):
return self._test(uctypes.addressof(self.lockword))
@micropython.asm_thumb
def _lock(r0, r1):
ldrex(r0, [r1, 0])
def lock(self):
self._lock(uctypes.addressof(self.lockword))
@micropython.asm_thumb
def _unlock(r0, r1):
mov(r0, 0)
strex(r0, r0, [r1, 0])
def unlock(self):
self._unlock(uctypes.addressof(self.lockword))
foo = Foo()
def update(t): # Interrupt handler records success or failure of strex
global can_lock, cannot_lock
if foo.test():
cannot_lock += 1
else:
can_lock += 1
def main():
global can_lock, cannot_lock
can_lock, cannot_lock = 0, 0
foo.lock() # does an ldrex which should cause the ISR test to fail
timer = pyb.Timer(4, freq = 1000, callback = update)
for x in range(10000):
pyb.delay(1)
if x % 1000 == 0:
print('Lock count {} fail count {}'.format(can_lock, cannot_lock))
timer.deinit()
foo.unlock() # strex to clear the lock
main()
Code: Select all
>>>
PYB: sync filesystems
PYB: soft reboot
MicroPython v1.5-60-g1657345-dirty on 2015-10-31; PYBv1.0 with STM32F405RG
Type "help()" for more information.
>>> import rats11
Lock count 0 fail count 0
Lock count 1000 fail count 0
Lock count 2000 fail count 0
Lock count 3000 fail count 0
Lock count 4000 fail count 0
Lock count 5000 fail count 0
Lock count 6000 fail count 0
Lock count 7000 fail count 0
Lock count 8000 fail count 0
Lock count 9000 fail count 0
>>>