====== Lab 07 ====== ===== Exercise Objectives ===== * Introduce multithreading on Pico ===== Introduction ===== RP2040 microcontroler has two Cortex-M0 cores, ''Core0'' and ''Core1''. In the default mode of Raspberry Pi Pico program execution, ''Core0'' executes all the tasks and ''Core1'' remains idle or on standby mode. Using both the cores of RP2040 provides us with two threads of execution and hence a more powerful project with better processing speed. Both ''Core0'' and ''Core1'' execute their assigned tasks independent of each other while sharing all the resources like memory space and program code with each other. Sharing the memory location between two cores can create race conditions and hence can cause trouble when mutual memory accessing is not assured. On the other hand, sharing program code with each other (''Core0'' and ''Core1'') may sound troublesome but practically it is not. The reason is fetching code is a read instruction that does not create a race condition. ==== Library _thread ==== In order to run a parallel process on a microcontroller, it is necessary to use a suitable library that activates Core1. In MicroPython, the [[https://docs.python.org/3.5/library/_thread.html#module-_thread|_thread]] library is available, which provides basic functionality that allows a user to work with multiple threads and also allow them to share global data space. ===== Examples ===== ==== Simple theads ==== from machine import Pin import utime import _thread We configure the pin of the internal led as an output and we assign to ''led''. led = Pin(25, Pin.OUT) Function that will block the thread with a while loop which will simply display a message every second def second_thread(): while True: print("Hello, I'm here in the second thread writting every second") utime.sleep(1) Function ''_thread.start_new_thread'' initializes execution in the second core. The second argument is a list or dictionary with the arguments that will be passed to the function. _thread.start_new_thread(second_thread, ()) Second loop that will block the main thread, and what it will do that the internal led blinks every half second. while True: led.toggle() utime.sleep(0.25) ==== Race condition ==== import _thread from utime import sleep def core0_thread(): global lock while True: lock.acquire() print('o', end="") sleep(0.25) print('n', end="") sleep(0.25) print('e', end="") sleep(0.25) print() lock.release() def core1_thread(): global lock while True: # lock.acquire() print('s', end="") sleep(0.25) print('i', end="") sleep(0.25) print('x', end="") sleep(0.25) print() # lock.release() lock = _thread.allocate_lock() second_thread = _thread.start_new_thread(core1_thread, ()) core0_thread()