Select one of the symbols to view example projects that use it.
 
Outline
#define _HARDWARE_BOOT_LOCK_H
#include "pico.h"
#define PARAM_ASSERTIONS_ENABLED_HARDWARE_BOOT_LOCK
#include "hardware/sync.h"
#include "hardware/structs/bootram.h"
boot_lock_t
boot_lock_instance(uint)
boot_lock_get_num(boot_lock_t *)
boot_lock_unsafe_blocking(boot_lock_t *)
boot_try_lock_unsafe(boot_lock_t *)
boot_unlock_unsafe(boot_lock_t *)
boot_lock_blocking(boot_lock_t *)
is_boot_locked(boot_lock_t *)
boot_unlock(boot_lock_t *, uint32_t)
boot_lock_init(uint);
boot_locks_reset();
Files
loading...
SourceVuRaspberry Pi Pico SDK and ExamplesPicoSDKsrc/rp2_common/hardware_boot_lock/include/hardware/boot_lock.h
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
/* * Copyright (c) 2024 Raspberry Pi (Trading) Ltd. * * SPDX-License-Identifier: BSD-3-Clause *//* ... */ #ifndef _HARDWARE_BOOT_LOCK_H #define _HARDWARE_BOOT_LOCK_H #include "pico.h" // PICO_CONFIG: PARAM_ASSERTIONS_ENABLED_HARDWARE_BOOT_LOCK, Enable/disable assertions in the hardware_boot_lock module, type=bool, default=0, group=hardware_boot_lock #ifndef PARAM_ASSERTIONS_ENABLED_HARDWARE_BOOT_LOCK #define PARAM_ASSERTIONS_ENABLED_HARDWARE_BOOT_LOCK 0 #endif #if NUM_BOOT_LOCKS > 0 #include "hardware/sync.h" #include "hardware/structs/bootram.h" /** \brief A boot lock identifier * \ingroup hardware_sync *//* ... */ typedef volatile uint32_t boot_lock_t; /*! \brief Get HW Bootlock instance from number * \ingroup hardware_sync * * \param lock_num Bootlock ID * \return The bootlock instance *//* ... */ __force_inline static boot_lock_t *boot_lock_instance(uint lock_num) { invalid_params_if(HARDWARE_BOOT_LOCK, lock_num >= NUM_BOOT_LOCKS); return (boot_lock_t *) (BOOTRAM_BASE + BOOTRAM_BOOTLOCK0_OFFSET + lock_num * 4); }{ ... } /*! \brief Get HW Bootlock number from instance * \ingroup hardware_sync * * \param lock The Bootlock instance * \return The Bootlock ID *//* ... */ __force_inline static uint boot_lock_get_num(boot_lock_t *lock) { invalid_params_if(HARDWARE_BOOT_LOCK, (uint) lock < BOOTRAM_BASE + BOOTRAM_BOOTLOCK0_OFFSET || (uint) lock >= NUM_BOOT_LOCKS * sizeof(boot_lock_t) + BOOTRAM_BASE + BOOTRAM_BOOTLOCK0_OFFSET || ((uint) lock - BOOTRAM_BASE + BOOTRAM_BOOTLOCK0_OFFSET) % sizeof(boot_lock_t) != 0); return (uint) (lock - (boot_lock_t *) (BOOTRAM_BASE + BOOTRAM_BOOTLOCK0_OFFSET)); }{ ... } /*! \brief Acquire a boot lock without disabling interrupts (hence unsafe) * \ingroup hardware_sync * * \param lock Bootlock instance *//* ... */ __force_inline static void boot_lock_unsafe_blocking(boot_lock_t *lock) { // Note we don't do a wfe or anything, because by convention these boot_locks are VERY SHORT LIVED and NEVER BLOCK and run // with INTERRUPTS disabled (to ensure that)... therefore nothing on our core could be blocking us, so we just need to wait on another core // anyway which should be finished soon while (__builtin_expect(!*lock, 0)) { // read from bootlock register (tries to acquire the lock) tight_loop_contents(); }while (__builtin_expect(!*lock, 0)) { ... } __mem_fence_acquire(); }{ ... } /*! \brief try to acquire a boot lock without disabling interrupts (hence unsafe) * \ingroup hardware_sync * * \param lock Bootlock instance *//* ... */ __force_inline static bool boot_try_lock_unsafe(boot_lock_t *lock) { if (*lock) { __mem_fence_acquire(); return true; }if (*lock) { ... } return false; }{ ... } /*! \brief Release a boot lock without re-enabling interrupts * \ingroup hardware_sync * * \param lock Bootlock instance *//* ... */ __force_inline static void boot_unlock_unsafe(boot_lock_t *lock) { __mem_fence_release(); *lock = 0; // write to bootlock register (release lock) }{ ... } /*! \brief Acquire a boot lock safely * \ingroup hardware_sync * * This function will disable interrupts prior to acquiring the bootlock * * \param lock Bootlock instance * \return interrupt status to be used when unlocking, to restore to original state *//* ... */ __force_inline static uint32_t boot_lock_blocking(boot_lock_t *lock) { uint32_t save = save_and_disable_interrupts(); boot_lock_unsafe_blocking(lock); return save; }{ ... } /*! \brief Check to see if a bootlock is currently acquired elsewhere. * \ingroup hardware_sync * * \param lock Bootlock instance *//* ... */ inline static bool is_boot_locked(boot_lock_t *lock) { check_hw_size(boot_lock_t, 4); uint lock_num = boot_lock_get_num(lock); return 0 != (*(io_ro_32 *) (BOOTRAM_BASE + BOOTRAM_BOOTLOCK_STAT_OFFSET) & (1u << lock_num)); }{ ... } /*! \brief Release a boot lock safely * \ingroup hardware_sync * * This function will re-enable interrupts according to the parameters. * * \param lock Bootlock instance * \param saved_irq Return value from the \ref boot_lock_blocking() function. * * \sa boot_lock_blocking() *//* ... */ __force_inline static void boot_unlock(boot_lock_t *lock, uint32_t saved_irq) { boot_unlock_unsafe(lock); restore_interrupts_from_disabled(saved_irq); }{ ... } /*! \brief Initialise a boot lock * \ingroup hardware_sync * * The boot lock is initially unlocked * * \param lock_num The boot lock number * \return The boot lock instance *//* ... */ boot_lock_t *boot_lock_init(uint lock_num); /*! \brief Release all boot locks * \ingroup hardware_sync *//* ... */ void boot_locks_reset(void); /* ... */ #endif/* ... */ #endif
Details