# for micropython 1.14 2021-02-05 from machine import Pin, Timer, UART, mem32 # the co-routine (tasking) package # see # https://docs.micropython.org/en/latest/library/uasyncio.html import uasyncio as asyncio import _thread import time import array from ctypes import addressof #====================================== # register adddresses for multicore # datasheet page 40 sio_base = 0xd0000000 # returns 0/1 depending on CORE id cpu_id_reg = sio_base # FiFO reggisters for both cores fifo_rd = sio_base + 0x058 fifo_wr = sio_base + 0x054 fifo_st = sio_base + 0x050 fifo_st_wr_rdy_bit = 0x002 fifo_st_rd_rdy_bit = 0x001 # spinlock base and lock zero # addd 4 for each sequential spinlock reg spin_base = sio_base + 0x100 #signal from core0 to core1 run_Thread = True # # ===================================== # === CORE to CORE fifo functions # blocking fifo read def fifo_rd_blk(): while not (mem32[fifo_st] & fifo_st_rd_rdy_bit) : pass fifo_data = mem32[fifo_rd] return fifo_data # blocking fifo write def fifo_wr_blk(fifo_data): while not (mem32[fifo_st] & fifo_st_wr_rdy_bit) : pass mem32[fifo_wr] = fifo_data # returns True if ready def fifo_wr_ready(): return (mem32[fifo_st] & fifo_st_wr_rdy_bit)>0 # returns True if ready def fifo_rd_ready(): return (mem32[fifo_st] & fifo_st_rd_rdy_bit)>0 #======================================= # CORE to CORE spinlock functions # lock number 0 to 31 # Blocks if second arameter is True # returns True if you get the lock, False if you don't def spin_acquire(lock_num, block): state = mem32[spin_base + 4 * lock_num] while state == 0 and block: pass return state != 0 # write anything to release lock def spin_release(lock_num): mem32[spin_base + 4 * lock_num] = 0 #======================================= # set up CORE 1 thread # the thread def CORE1_task(f): global shared_golbal led14 = Pin(14,Pin.OUT) led13 = Pin(13,Pin.OUT) # which core ? print('CORE1? ', machine.mem32[cpu_id_reg], 'start') # share memory from core0 addr_share_mem = fifo_rd_blk() # shoould print shared_mem[1] (see other core) print('shared[1]=',mem32[addr_share_mem+4]) while(run_Thread): # memory protect sp = spin_acquire(0, True) mem32[addr_share_mem] += 1 shared_var[0] += 1 shared_golbal += 1 spin_release(0) # n increments by two on shared memory print('CORE', machine.mem32[cpu_id_reg], mem32[addr_share_mem], shared_var[0], shared_golbal) led14.toggle() # time.sleep_ms(200) # start CORE 1 def start_CORE1(): _thread.start_new_thread(CORE1_task, (500,)) #======================================= # set up CORE 0 multitasking (CORO) # on obard LED led25 = Pin(25,Pin.OUT) # one set of possible UART0 pins uart_tx = machine.Pin(16) uart_rx = machine.Pin(17) # map the pins to the internal signals uart = UART(0, tx=uart_tx, rx=uart_rx) # global vaariable for both cores # arrays appear to be global, normal vars NOT shared_var = array.array('i', [0,]) # this variable is also global #shared_golbal -- # !!marked global in both threads!! shared_golbal = 0 # Task to read/write to uart # I could not get StreamReader to work async def receiver(uart): while True: swriter = asyncio.StreamWriter(uart, {}) last_char = '' cmd = '' # throw awy any junk characters if (uart.any()): res = uart.read(1) # while last_char != '\r': await asyncio.sleep(0) if (uart.any()): res = uart.read(1) last_char = res.decode('UTF-8') cmd = cmd + last_char # echo typing swriter.write(last_char) await swriter.drain() # print to console for testing #print (cmd) # print to uart swriter.write('\r\n>' + cmd + '\r\n') await swriter.drain() await asyncio.sleep(0.0) # heart beat to show tasks still executing async def toggle(led25, time_ms): # define an array to share with other core1 share_mem = array.array('i', [0, 20, 30]) global shared_golbal # and share the pointer addr_share_mem = addressof(share_mem) fifo_wr_blk(addr_share_mem) # avoid deadlock spin_release(0) while True: await asyncio.sleep_ms(600) led25.toggle() # read n from the ther core sp = spin_acquire(0, True) share_mem[0] += 1 shared_var[0] += 1 shared_golbal += 1 spin_release(0) # define the tasks async def main(): # start CORE 0 tasks t = 500 # runs as fast at 10 mSec, probably fasterr asyncio.create_task(toggle(led25, t)) asyncio.create_task(receiver(uart)) # get the CORE ID print('CORE0? ', machine.mem32[cpu_id_reg], ' start') # === thread strt === start_CORE1() # =================== while True: await asyncio.sleep_ms(1000) def test(): try: asyncio.run(main()) except KeyboardInterrupt: # cntl-c stops the program run_Thread = False print('Interrupted') #time.sleep(1) finally: # reset event loop asyncio.new_event_loop() # Start! test()