1 /*
2  * Copyright (c) 2020 - 2024, Nordic Semiconductor ASA
3  * All rights reserved.
4  *
5  * SPDX-License-Identifier: BSD-3-Clause
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright notice, this
11  *    list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * 3. Neither the name of the copyright holder nor the names of its
18  *    contributors may be used to endorse or promote products derived from this
19  *    software without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
25  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 #ifndef NRF_VDMA_H__
35 #define NRF_VDMA_H__
36 
37 #include <nrfx.h>
38 
39 #ifdef __cplusplus
40 extern "C" {
41 #endif
42 
43 /**
44  * @defgroup nrf_vdma Generic Vector DMA layer.
45  * @{
46  * @ingroup nrf_mvdma
47  * @brief   Helper layer that provides the common functionality for Vector DMA (VDMA).
48  */
49 
50 /** @brief Maximum size of VDMA buffer. */
51 #define NRF_VDMA_BUFFER_SIZE_MASK VDMADESCRIPTOR_CONFIG_CNT_Msk
52 
53 /** @brief Structure describing VDMA job. */
54 typedef struct
55 {
56     uint8_t * p_buffer; ///< Pointer to the VDMA job buffer.
57     struct __PACKED
58     {
59         uint32_t size:24;    ///< Size of the job buffer.
60         uint8_t  attributes; ///< Attributes of the job.
61     };
62 } nrf_vdma_job_t;
63 
64 /** @brief Type describing VDMA job with fixed attributes and length. */
65 typedef uint32_t nrf_vdma_job_reduced_t;
66 
67 /**
68  * @brief VDMA attributes.
69  *
70  * @note Only one attribute can be set for the job.
71  */
72 typedef enum
73 {
74     NRF_VDMA_ATTRIBUTE_PLAIN_DATA           = 0x00, ///< Data is not modified.
75     NRF_VDMA_ATTRIBUTE_BYTE_SWAP            = 0x07, ///< Data bytes are swapped.
76     NRF_VDMA_ATTRIBUTE_JOB_LIST             = 0x08, ///< Allows chaining of joblists.
77     NRF_VDMA_ATTRIBUTE_BUFFER_FILL          = 0x09, ///< Insters zeros into sink data buffers. Sink job attribute only.
78     NRF_VDMA_ATTRIBUTE_FIXED_ATTR           = 0x0A, ///< Identical job attributes and sizes for all jobs in the list.
79     NRF_VDMA_ATTRIBUTE_CRC                  = 0x0B, ///< CRC checksum is calculated on all data in the source list.
80     NRF_VDMA_ATTRIBUTE_STATIC_ADDR          = 0x0C, ///< Memory address is fixed for the entirety of the job.
81     NRF_VDMA_ATTRIBUTE_PLAIN_DATA_BUF_WRITE = 0x0D, ///< Used to get better write performance when many short bursts are beiing sent.
82 } nrf_vdma_attributes_t;
83 
84 /**
85  * @brief VDMA extended attributes.
86  *
87  * @note This attributes can be combined with each other and with standard attribute
88  */
89 typedef enum
90 {
91     NRF_VDMA_EXT_ATTRIBUTE_PERIPHERAL_MODE = 0x40, //< Job contains a pointer to a peripheral address.
92     NRF_VDMA_EXT_ATTRIBUTE_EVENT_ENABLE    = 0x80, //< Enable event on job completion.
93 } nrf_vdma_ext_attribute_t;
94 
95 /**
96  * @brief Macro for computing size of the array of reduced job structures.
97  *
98  * @param[in] count Number of jobs to be stored in reduced job list.
99  */
100 #define NRF_VDMA_REDUCED_JOB_SIZE(count) (count + 2)
101 
102 /**
103  * @brief Macro for defining an element of a job list.
104  *
105  * @param[in] p_buffer  Pointer to the buffer.
106  * @param[in] size      Size of the transfer.
107  * @param[in] attribute Attribute mask.
108  *
109  * @return Two words of the job descriptor.
110  */
111 #define NRF_VDMA_JOB_ELEMENT(p_buffer, size, attribute)                   \
112         (uint32_t)p_buffer,                                               \
113         (uint32_t)(((attribute) << VDMADESCRIPTOR_CONFIG_ATTRIBUTE_Pos) | \
114                    ((size) & NRF_VDMA_BUFFER_SIZE_MASK))
115 
116 /**
117  * @brief Macro for defining initial element of reduced job list.
118  *
119  * @param[in] p_buffer  Job buffer.
120  * @param[in] size      Size of the job buffer.
121  * @param[in] attribute Attributes of the job.
122  *
123  * @return Two words of the job descriptor.
124  */
125 #define NRF_VDMA_REDUCED_JOB_INIT_ELEMENT(p_buffer, size, attribute) \
126     NRF_VDMA_JOB_ELEMENT(p_buffer, size, NRF_VDMA_ATTRIBUTE_FIXED_ATTR | (attribute))
127 
128 /**
129  * @brief Macro for defining a job for transfer engaging peripheral.
130  *
131  * @param[in] addr Starting address.
132  * @param[in] size Size of a DMA job.
133  *
134  * @return Two words which contains address, size and the descriptor byte.
135  */
136 #define NRFX_VDMA_PERIPH_JOB(addr, size) \
137         NRF_VDMA_JOB_ELEMENT(addr, size, NRF_VDMA_EXT_ATTRIBUTE_PERIPHERAL_MODE)
138 
139 /**
140  * @brief Function for filling the specified structure of the job with given job parameters.
141  *
142  * @param[out] p_job      Pointer to the structure of the job to be filled.
143  * @param[in]  p_buffer   Job buffer.
144  * @param[in]  size       Size of the job buffer.
145  * @param[in]  attributes Attributes of the job.
146  */
nrf_vdma_job_fill(nrf_vdma_job_t * p_job,void * p_buffer,size_t size,uint8_t attributes)147 __STATIC_INLINE void nrf_vdma_job_fill(nrf_vdma_job_t * p_job,
148                                        void *           p_buffer,
149                                        size_t           size,
150                                        uint8_t          attributes)
151 {
152     p_job->p_buffer   = (uint8_t *)p_buffer;
153     p_job->size       = (uint32_t)size & NRF_VDMA_BUFFER_SIZE_MASK;
154     p_job->attributes = attributes;
155 }
156 
157 /**
158  * @brief Function for initializing the specified structure of the job with fixed attributes.
159  *
160  * First element of reduced job list occupies space for two elements.
161  *
162  * @note Use @ref nrf_vdma_job_terminate() to terminate reduced job list.
163  *
164  * @param[out] p_job      Pointer to the reduced structure of the job to be filled.
165  * @param[in]  p_buffer   Job buffer.
166  * @param[in]  size       Size of the job buffer.
167  * @param[in]  attributes Additional attribute of the job.
168  */
nrf_vdma_job_reduced_init(nrf_vdma_job_reduced_t * p_job,void * p_buffer,size_t size,uint8_t attributes)169 __STATIC_INLINE void nrf_vdma_job_reduced_init(nrf_vdma_job_reduced_t * p_job,
170                                                void *                   p_buffer,
171                                                size_t                   size,
172                                                uint8_t                  attributes)
173 {
174     *p_job       = (uint32_t)p_buffer;
175     *(p_job + 1) = (uint32_t)(((NRF_VDMA_ATTRIBUTE_FIXED_ATTR | attributes) <<
176                                 VDMADESCRIPTOR_CONFIG_ATTRIBUTE_Pos) |
177                                 (size & NRF_VDMA_BUFFER_SIZE_MASK));
178 }
179 
180 /**
181  * @brief Function for filling the specified reduced structure of the job with given buffer pointer.
182  *
183  * @param[out] p_job    Pointer to the reduced structure of the job to be filled.
184  * @param[in]  p_buffer Job buffer.
185  */
nrf_vdma_job_reduced_fill(nrf_vdma_job_reduced_t * p_job,void * p_buffer)186 __STATIC_INLINE void nrf_vdma_job_reduced_fill(nrf_vdma_job_reduced_t * p_job,
187                                                void *                   p_buffer)
188 {
189     *p_job = (uint32_t)p_buffer;
190 }
191 
192 /**
193  * @brief Function for getting the pointer to the buffer associated with specified job.
194  *
195  * @param[in] p_job Pointer to the structure of the specified job.
196  *
197  * @return Pointer to the job buffer.
198  */
nrf_vdma_job_buffer_get(nrf_vdma_job_t const * p_job)199 __STATIC_INLINE void * nrf_vdma_job_buffer_get(nrf_vdma_job_t const * p_job)
200 {
201     return (void *)p_job->p_buffer;
202 }
203 
204 /**
205  * @brief Function for getting the size of the buffer associated with specified job.
206  *
207  * @param[in] p_job Pointer to the structure of the specified job.
208  *
209  * @return Size of the job buffer.
210  */
nrf_vdma_job_size_get(nrf_vdma_job_t const * p_job)211 __STATIC_INLINE size_t nrf_vdma_job_size_get(nrf_vdma_job_t const * p_job)
212 {
213     return (size_t)p_job->size;
214 }
215 
216 /**
217  * @brief Function for terminating the specified job.
218  *
219  * When VectorDMA encounters job that is terminated, processing of the job list stops.
220  *
221  * @param[out] p_job Pointer to the structure of the job to be terminated.
222  */
nrf_vdma_job_terminate(nrf_vdma_job_t * p_job)223 __STATIC_INLINE void nrf_vdma_job_terminate(nrf_vdma_job_t * p_job)
224 {
225     p_job->p_buffer = NULL;
226 }
227 
228 /**
229  * @brief Function for linking the job with another job.
230  *
231  * When VectorDMA encounters job that is linked to another job,
232  * execution of the linked job starts.
233  *
234  * @param[out] p_job        Pointer to the structure of the job to become link.
235  * @param[in]  p_job_linked Pointer to the structure of the job to be linked.
236  */
nrf_vdma_job_link(nrf_vdma_job_t * p_job,nrf_vdma_job_t * p_job_linked)237 __STATIC_INLINE void nrf_vdma_job_link(nrf_vdma_job_t * p_job,
238                                        nrf_vdma_job_t * p_job_linked)
239 {
240     p_job->p_buffer   = (uint8_t *)p_job_linked;
241     p_job->attributes = NRF_VDMA_ATTRIBUTE_JOB_LIST;
242 }
243 
244 /** @} */
245 
246 #ifdef __cplusplus
247 }
248 #endif
249 
250 #endif // NRF_VDMA_H__
251