Line data Source code
1 0 : /* 2 : * Copyright (c) 2023 Nordic Semiconductor ASA 3 : * 4 : * SPDX-License-Identifier: Apache-2.0 5 : */ 6 : 7 : #ifndef ZEPHYR_INCLUDE_IPC_PBUF_H_ 8 : #define ZEPHYR_INCLUDE_IPC_PBUF_H_ 9 : 10 : #include <zephyr/cache.h> 11 : #include <zephyr/devicetree.h> 12 : 13 : #ifdef __cplusplus 14 : extern "C" { 15 : #endif 16 : 17 : /** 18 : * @brief Packed buffer API 19 : * @defgroup pbuf Packed Buffer API 20 : * @ingroup ipc 21 : * @{ 22 : */ 23 : 24 : /** @brief Size of packet length field. */ 25 1 : #define PBUF_PACKET_LEN_SZ sizeof(uint32_t) 26 : 27 : /* Amount of data that is left unused to distinguish between empty and full. */ 28 : #define _PBUF_IDX_SIZE sizeof(uint32_t) 29 : 30 : /* Minimal length of the data field in the buffer to store the smalest packet 31 : * possible. 32 : * (+1) for at least one byte of data. 33 : * (+_PBUF_IDX_SIZE) to distinguish buffer full and buffer empty. 34 : * Rounded up to keep wr/rd indexes pointing to aligned address. 35 : */ 36 : #define _PBUF_MIN_DATA_LEN ROUND_UP(PBUF_PACKET_LEN_SZ + 1 + _PBUF_IDX_SIZE, _PBUF_IDX_SIZE) 37 : 38 : #if defined(CONFIG_ARCH_POSIX) 39 : /* For the native simulated boards we need to modify some pointers at init */ 40 : #define PBUF_MAYBE_CONST 41 : #else 42 0 : #define PBUF_MAYBE_CONST const 43 : #endif 44 : 45 : /** @brief Control block of packet buffer. 46 : * 47 : * The structure contains configuration data. 48 : */ 49 1 : struct pbuf_cfg { 50 0 : volatile uint32_t *rd_idx_loc; /* Address of the variable holding 51 : * index value of the first valid byte 52 : * in data[]. 53 : */ 54 0 : volatile uint32_t *wr_idx_loc; /* Address of the variable holding 55 : * index value of the first free byte 56 : * in data[]. 57 : */ 58 0 : uint32_t dcache_alignment; /* CPU data cache line size in bytes. 59 : * Used for validation - TODO: To be 60 : * replaced by flags. 61 : */ 62 0 : uint32_t len; /* Length of data[] in bytes. */ 63 0 : uint8_t *data_loc; /* Location of the data[]. */ 64 : }; 65 : 66 : /** 67 : * @brief Data block of the packed buffer. 68 : * 69 : * The structure contains local copies of wr and rd indexes used by writer and 70 : * reader respectively. 71 : */ 72 1 : struct pbuf_data { 73 0 : volatile uint32_t wr_idx; /* Index of the first holding first 74 : * free byte in data[]. Used for 75 : * writing. 76 : */ 77 0 : volatile uint32_t rd_idx; /* Index of the first holding first 78 : * valid byte in data[]. Used for 79 : * reading. 80 : */ 81 : }; 82 : 83 : 84 : /** 85 : * @brief Scure packed buffer. 86 : * 87 : * The packet buffer implements lightweight unidirectional packet 88 : * buffer with read/write semantics on top of a memory region shared 89 : * by the reader and writer. It embeds cache and memory barrier management to 90 : * ensure correct data access. 91 : * 92 : * This structure supports single writer and reader. Data stored in the buffer 93 : * is encapsulated to a message (with length header). The read/write API is 94 : * written in a way to protect the data from being corrupted. 95 : */ 96 1 : struct pbuf { 97 0 : PBUF_MAYBE_CONST struct pbuf_cfg *const cfg; /* Configuration of the 98 : * buffer. 99 : */ 100 0 : struct pbuf_data data; /* Data used to read and write 101 : * to the buffer 102 : */ 103 : }; 104 : 105 : /** 106 : * @brief Macro for configuration initialization. 107 : * 108 : * It is recommended to use this macro to initialize packed buffer 109 : * configuration. 110 : * 111 : * @param mem_addr Memory address for pbuf. 112 : * @param size Size of the memory. 113 : * @param dcache_align Data cache alignment. 114 : */ 115 1 : #define PBUF_CFG_INIT(mem_addr, size, dcache_align) \ 116 : { \ 117 : .rd_idx_loc = (uint32_t *)(mem_addr), \ 118 : .wr_idx_loc = (uint32_t *)((uint8_t *)(mem_addr) + \ 119 : MAX(dcache_align, _PBUF_IDX_SIZE)), \ 120 : .data_loc = (uint8_t *)((uint8_t *)(mem_addr) + \ 121 : MAX(dcache_align, _PBUF_IDX_SIZE) + _PBUF_IDX_SIZE), \ 122 : .len = (uint32_t)((uint32_t)(size) - MAX(dcache_align, _PBUF_IDX_SIZE) - \ 123 : _PBUF_IDX_SIZE), \ 124 : .dcache_alignment = (dcache_align), \ 125 : } 126 : 127 : /** 128 : * @brief Macro calculates memory overhead taken by the header in shared memory. 129 : * 130 : * It contains the read index, write index and padding. 131 : * 132 : * @param dcache_align Data cache alignment. 133 : */ 134 1 : #define PBUF_HEADER_OVERHEAD(dcache_align) \ 135 : (MAX(dcache_align, _PBUF_IDX_SIZE) + _PBUF_IDX_SIZE) 136 : 137 : /** 138 : * @brief Statically define and initialize pbuf. 139 : * 140 : * @param name Name of the pbuf. 141 : * @param mem_addr Memory address for pbuf. 142 : * @param size Size of the memory. 143 : * @param dcache_align Data cache line size. 144 : */ 145 1 : #define PBUF_DEFINE(name, mem_addr, size, dcache_align) \ 146 : BUILD_ASSERT(dcache_align >= 0, \ 147 : "Cache line size must be non negative."); \ 148 : BUILD_ASSERT((size) > 0 && IS_PTR_ALIGNED_BYTES(size, _PBUF_IDX_SIZE), \ 149 : "Incorrect size."); \ 150 : BUILD_ASSERT(IS_PTR_ALIGNED_BYTES(mem_addr, MAX(dcache_align, _PBUF_IDX_SIZE)), \ 151 : "Misaligned memory."); \ 152 : BUILD_ASSERT(size >= (MAX(dcache_align, _PBUF_IDX_SIZE) + _PBUF_IDX_SIZE + \ 153 : _PBUF_MIN_DATA_LEN), "Insufficient size."); \ 154 : static PBUF_MAYBE_CONST struct pbuf_cfg cfg_##name = \ 155 : PBUF_CFG_INIT(mem_addr, size, dcache_align); \ 156 : static struct pbuf name = { \ 157 : .cfg = &cfg_##name, \ 158 : } 159 : 160 : /** 161 : * @brief Initialize the Tx packet buffer. 162 : * 163 : * This function initializes the Tx packet buffer based on provided configuration. 164 : * If the configuration is incorrect, the function will return error. 165 : * 166 : * It is recommended to use PBUF_DEFINE macro for build time initialization. 167 : * 168 : * @param pb Pointer to the packed buffer containing 169 : * configuration and data. Configuration has to be 170 : * fixed before the initialization. 171 : * @retval 0 on success. 172 : * @retval -EINVAL when the input parameter is incorrect. 173 : */ 174 1 : int pbuf_tx_init(struct pbuf *pb); 175 : 176 : /** 177 : * @brief Initialize the Rx packet buffer. 178 : * 179 : * This function initializes the Rx packet buffer. 180 : * If the configuration is incorrect, the function will return error. 181 : * 182 : * It is recommended to use PBUF_DEFINE macro for build time initialization. 183 : * 184 : * @param pb Pointer to the packed buffer containing 185 : * configuration and data. Configuration has to be 186 : * fixed before the initialization. 187 : * @retval 0 on success. 188 : * @retval -EINVAL when the input parameter is incorrect. 189 : */ 190 1 : int pbuf_rx_init(struct pbuf *pb); 191 : 192 : /** 193 : * @brief Write specified amount of data to the packet buffer. 194 : * 195 : * This function call writes specified amount of data to the packet buffer if 196 : * the buffer will fit the data. 197 : * 198 : * @param pb A buffer to which to write. 199 : * @param buf Pointer to the data to be written to the buffer. 200 : * @param len Number of bytes to be written to the buffer. Must be positive. 201 : * @retval int Number of bytes written, negative error code on fail. 202 : * -EINVAL, if any of input parameter is incorrect. 203 : * -ENOMEM, if len is bigger than the buffer can fit. 204 : */ 205 : 206 1 : int pbuf_write(struct pbuf *pb, const char *buf, uint16_t len); 207 : 208 : /** 209 : * @brief Read specified amount of data from the packet buffer. 210 : * 211 : * Single read allows to read the message send by the single write. 212 : * The provided %p buf must be big enough to store the whole message. 213 : * 214 : * @param pb A buffer from which data will be read. 215 : * @param buf Data pointer to which read data will be written. 216 : * If NULL, len of stored message is returned. 217 : * @param len Number of bytes to be read from the buffer. 218 : * @retval int Bytes read, negative error code on fail. 219 : * Bytes to be read, if buf == NULL. 220 : * -EINVAL, if any of input parameter is incorrect. 221 : * -ENOMEM, if message can not fit in provided buf. 222 : * -EAGAIN, if not whole message is ready yet. 223 : */ 224 1 : int pbuf_read(struct pbuf *pb, char *buf, uint16_t len); 225 : 226 : /** 227 : * @} 228 : */ 229 : 230 : #ifdef __cplusplus 231 : } 232 : #endif 233 : 234 : #endif /* ZEPHYR_INCLUDE_IPC_PBUF_H_ */