Loading...
Searching...
No Matches
multicore.h
Go to the documentation of this file.
1/*
2 * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6
7#ifndef _PICO_MULTICORE_H
8#define _PICO_MULTICORE_H
9
10#include "pico/types.h"
11#include "pico/sync.h"
12#include "hardware/structs/sio.h"
13
14#ifdef __cplusplus
15extern "C" {
16#endif
17
18// PICO_CONFIG: PARAM_ASSERTIONS_ENABLED_PICO_MULTICORE, Enable/disable assertions in the pico_multicore module, type=bool, default=0, group=pico_multicore
19#ifndef PARAM_ASSERTIONS_ENABLED_PICO_MULTICORE
20#define PARAM_ASSERTIONS_ENABLED_PICO_MULTICORE 0
21#endif
22
31
32// PICO_CONFIG: PICO_CORE1_STACK_SIZE, Minimum amount of stack space reserved in the linker script for core 1 - if zero then no space is reserved and the user must provide their own stack, min=0, max=0x10000, default=PICO_STACK_SIZE (0x800), group=pico_multicore
33#ifndef PICO_CORE1_STACK_SIZE
34#ifdef PICO_STACK_SIZE
35#define PICO_CORE1_STACK_SIZE PICO_STACK_SIZE
36#else
37#define PICO_CORE1_STACK_SIZE 0x800
38#endif
39#endif
40
41// PICO_CONFIG: PICO_MULTICORE_LOCKOUT_BEFORE_CORE1_STARTED, Allow multicore_lockout functions called from core 0 to succeed if core1 has not been started, type=bool, default=1, group=pico_multicore
42#ifndef PICO_MULTICORE_LOCKOUT_BEFORE_CORE1_STARTED
43#define PICO_MULTICORE_LOCKOUT_BEFORE_CORE1_STARTED 1
44#endif
45
62#ifndef SIO_FIFO_IRQ_NUM
63#if !PICO_RP2040
64#define SIO_FIFO_IRQ_NUM(core) SIO_IRQ_FIFO
65#else
66static_assert(SIO_IRQ_PROC1 == SIO_IRQ_PROC0 + 1, "");
67#define SIO_FIFO_IRQ_NUM(core) (SIO_IRQ_PROC0 + (core))
68#endif
69#endif
70
78void multicore_reset_core1(void);
79
92void multicore_launch_core1(void (*entry)(void));
93
108void multicore_launch_core1_with_stack(void (*entry)(void), uint32_t *stack_bottom, size_t stack_size_bytes);
109
125void multicore_launch_core1_raw(void (*entry)(void), uint32_t *sp, uint32_t vector_table);
126
142
150static inline bool multicore_fifo_rvalid(void) {
151 return sio_hw->fifo_st & SIO_FIFO_ST_VLD_BITS;
152}
153
161static inline bool multicore_fifo_wready(void) {
162 return sio_hw->fifo_st & SIO_FIFO_ST_RDY_BITS;
163}
164
176void multicore_fifo_push_blocking(uint32_t data);
177
189static inline void multicore_fifo_push_blocking_inline(uint32_t data) {
190 // We wait for the fifo to have some space
191 while (!multicore_fifo_wready())
193
194 sio_hw->fifo_wr = data;
195
196 // Fire off an event to the other core
197 __sev();
198}
199
210bool multicore_fifo_push_timeout_us(uint32_t data, uint64_t timeout_us);
211
223uint32_t multicore_fifo_pop_blocking(void);
224
236static inline uint32_t multicore_fifo_pop_blocking_inline(void) {
237 // If nothing there yet, we wait for an event first,
238 // to try and avoid too much busy waiting
239 while (!multicore_fifo_rvalid())
240 __wfe();
241
242 return sio_hw->fifo_rd;
243}
244
256bool multicore_fifo_pop_timeout_us(uint64_t timeout_us, uint32_t *out);
257
263static inline void multicore_fifo_drain(void) {
264 while (multicore_fifo_rvalid())
265 (void) sio_hw->fifo_rd;
266}
267
278static inline void multicore_fifo_clear_irq(void) {
279 // Write any value to clear the error flags
280 sio_hw->fifo_st = 0xff;
281}
282
298static inline uint32_t multicore_fifo_get_status(void) {
299 return sio_hw->fifo_st;
300}
301
311
312#if NUM_DOORBELLS
313static inline void check_doorbell_num_param(__unused uint doorbell_num) {
314 invalid_params_if(PICO_MULTICORE, doorbell_num >= NUM_DOORBELLS);
315}
316
317static inline void check_core_mask_param(__unused uint core_mask) {
318 invalid_params_if(PICO_MULTICORE, core_mask >= (1u << NUM_CORES));
319}
320
330void multicore_doorbell_claim(uint doorbell_num, uint core_mask);
331
342int multicore_doorbell_claim_unused(uint core_mask, bool required);
343
351void multicore_doorbell_unclaim(uint doorbell_num, uint core_mask);
352
357static inline void multicore_doorbell_set_other_core(uint doorbell_num) {
358 check_doorbell_num_param(doorbell_num);
359 sio_hw->doorbell_out_set = 1u << doorbell_num;
360}
361
366static inline void multicore_doorbell_clear_other_core(uint doorbell_num) {
367 check_doorbell_num_param(doorbell_num);
368 sio_hw->doorbell_out_clr = 1u << doorbell_num;
369}
370
375static inline void multicore_doorbell_set_current_core(uint doorbell_num) {
376 check_doorbell_num_param(doorbell_num);
377 sio_hw->doorbell_in_set = 1u << doorbell_num;
378}
379
384static inline void multicore_doorbell_clear_current_core(uint doorbell_num) {
385 check_doorbell_num_param(doorbell_num);
386 sio_hw->doorbell_in_clr = 1u << doorbell_num;
387}
388
393static inline bool multicore_doorbell_is_set_current_core(uint doorbell_num) {
394 check_doorbell_num_param(doorbell_num);
395 return sio_hw->doorbell_in_set & (1u << doorbell_num);
396}
397
402static inline bool multicore_doorbell_is_set_other_core(uint doorbell_num) {
403 check_doorbell_num_param(doorbell_num);
404 return sio_hw->doorbell_out_set & (1u << doorbell_num);
405}
406
415#ifndef DOORBELL_IRQ_NUM
416#define DOORBELL_IRQ_NUM(doorbell_num) SIO_IRQ_BELL
417#endif
418
419static inline uint multicore_doorbell_irq_num(uint doorbell_num) {
420 check_doorbell_num_param(doorbell_num);
421 return DOORBELL_IRQ_NUM(doorbell_num);
422}
423
424#endif
425
459
466
473
485
496bool multicore_lockout_ready(void);
497
507
519bool multicore_lockout_start_timeout_us(uint64_t timeout_us);
520
532
547bool multicore_lockout_end_timeout_us(uint64_t timeout_us);
548
549#ifdef __cplusplus
550}
551#endif
552#endif
static __force_inline void __sev(void)
Insert a SEV instruction in to the code path.
Definition sync.h:96
static __force_inline void __wfe(void)
Insert a WFE instruction in to the code path.
Definition sync.h:115
static bool multicore_doorbell_is_set_other_core(uint doorbell_num)
Determine if the given doorbell is active on the other core.
Definition multicore.h:402
static void multicore_doorbell_clear_current_core(uint doorbell_num)
Deactivate the given doorbell on this core.
Definition multicore.h:384
void multicore_doorbell_claim(uint doorbell_num, uint core_mask)
Cooperatively claim the use of this doorbell.
Definition multicore.c:420
static void multicore_doorbell_clear_other_core(uint doorbell_num)
Deactivate the given doorbell on the other core.
Definition multicore.h:366
#define DOORBELL_IRQ_NUM(doorbell_num)
Returns the irq_num_t for processor interrupts for the given doorbell number.
Definition multicore.h:416
int multicore_doorbell_claim_unused(uint core_mask, bool required)
Cooperatively claim the use of an unused doorbell.
Definition multicore.c:428
static void multicore_doorbell_set_other_core(uint doorbell_num)
Activate the given doorbell on the other core.
Definition multicore.h:357
static void multicore_doorbell_set_current_core(uint doorbell_num)
Activate the given doorbell on this core.
Definition multicore.h:375
void multicore_doorbell_unclaim(uint doorbell_num, uint core_mask)
Cooperatively release the claim on use of this doorbell.
Definition multicore.c:445
static bool multicore_doorbell_is_set_current_core(uint doorbell_num)
Determine if the given doorbell is active on this core.
Definition multicore.h:393
bool multicore_fifo_push_timeout_us(uint32_t data, uint64_t timeout_us)
Push data on to the write FIFO (data to the other core) with timeout.
Definition multicore.c:49
void multicore_fifo_push_blocking(uint32_t data)
Push data on to the write FIFO (data to the other core).
Definition multicore.c:45
bool multicore_fifo_pop_timeout_us(uint64_t timeout_us, uint32_t *out)
Pop data from the read FIFO (data from the other core) with timeout.
Definition multicore.c:68
static uint32_t multicore_fifo_pop_blocking_inline(void)
Pop data from the read FIFO (data from the other core).
Definition multicore.h:236
static void multicore_fifo_drain(void)
Discard any data in the read FIFO.
Definition multicore.h:263
static void multicore_fifo_push_blocking_inline(uint32_t data)
Push data on to the write FIFO (data to the other core).
Definition multicore.h:189
static bool multicore_fifo_wready(void)
Check the write FIFO to see if it has space for more data.
Definition multicore.h:161
static uint32_t multicore_fifo_get_status(void)
Get FIFO statuses.
Definition multicore.h:298
uint32_t multicore_fifo_pop_blocking(void)
Pop data from the read FIFO (data from the other core).
Definition multicore.c:64
static void multicore_fifo_clear_irq(void)
Clear FIFO interrupt.
Definition multicore.h:278
static bool multicore_fifo_rvalid(void)
Check the read FIFO to see if there is data available (sent by the other core).
Definition multicore.h:150
bool multicore_lockout_victim_is_initialized(uint core_num)
Determine if multicore_lockout_victim_init() has been called on the specified core.
Definition multicore.c:370
void multicore_lockout_victim_init(void)
Initialize the current core such that it can be a "victim" of lockout (i.e. forced to pause in a know...
Definition multicore.c:259
void multicore_lockout_victim_deinit(void)
Stop the current core being able to be a "victim" of lockout (i.e. forced to pause in a known state b...
Definition multicore.c:270
void multicore_lockout_start_blocking(void)
Request the other core to pause in a known state and wait for it to do so.
Definition multicore.c:347
bool multicore_lockout_start_timeout_us(uint64_t timeout_us)
Request the other core to pause in a known state and wait up to a time limit for it to do so.
Definition multicore.c:343
void multicore_lockout_end_blocking(void)
Release the other core from a locked out state.
Definition multicore.c:366
bool multicore_lockout_ready(void)
Determine whether it is safe to call multicore_lockout_start functions from this core.
Definition multicore.c:374
bool multicore_lockout_end_timeout_us(uint64_t timeout_us)
Release the other core from a locked out state.
Definition multicore.c:362
void multicore_launch_core1(void(*entry)(void))
Run code on core 1.
Definition multicore.c:176
void multicore_launch_core1_with_stack(void(*entry)(void), uint32_t *stack_bottom, size_t stack_size_bytes)
Launch code on core 1 with stack.
Definition multicore.c:153
void multicore_launch_core1_raw(void(*entry)(void), uint32_t *sp, uint32_t vector_table)
Launch code on core 1 with no stack protection.
Definition multicore.c:188
void multicore_reset_core1(void)
Reset core 1.
Definition multicore.c:113
static __force_inline void tight_loop_contents(void)
No-op function for the body of tight loops.
Definition common.h:79