1 /*
2  * Copyright (c) 2020 Raspberry Pi (Trading) Ltd.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  */
6 
7 #ifndef _HARDWARE_CLAIM_H
8 #define _HARDWARE_CLAIM_H
9 
10 #include "pico.h"
11 #include "hardware/sync.h"
12 
13 /** \file claim.h
14  *  \defgroup hardware_claim hardware_claim
15  *
16  *  Lightweight hardware resource management
17  *
18  * `hardware_claim` provides a simple API for management of hardware resources at runtime.
19  *
20  * This API is usually called by other hardware specific _claiming_ APIs and provides simple
21  * multi-core safe methods to manipulate compact bit-sets representing hardware resources.
22  *
23  * This API allows any other library to cooperatively participate in a scheme by which
24  * both compile time and runtime allocation of resources can co-exist, and conflicts
25  * can be avoided or detected (depending on the use case) without the libraries having
26  * any other knowledge of each other.
27  *
28  * Facilities are providing for:
29  *
30  * 1. Claiming resources (and asserting if they are already claimed)
31  * 2. Freeing (unclaiming) resources
32  * 3. Finding unused resources
33  */
34 
35 #ifdef __cplusplus
36 extern "C" {
37 #endif
38 
39 /*! \brief Atomically claim a resource, panicking if it is already in use
40  *  \ingroup hardware_claim
41  *
42  * The resource ownership is indicated by the bit_index bit in an array of bits.
43  *
44  * \param bits pointer to an array of bits (8 bits per byte)
45  * \param bit_index resource to claim (bit index into array of bits)
46  * \param message string to display if the bit cannot be claimed; note this may have a single printf format "%d" for the bit
47  */
48 void hw_claim_or_assert(uint8_t *bits, uint bit_index, const char *message);
49 
50 /*! \brief Atomically claim one resource out of a range of resources, optionally asserting if none are free
51  *  \ingroup hardware_claim
52  *
53  * \param bits pointer to an array of bits (8 bits per byte)
54  * \param required true if this method should panic if the resource is not free
55  * \param bit_lsb the lower bound (inclusive) of the resource range to claim from
56  * \param bit_msb the upper bound (inclusive) of the resource range to claim from
57  * \param message string to display if the bit cannot be claimed
58  * \return the bit index representing the claimed or -1 if none are available in the range, and required = false
59  */
60 int hw_claim_unused_from_range(uint8_t *bits, bool required, uint bit_lsb, uint bit_msb, const char *message);
61 
62 /*! \brief Determine if a resource is claimed at the time of the call
63  *  \ingroup hardware_claim
64  *
65  * The resource ownership is indicated by the bit_index bit in an array of bits.
66  *
67  * \param bits pointer to an array of bits (8 bits per byte)
68  * \param bit_index resource to check (bit index into array of bits)
69  * \return true if the resource is claimed
70  */
71 bool hw_is_claimed(const uint8_t *bits, uint bit_index);
72 
73 /*! \brief Atomically unclaim a resource
74  *  \ingroup hardware_claim
75  *
76  * The resource ownership is indicated by the bit_index bit in an array of bits.
77  *
78  * \param bits pointer to an array of bits (8 bits per byte)
79  * \param bit_index resource to unclaim (bit index into array of bits)
80  */
81 void hw_claim_clear(uint8_t *bits, uint bit_index);
82 
83 /*! \brief Acquire the runtime mutual exclusion lock provided by the `hardware_claim` library
84  *  \ingroup hardware_claim
85  *
86  * This method is called automatically by the other `hw_claim_` methods, however it is provided as a convenience
87  * to code that might want to protect other hardware initialization code from concurrent use.
88  *
89  * \note hw_claim_lock() uses a spin lock internally, so disables interrupts on the calling core, and will deadlock
90  * if the calling core already owns the lock.
91  *
92  * \return a token to pass to hw_claim_unlock()
93  */
94 uint32_t hw_claim_lock(void);
95 
96 /*! \brief Release the runtime mutual exclusion lock provided by the `hardware_claim` library
97  *  \ingroup hardware_claim
98  *
99  * \note This method MUST be called from the same core that call hw_claim_lock()
100  *
101  * \param token the token returned by the corresponding call to hw_claim_lock()
102  */
103 void hw_claim_unlock(uint32_t token);
104 
105 #ifdef __cplusplus
106 }
107 #endif
108 
109 #endif
110