Line data Source code
1 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 1 : #define UDC_BUF_ALIGN Z_UDC_BUF_ALIGN
48 :
49 : /** Buffer granularity required by the UDC driver */
50 1 : #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 1 : #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 1 : #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 1 : #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 1 : #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 */
|