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 * @brief Buffer macros and definitions used in USB device support 39 * @defgroup udc_buf Buffer macros and definitions used in USB device support 40 * @ingroup usb 41 * @since 4.0 42 * @version 0.1.0 43 * @{ 44 */ 45 46 /** Buffer alignment required by the UDC driver */ 47 #define UDC_BUF_ALIGN Z_UDC_BUF_ALIGN 48 49 /** Buffer granularity required by the UDC driver */ 50 #define UDC_BUF_GRANULARITY Z_UDC_BUF_GRANULARITY 51 52 /** 53 * @brief Define a UDC driver-compliant static buffer 54 * 55 * This macro should be used if the application defines its own buffers to be 56 * used for USB transfers. 57 * 58 * @param name Buffer name 59 * @param size Buffer size 60 */ 61 #define UDC_STATIC_BUF_DEFINE(name, size) \ 62 static uint8_t __aligned(UDC_BUF_ALIGN) name[ROUND_UP(size, UDC_BUF_GRANULARITY)]; 63 64 /** 65 * @brief Verify that the buffer is aligned as required by the UDC driver 66 * 67 * @see IS_ALIGNED 68 * 69 * @param buf Buffer pointer 70 */ 71 #define IS_UDC_ALIGNED(buf) IS_ALIGNED(buf, UDC_BUF_ALIGN) 72 73 /** 74 * @cond INTERNAL_HIDDEN 75 */ 76 #define UDC_HEAP_DEFINE(name, bytes, in_section) \ 77 uint8_t in_section __aligned(UDC_BUF_ALIGN) \ 78 kheap_##name[MAX(bytes, Z_HEAP_MIN_SIZE)]; \ 79 STRUCT_SECTION_ITERABLE(k_heap, name) = { \ 80 .heap = { \ 81 .init_mem = kheap_##name, \ 82 .init_bytes = MAX(bytes, Z_HEAP_MIN_SIZE), \ 83 }, \ 84 } 85 86 #define UDC_K_HEAP_DEFINE(name, size) \ 87 COND_CODE_1(CONFIG_UDC_BUF_FORCE_NOCACHE, \ 88 (UDC_HEAP_DEFINE(name, size, __nocache)), \ 89 (UDC_HEAP_DEFINE(name, size, __noinit))) 90 91 extern const struct net_buf_data_cb net_buf_dma_cb; 92 /** @endcond */ 93 94 /** 95 * @brief Define a new pool for UDC buffers with variable-size payloads 96 * 97 * This macro is similar to `NET_BUF_POOL_VAR_DEFINE`, but provides buffers 98 * with alignment and granularity suitable for use by UDC driver. 99 * 100 * @see NET_BUF_POOL_VAR_DEFINE 101 * 102 * @param pname Name of the pool variable. 103 * @param count Number of buffers in the pool. 104 * @param size Maximum data payload per buffer. 105 * @param ud_size User data space to reserve per buffer. 106 * @param fdestroy Optional destroy callback when buffer is freed. 107 */ 108 #define UDC_BUF_POOL_VAR_DEFINE(pname, count, size, ud_size, fdestroy) \ 109 _NET_BUF_ARRAY_DEFINE(pname, count, ud_size); \ 110 UDC_K_HEAP_DEFINE(net_buf_mem_pool_##pname, size); \ 111 static const struct net_buf_data_alloc net_buf_data_alloc_##pname = { \ 112 .cb = &net_buf_dma_cb, \ 113 .alloc_data = &net_buf_mem_pool_##pname, \ 114 .max_alloc_size = 0, \ 115 }; \ 116 static STRUCT_SECTION_ITERABLE(net_buf_pool, pname) = \ 117 NET_BUF_POOL_INITIALIZER(pname, &net_buf_data_alloc_##pname, \ 118 _net_buf_##pname, count, ud_size, \ 119 fdestroy) 120 121 /** 122 * @brief Define a new pool for UDC buffers based on fixed-size data 123 * 124 * This macro is similar to `NET_BUF_POOL_DEFINE`, but provides buffers 125 * with alignment and granularity suitable for use by UDC driver. 126 * 127 * @see NET_BUF_POOL_DEFINE 128 129 * @param pname Name of the pool variable. 130 * @param count Number of buffers in the pool. 131 * @param size Maximum data payload per buffer. 132 * @param ud_size User data space to reserve per buffer. 133 * @param fdestroy Optional destroy callback when buffer is freed. 134 */ 135 #define UDC_BUF_POOL_DEFINE(pname, count, size, ud_size, fdestroy) \ 136 _NET_BUF_ARRAY_DEFINE(pname, count, ud_size); \ 137 BUILD_ASSERT((UDC_BUF_GRANULARITY) % (UDC_BUF_ALIGN) == 0, \ 138 "Code assumes granurality is multiple of alignment"); \ 139 static uint8_t __nocache __aligned(UDC_BUF_ALIGN) \ 140 net_buf_data_##pname[count][ROUND_UP(size, UDC_BUF_GRANULARITY)];\ 141 static const struct net_buf_pool_fixed net_buf_fixed_##pname = { \ 142 .data_pool = (uint8_t *)net_buf_data_##pname, \ 143 }; \ 144 static const struct net_buf_data_alloc net_buf_fixed_alloc_##pname = { \ 145 .cb = &net_buf_fixed_cb, \ 146 .alloc_data = (void *)&net_buf_fixed_##pname, \ 147 .max_alloc_size = ROUND_UP(size, UDC_BUF_GRANULARITY), \ 148 }; \ 149 static STRUCT_SECTION_ITERABLE(net_buf_pool, pname) = \ 150 NET_BUF_POOL_INITIALIZER(pname, &net_buf_fixed_alloc_##pname, \ 151 _net_buf_##pname, count, ud_size, \ 152 fdestroy) 153 154 /** 155 * @} 156 */ 157 158 #endif /* ZEPHYR_INCLUDE_UDC_BUF_H */ 159