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