1 /*
2 * Copyright 2020-2024 NXP
3 *
4 * SPDX-License-Identifier: BSD-3-Clause
5 */
6 #include <stdio.h>
7 #include <string.h>
8
9 #include "rpmsg_platform.h"
10 #include "rpmsg_default_config.h"
11 #include "rpmsg_lite.h"
12
13 #include "rpmsg_env.h"
14
15 #include "fsl_device_registers.h"
16 #include "fsl_imu.h"
17
18 #if defined(RL_USE_MCMGR_IPC_ISR_HANDLER) && (RL_USE_MCMGR_IPC_ISR_HANDLER == 1)
19 #include "mcmgr.h"
20 #endif
21
22 #if defined(RL_USE_ENVIRONMENT_CONTEXT) && (RL_USE_ENVIRONMENT_CONTEXT == 1)
23 #error "This RPMsg-Lite port requires RL_USE_ENVIRONMENT_CONTEXT set to 0"
24 #endif
25
26 #define APP_MU_IRQ_PRIORITY (3U)
27
28 #if defined(IMU_CPU_INDEX) && (IMU_CPU_INDEX == 1U)
29 #define APP_MU_IRQn RF_IMU0_IRQn
30 #define APP_IMU_LINK kIMU_LinkCpu1Cpu2
31 #elif defined(IMU_CPU_INDEX) && (IMU_CPU_INDEX == 2U)
32 #define APP_MU_IRQn CPU2_MSG_RDY_INT_IRQn
33 #define APP_IMU_LINK kIMU_LinkCpu2Cpu1
34 #endif
35
36 /* Generator for CRC calculations. */
37 #define POLGEN 0x1021U
38
39 static int32_t isr_counter = 0;
40 static int32_t disable_counter = 0;
41 static void *platform_lock;
42 #if defined(RL_USE_STATIC_API) && (RL_USE_STATIC_API == 1)
43 static LOCK_STATIC_CONTEXT platform_lock_static_ctxt;
44 #endif
45
46 /* This structure is used to validate that shmem config that is stored in SMU2 is valid */
47 typedef struct rpmsg_platform_shmem_config_protected
48 {
49 uint8_t identificationWord[10];
50 rpmsg_platform_shmem_config_t config;
51 uint16_t shmemConfigCrc;
52 } rpmsg_platform_shmem_config_protected_t;
53
54 static const uint8_t ShmemConfigIdentifier[12] = {"SMEM_CONFIG:"};
55
56 /* Compute CRC to protect shared memory strcuture stored in RAM by application core and retrieve by NBU */
57 static uint16_t platform_compute_crc_over_shmem_struct(rpmsg_platform_shmem_config_protected_t *protected_structure);
58
59 static uint32_t first_time = RL_TRUE;
60 static rpmsg_platform_shmem_config_t shmem_config = {0U};
61
62 #if defined(RL_USE_MCMGR_IPC_ISR_HANDLER) && (RL_USE_MCMGR_IPC_ISR_HANDLER == 1)
mcmgr_event_handler(uint16_t vring_idx,void * context)63 static void mcmgr_event_handler(uint16_t vring_idx, void *context)
64 {
65 env_isr((uint32_t)vring_idx);
66 }
67 #else
68
69 /* MU ISR router */
imu_rx_isr()70 static void imu_rx_isr()
71 {
72 env_isr(0);
73 IMU_ClearPendingInterrupts(APP_IMU_LINK, IMU_MSG_FIFO_CNTL_MSG_RDY_INT_CLR_MASK);
74 }
75
76 #if defined(IMU_CPU_INDEX) && (IMU_CPU_INDEX == 1U)
RF_IMU0_IRQHandler(void)77 int32_t RF_IMU0_IRQHandler(void)
78 {
79 imu_rx_isr();
80 SDK_ISR_EXIT_BARRIER;
81 return 0;
82 }
83 #endif
84
85 #if defined(IMU_CPU_INDEX) && (IMU_CPU_INDEX == 2U)
CPU2_MSG_RDY_INT_IRQHandler(void)86 int32_t CPU2_MSG_RDY_INT_IRQHandler(void)
87 {
88 imu_rx_isr();
89 SDK_ISR_EXIT_BARRIER;
90 return 0;
91 }
92 #endif /* IMU_CPU_INDEX */
93 #endif
94
platform_global_isr_disable(void)95 static void platform_global_isr_disable(void)
96 {
97 __asm volatile("cpsid i");
98 }
99
platform_global_isr_enable(void)100 static void platform_global_isr_enable(void)
101 {
102 __asm volatile("cpsie i");
103 }
104
platform_init_interrupt(uint32_t vector_id,void * isr_data)105 int32_t platform_init_interrupt(uint32_t vector_id, void *isr_data)
106 {
107 if (platform_lock != ((void *)0))
108 {
109 /* Register ISR to environment layer */
110 env_register_isr(vector_id, isr_data);
111
112 env_lock_mutex(platform_lock);
113
114 RL_ASSERT(0 <= isr_counter);
115 if (isr_counter < 2)
116 {
117 (void)EnableIRQ(APP_MU_IRQn);
118 }
119 isr_counter++;
120
121 env_unlock_mutex(platform_lock);
122 return 0;
123 }
124 else
125 {
126 return -1;
127 }
128 }
129
platform_deinit_interrupt(uint32_t vector_id)130 int32_t platform_deinit_interrupt(uint32_t vector_id)
131 {
132 if (platform_lock != ((void *)0))
133 {
134 env_lock_mutex(platform_lock);
135
136 RL_ASSERT(0 < isr_counter);
137 isr_counter--;
138 if (isr_counter < 2)
139 {
140 (void)DisableIRQ(APP_MU_IRQn);
141 }
142
143 /* Unregister ISR from environment layer */
144 env_unregister_isr(vector_id);
145
146 env_unlock_mutex(platform_lock);
147
148 return 0;
149 }
150 else
151 {
152 return -1;
153 }
154 }
155
platform_notify(uint32_t vector_id)156 void platform_notify(uint32_t vector_id)
157 {
158 env_lock_mutex(platform_lock);
159 #if defined(RL_USE_MCMGR_IPC_ISR_HANDLER) && (RL_USE_MCMGR_IPC_ISR_HANDLER == 1)
160 (void)MCMGR_TriggerEvent(kMCMGR_RemoteRPMsgEvent, (uint16_t)RL_GET_Q_ID(vector_id));
161 #else
162 /* TO Not support*/
163 #endif
164 env_unlock_mutex(platform_lock);
165 }
166
167 /**
168 * platform_time_delay
169 *
170 * @param num_msec Delay time in ms.
171 *
172 * This is not an accurate delay, it ensures at least num_msec passed when return.
173 */
platform_time_delay(uint32_t num_msec)174 void platform_time_delay(uint32_t num_msec)
175 {
176 uint32_t loop;
177
178 /* Recalculate the CPU frequency */
179 SystemCoreClockUpdate();
180
181 /* Calculate the CPU loops to delay, each loop has 3 cycles */
182 loop = SystemCoreClock / 3U / 1000U * num_msec;
183
184 /* There's some difference among toolchains, 3 or 4 cycles each loop */
185 while (loop > 0U)
186 {
187 __NOP();
188 loop--;
189 }
190 }
191
192 /**
193 * platform_in_isr
194 *
195 * Return whether CPU is processing IRQ
196 *
197 * @return True for IRQ, false otherwise.
198 *
199 */
platform_in_isr(void)200 int32_t platform_in_isr(void)
201 {
202 /* coco begin validated: This platform-dependent function is used in OS-based environments only, not used in
203 * baremetal app */
204 return (((SCB->ICSR & SCB_ICSR_VECTACTIVE_Msk) != 0UL) ? 1 : 0);
205 }
206 /* coco end */
207
208 /**
209 * platform_interrupt_enable
210 *
211 * Enable peripheral-related interrupt
212 *
213 * @param vector_id Virtual vector ID that needs to be converted to IRQ number
214 *
215 * @return vector_id Return value is never checked.
216 *
217 */
platform_interrupt_enable(uint32_t vector_id)218 int32_t platform_interrupt_enable(uint32_t vector_id)
219 {
220 RL_ASSERT(0 < disable_counter);
221
222 platform_global_isr_disable();
223 disable_counter--;
224
225 if (disable_counter == 0)
226 {
227 NVIC_EnableIRQ(APP_MU_IRQn);
228 }
229 platform_global_isr_enable();
230 return ((int32_t)vector_id);
231 }
232
233 /**
234 * platform_interrupt_disable
235 *
236 * Disable peripheral-related interrupt.
237 *
238 * @param vector_id Virtual vector ID that needs to be converted to IRQ number
239 *
240 * @return vector_id Return value is never checked.
241 *
242 */
platform_interrupt_disable(uint32_t vector_id)243 int32_t platform_interrupt_disable(uint32_t vector_id)
244 {
245 RL_ASSERT(0 <= disable_counter);
246
247 platform_global_isr_disable();
248 /* virtqueues use the same NVIC vector
249 if counter is set - the interrupts are disabled */
250 if (disable_counter == 0)
251 {
252 NVIC_DisableIRQ(APP_MU_IRQn);
253 }
254 disable_counter++;
255 platform_global_isr_enable();
256 return ((int32_t)vector_id);
257 }
258
259 /**
260 * platform_map_mem_region
261 *
262 * Dummy implementation
263 *
264 */
platform_map_mem_region(uint32_t vrt_addr,uint32_t phy_addr,uint32_t size,uint32_t flags)265 void platform_map_mem_region(uint32_t vrt_addr, uint32_t phy_addr, uint32_t size, uint32_t flags)
266 {
267 }
268
269 /**
270 * platform_cache_all_flush_invalidate
271 *
272 * Dummy implementation
273 *
274 */
platform_cache_all_flush_invalidate(void)275 void platform_cache_all_flush_invalidate(void)
276 {
277 }
278
279 /**
280 * platform_cache_disable
281 *
282 * Dummy implementation
283 *
284 */
platform_cache_disable(void)285 void platform_cache_disable(void)
286 {
287 }
288
289 /**
290 * platform_init
291 *
292 * platform/environment init
293 */
platform_init(void)294 int32_t platform_init(void)
295 {
296 #if defined(RL_USE_MCMGR_IPC_ISR_HANDLER) && (RL_USE_MCMGR_IPC_ISR_HANDLER == 1)
297 mcmgr_status_t retval = kStatus_MCMGR_Error;
298 retval = MCMGR_RegisterEvent(kMCMGR_RemoteRPMsgEvent, mcmgr_event_handler, ((void *)0));
299 if (kStatus_MCMGR_Success != retval)
300 {
301 return -1; /* coco validated: line never reached, MCMGR_RegisterEvent() fails only when the type parameter is
302 out of scope, here the correct kMCMGR_RemoteRPMsgEvent is passed */
303 }
304 #else
305 IMU_Init(APP_IMU_LINK);
306 NVIC_SetPriority(APP_MU_IRQn, APP_MU_IRQ_PRIORITY);
307 NVIC_EnableIRQ(APP_MU_IRQn);
308 #endif
309
310 /* Create lock used in multi-instanced RPMsg */
311 #if defined(RL_USE_STATIC_API) && (RL_USE_STATIC_API == 1)
312 if (0 != env_create_mutex(&platform_lock, 1, &platform_lock_static_ctxt))
313 #else
314 if (0 != env_create_mutex(&platform_lock, 1))
315 #endif
316 {
317 return -1; /* coco validated: not able to force the application to reach this line */
318 }
319
320 return 0;
321 }
322
323 /**
324 * platform_deinit
325 *
326 * platform/environment deinit process
327 */
platform_deinit(void)328 int32_t platform_deinit(void)
329 {
330 IMU_Deinit(APP_IMU_LINK);
331
332 /* Delete lock used in multi-instanced RPMsg */
333 env_delete_mutex(platform_lock);
334 platform_lock = ((void *)0);
335 return 0;
336 }
337
platform_set_static_shmem_config(void)338 void platform_set_static_shmem_config(void)
339 {
340 extern uint32_t rpmsg_sh_mem_start[];
341 rpmsg_platform_shmem_config_protected_t protec_shmem_struct;
342
343 /* Identifier at the beginning of the structure that will be used to verify on nbu side validity of the structure */
344 memcpy(&(protec_shmem_struct.identificationWord), ShmemConfigIdentifier, sizeof(ShmemConfigIdentifier));
345
346 /* Fill shared memory structure with setting from the app core */
347 protec_shmem_struct.config.buffer_payload_size = RL_BUFFER_PAYLOAD_SIZE;
348 protec_shmem_struct.config.buffer_count = RL_BUFFER_COUNT;
349 protec_shmem_struct.config.vring_size = VRING_SIZE;
350 protec_shmem_struct.config.vring_align = VRING_ALIGN;
351
352 /* Calculate and set CRC of the strucuture */
353 protec_shmem_struct.shmemConfigCrc = platform_compute_crc_over_shmem_struct(&protec_shmem_struct);
354
355 /* Store in SMU2 the all structure */
356 memcpy(rpmsg_sh_mem_start, &protec_shmem_struct, sizeof(rpmsg_platform_shmem_config_protected_t));
357 }
358
platform_get_custom_shmem_config(uint32_t link_id,rpmsg_platform_shmem_config_t * config)359 uint32_t platform_get_custom_shmem_config(uint32_t link_id, rpmsg_platform_shmem_config_t *config)
360 {
361 extern uint32_t rpmsg_sh_mem_start[];
362 rpmsg_platform_shmem_config_protected_t protec_shmem_struct = {0U};
363
364 do
365 {
366 if (first_time == RL_FALSE)
367 {
368 /* Variable shmem_config is already set if this is not the fisrt call */
369 break;
370 }
371
372 first_time = RL_FALSE;
373
374 /* Copy the full structure in local variable */
375 memcpy(&protec_shmem_struct, rpmsg_sh_mem_start, sizeof(rpmsg_platform_shmem_config_protected_t));
376
377 /* By default set the values of the MR3 connectivity release */
378 shmem_config.buffer_payload_size = 496U;
379 shmem_config.buffer_count = 4U;
380 shmem_config.vring_size = 0x80U;
381 shmem_config.vring_align = 0x10U;
382
383 if (memcmp(&(protec_shmem_struct.identificationWord), ShmemConfigIdentifier, sizeof(ShmemConfigIdentifier)) !=
384 0U)
385 {
386 break;
387 }
388 if (platform_compute_crc_over_shmem_struct(&protec_shmem_struct) != protec_shmem_struct.shmemConfigCrc)
389 {
390 break;
391 }
392 /* If the identifier and the CRC are correct we can copy the shared memory config stored in SMU2 in local
393 * variable */
394 memcpy(&shmem_config, &(protec_shmem_struct.config), sizeof(rpmsg_platform_shmem_config_t));
395
396 } while (false);
397
398 memcpy(config, &shmem_config, sizeof(rpmsg_platform_shmem_config_t));
399
400 (void)link_id;
401
402 return 0U;
403 }
404
platform_compute_crc_over_shmem_struct(rpmsg_platform_shmem_config_protected_t * protec_shmem_struct)405 static uint16_t platform_compute_crc_over_shmem_struct(rpmsg_platform_shmem_config_protected_t *protec_shmem_struct)
406 {
407 uint16_t computedCRC = 0U;
408 uint8_t crcA;
409 uint8_t byte = 0U;
410
411 uint8_t *ptr = (uint8_t *)(&protec_shmem_struct->config);
412 uint16_t len = (uint16_t)((uint32_t)(uint8_t *)(&protec_shmem_struct->shmemConfigCrc) -
413 (uint32_t)(uint8_t *)(&protec_shmem_struct->config));
414 while (len != 0U)
415 {
416 byte = *ptr;
417 computedCRC ^= ((uint16_t)byte << 8U);
418 for (crcA = 8U; crcA != 0U; crcA--)
419 {
420 if ((computedCRC & 0x8000U) != 0U)
421 {
422 computedCRC <<= 1U;
423 computedCRC ^= POLGEN;
424 }
425 else
426 {
427 computedCRC <<= 1U;
428 }
429 }
430 --len;
431 ++ptr;
432 }
433 return computedCRC;
434 }
435