1 /* 2 * Copyright (c) 2024 Nordic Semiconductor ASA 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7 /** 8 * @file 9 * @brief Buffers for USB device support 10 */ 11 12 #ifndef ZEPHYR_INCLUDE_UDC_BUF_H 13 #define ZEPHYR_INCLUDE_UDC_BUF_H 14 15 #include <zephyr/kernel.h> 16 #include <zephyr/net_buf.h> 17 18 #if defined(CONFIG_DCACHE) && !defined(CONFIG_UDC_BUF_FORCE_NOCACHE) 19 /* 20 * Here we try to get DMA-safe buffers, but we lack a consistent source of 21 * information about data cache properties, such as line cache size, and a 22 * consistent source of information about what part of memory is DMA'able. 23 * For now, we simply assume that all available memory is DMA'able and use 24 * Kconfig option DCACHE_LINE_SIZE for alignment and granularity. 25 */ 26 #define Z_UDC_BUF_ALIGN CONFIG_DCACHE_LINE_SIZE 27 #define Z_UDC_BUF_GRANULARITY CONFIG_DCACHE_LINE_SIZE 28 #else 29 /* 30 * Default alignment and granularity to pointer size if the platform does not 31 * have a data cache or buffers are placed in nocache memory region. 32 */ 33 #define Z_UDC_BUF_ALIGN sizeof(void *) 34 #define Z_UDC_BUF_GRANULARITY sizeof(void *) 35 #endif 36 37 38 #if defined(CONFIG_UDC_BUF_FORCE_NOCACHE) 39 /* 40 * The usb transfer buffer needs to be in __nocache section 41 */ 42 #define Z_UDC_BUF_SECTION __nocache 43 #else 44 #define Z_UDC_BUF_SECTION 45 #endif 46 47 /** 48 * @brief Buffer macros and definitions used in USB device support 49 * @defgroup udc_buf Buffer macros and definitions used in USB device support 50 * @ingroup usb 51 * @since 4.0 52 * @version 0.1.0 53 * @{ 54 */ 55 56 /** Buffer alignment required by the UDC driver */ 57 #define UDC_BUF_ALIGN Z_UDC_BUF_ALIGN 58 59 /** Buffer granularity required by the UDC driver */ 60 #define UDC_BUF_GRANULARITY Z_UDC_BUF_GRANULARITY 61 62 /** 63 * @brief Define a UDC driver-compliant static buffer 64 * 65 * This macro should be used if the application defines its own buffers to be 66 * used for USB transfers. 67 * 68 * @param name Buffer name 69 * @param size Buffer size 70 */ 71 #define UDC_STATIC_BUF_DEFINE(name, size) \ 72 static uint8_t Z_UDC_BUF_SECTION __aligned(UDC_BUF_ALIGN) \ 73 name[ROUND_UP(size, UDC_BUF_GRANULARITY)]; 74 75 /** 76 * @brief Verify that the buffer is aligned as required by the UDC driver 77 * 78 * @see IS_ALIGNED 79 * 80 * @param buf Buffer pointer 81 */ 82 #define IS_UDC_ALIGNED(buf) IS_ALIGNED(buf, UDC_BUF_ALIGN) 83 84 /** 85 * @cond INTERNAL_HIDDEN 86 */ 87 #define UDC_HEAP_DEFINE(name, bytes, in_section) \ 88 uint8_t in_section __aligned(UDC_BUF_ALIGN) \ 89 kheap_##name[MAX(bytes, Z_HEAP_MIN_SIZE)]; \ 90 STRUCT_SECTION_ITERABLE(k_heap, name) = { \ 91 .heap = { \ 92 .init_mem = kheap_##name, \ 93 .init_bytes = MAX(bytes, Z_HEAP_MIN_SIZE), \ 94 }, \ 95 } 96 97 #define UDC_K_HEAP_DEFINE(name, size) \ 98 COND_CODE_1(CONFIG_UDC_BUF_FORCE_NOCACHE, \ 99 (UDC_HEAP_DEFINE(name, size, __nocache)), \ 100 (UDC_HEAP_DEFINE(name, size, __noinit))) 101 102 extern const struct net_buf_data_cb net_buf_dma_cb; 103 /** @endcond */ 104 105 /** 106 * @brief Define a new pool for UDC buffers with variable-size payloads 107 * 108 * This macro is similar to `NET_BUF_POOL_VAR_DEFINE`, but provides buffers 109 * with alignment and granularity suitable for use by UDC driver. 110 * 111 * @see NET_BUF_POOL_VAR_DEFINE 112 * 113 * @param pname Name of the pool variable. 114 * @param count Number of buffers in the pool. 115 * @param size Maximum data payload per buffer. 116 * @param ud_size User data space to reserve per buffer. 117 * @param fdestroy Optional destroy callback when buffer is freed. 118 */ 119 #define UDC_BUF_POOL_VAR_DEFINE(pname, count, size, ud_size, fdestroy) \ 120 _NET_BUF_ARRAY_DEFINE(pname, count, ud_size); \ 121 UDC_K_HEAP_DEFINE(net_buf_mem_pool_##pname, size); \ 122 static const struct net_buf_data_alloc net_buf_data_alloc_##pname = { \ 123 .cb = &net_buf_dma_cb, \ 124 .alloc_data = &net_buf_mem_pool_##pname, \ 125 .max_alloc_size = 0, \ 126 }; \ 127 static STRUCT_SECTION_ITERABLE(net_buf_pool, pname) = \ 128 NET_BUF_POOL_INITIALIZER(pname, &net_buf_data_alloc_##pname, \ 129 _net_buf_##pname, count, ud_size, \ 130 fdestroy) 131 132 /** 133 * @brief Define a new pool for UDC buffers based on fixed-size data 134 * 135 * This macro is similar to `NET_BUF_POOL_DEFINE`, but provides buffers 136 * with alignment and granularity suitable for use by UDC driver. 137 * 138 * @see NET_BUF_POOL_DEFINE 139 140 * @param pname Name of the pool variable. 141 * @param count Number of buffers in the pool. 142 * @param size Maximum data payload per buffer. 143 * @param ud_size User data space to reserve per buffer. 144 * @param fdestroy Optional destroy callback when buffer is freed. 145 */ 146 #define UDC_BUF_POOL_DEFINE(pname, count, size, ud_size, fdestroy) \ 147 _NET_BUF_ARRAY_DEFINE(pname, count, ud_size); \ 148 BUILD_ASSERT((UDC_BUF_GRANULARITY) % (UDC_BUF_ALIGN) == 0, \ 149 "Code assumes granurality is multiple of alignment"); \ 150 static uint8_t Z_UDC_BUF_SECTION __aligned(UDC_BUF_ALIGN) \ 151 net_buf_data_##pname[count][ROUND_UP(size, UDC_BUF_GRANULARITY)];\ 152 static const struct net_buf_pool_fixed net_buf_fixed_##pname = { \ 153 .data_pool = (uint8_t *)net_buf_data_##pname, \ 154 }; \ 155 static const struct net_buf_data_alloc net_buf_fixed_alloc_##pname = { \ 156 .cb = &net_buf_fixed_cb, \ 157 .alloc_data = (void *)&net_buf_fixed_##pname, \ 158 .max_alloc_size = ROUND_UP(size, UDC_BUF_GRANULARITY), \ 159 }; \ 160 static STRUCT_SECTION_ITERABLE(net_buf_pool, pname) = \ 161 NET_BUF_POOL_INITIALIZER(pname, &net_buf_fixed_alloc_##pname, \ 162 _net_buf_##pname, count, ud_size, \ 163 fdestroy) 164 165 /** 166 * @} 167 */ 168 169 #endif /* ZEPHYR_INCLUDE_UDC_BUF_H */ 170