1 /*
2  * Copyright (c) 2017, Texas Instruments Incorporated
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <stdio.h>
8 #include <stdlib.h>
9 #include <string.h>
10 
11 #include <zephyr/kernel.h>
12 #include <zephyr/device.h>
13 #include <zephyr/init.h>
14 #include <zephyr/sys/util.h>
15 #include <zephyr/sys/__assert.h>
16 
17 #include <inc/hw_types.h>
18 #include <inc/hw_ints.h>
19 #include <driverlib/rom_map.h>
20 #include <driverlib/interrupt.h>
21 
22 #include <ti/drivers/net/wifi/simplelink.h>
23 #include <kernel/zephyr/dpl/dpl.h>
24 
25 #define	 SPAWN_TASK_STACKSIZE  2048
26 /*
27  * Priority must be higher than any thread priority in the system which
28  * might use the SimpleLink host driver, which involves the spawn_task().
29  * Since SimpleLink APIs may be called from any thread, including
30  * cooperative threads, and the _main kernel thread, we must set this
31  * as highest prioirty.
32  */
33 #define	 SPAWN_TASK_PRIORITY   K_HIGHEST_THREAD_PRIO
34 
35 /* Spawn message queue size: Could be 1, but 3 is used by other DPL ports */
36 #define SPAWN_QUEUE_SIZE  ( 3 )
37 
38 /* Stack, for the simplelink spawn task: */
39 static K_THREAD_STACK_DEFINE(spawn_task_stack, SPAWN_TASK_STACKSIZE);
40 static struct k_thread spawn_task_data;
41 
42 static void spawn_task(void *unused1, void *unused2, void *unused3);
43 
44 /*
45  * MessageQ to send message from an ISR or other task to the SimpleLink
46  * "Spawn" task:
47  */
48 K_MSGQ_DEFINE(spawn_msgq, sizeof(tSimpleLinkSpawnMsg), SPAWN_QUEUE_SIZE,\
49 	      MEM_ALIGN);
50 
51 /*
52  * SimpleLink does not have an init hook, so we export this function to
53  * be called early during system initialization.
54  */
dpl_zephyr_init(void)55 static int dpl_zephyr_init(void)
56 {
57 	(void)k_thread_create(&spawn_task_data, spawn_task_stack,
58 			SPAWN_TASK_STACKSIZE, spawn_task,
59 			NULL, NULL, NULL,
60 			SPAWN_TASK_PRIORITY, 0, K_NO_WAIT);
61 	return 0;
62 }
63 SYS_INIT(dpl_zephyr_init, POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEFAULT);
64 
65 /* SimpleLink driver code can call this from ISR or task context: */
os_Spawn(P_OS_SPAWN_ENTRY pEntry,void * pValue,unsigned long flags)66 _SlReturnVal_t os_Spawn(P_OS_SPAWN_ENTRY pEntry, void *pValue,
67 			unsigned long flags)
68 {
69 	tSimpleLinkSpawnMsg slMsg;
70 	_SlReturnVal_t retval;
71 
72 	slMsg.pEntry = pEntry;
73 	slMsg.pValue = pValue;
74 
75 	if (0 == k_msgq_put(&spawn_msgq, &slMsg, K_NO_WAIT)) {
76 		retval = OS_OK;
77 	}
78 	else {
79 		retval = -1;
80 		__ASSERT(retval == OS_OK,
81 			 "os_Spawn: Failed to k_msgq_put failed\r\n");
82 
83 	}
84 
85 	return retval;
86 }
87 
spawn_task(void * unused1,void * unused2,void * unused3)88 void spawn_task(void *unused1, void *unused2, void *unused3)
89 {
90 	tSimpleLinkSpawnMsg slMsg;
91 
92 	ARG_UNUSED(unused1);
93 	ARG_UNUSED(unused2);
94 	ARG_UNUSED(unused3);
95 
96 	while (1) {
97 		k_msgq_get(&spawn_msgq, &slMsg, K_FOREVER);
98 		slMsg.pEntry(slMsg.pValue);
99 	}
100 }
101 
102 #if CONFIG_ERRNO && !defined(SL_INC_INTERNAL_ERRNO)
103 /*
104  * Called by the SimpleLink host driver to set POSIX error codes
105  * for the host OS.
106  */
dpl_set_errno(int err)107 int dpl_set_errno(int err)
108 {
109 	/* Ensure (POSIX) errno is positive.
110 	 * __errno() is a Zephyr function returning a pointer to the
111 	 * current thread's errno variable.
112 	 */
113 	errno = (err < 0? -err : err);
114 	return -1;
115 }
116 #endif
117