1 /*
2 * Copyright (c) 2018 Intel Corporation
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 */
6
7 #include <zephyr/kernel.h>
8 #include <zephyr/portability/cmsis_types.h>
9 #include <string.h>
10
11 K_MEM_SLAB_DEFINE(cmsis_rtos_event_cb_slab, sizeof(struct cmsis_rtos_event_cb),
12 CONFIG_CMSIS_V2_EVT_FLAGS_MAX_COUNT, 4);
13
14 static const osEventFlagsAttr_t init_event_flags_attrs = {
15 .name = "ZephyrEvent",
16 .attr_bits = 0,
17 .cb_mem = NULL,
18 .cb_size = 0,
19 };
20
21 #define DONT_CARE (0)
22
23 /**
24 * @brief Create and Initialize an Event Flags object.
25 */
osEventFlagsNew(const osEventFlagsAttr_t * attr)26 osEventFlagsId_t osEventFlagsNew(const osEventFlagsAttr_t *attr)
27 {
28 struct cmsis_rtos_event_cb *events;
29
30 if (k_is_in_isr()) {
31 return NULL;
32 }
33
34 if (attr == NULL) {
35 attr = &init_event_flags_attrs;
36 }
37
38 if (attr->cb_mem != NULL) {
39 __ASSERT(attr->cb_size == sizeof(struct cmsis_rtos_event_cb), "Invalid cb_size\n");
40 events = (struct cmsis_rtos_event_cb *)attr->cb_mem;
41 } else if (k_mem_slab_alloc(&cmsis_rtos_event_cb_slab, (void **)&events, K_MSEC(100)) !=
42 0) {
43 return NULL;
44 }
45 memset(events, 0, sizeof(struct cmsis_rtos_event_cb));
46
47 k_event_init(&events->z_event);
48 events->is_cb_dynamic_allocation = (attr->cb_mem == NULL);
49 events->name = (attr->name == NULL) ? init_event_flags_attrs.name : attr->name;
50
51 return (osEventFlagsId_t)events;
52 }
53
54 /**
55 * @brief Set the specified Event Flags.
56 */
osEventFlagsSet(osEventFlagsId_t ef_id,uint32_t flags)57 uint32_t osEventFlagsSet(osEventFlagsId_t ef_id, uint32_t flags)
58 {
59 struct cmsis_rtos_event_cb *events = (struct cmsis_rtos_event_cb *)ef_id;
60 uint32_t rv;
61
62 if ((ef_id == NULL) || (flags & osFlagsError)) {
63 return osFlagsErrorParameter;
64 }
65
66 rv = k_event_test(&events->z_event, 0xFFFFFFFF);
67 k_event_post(&events->z_event, flags & ~rv);
68
69 return flags & ~rv;
70 }
71
72 /**
73 * @brief Clear the specified Event Flags.
74 */
osEventFlagsClear(osEventFlagsId_t ef_id,uint32_t flags)75 uint32_t osEventFlagsClear(osEventFlagsId_t ef_id, uint32_t flags)
76 {
77 struct cmsis_rtos_event_cb *events = (struct cmsis_rtos_event_cb *)ef_id;
78 uint32_t rv;
79
80 if ((ef_id == NULL) || (flags & osFlagsError)) {
81 return osFlagsErrorParameter;
82 }
83
84 rv = k_event_test(&events->z_event, 0xFFFFFFFF);
85 k_event_clear(&events->z_event, flags & rv);
86
87 return rv;
88 }
89
90 /**
91 * @brief Wait for one or more Event Flags to become signaled.
92 */
osEventFlagsWait(osEventFlagsId_t ef_id,uint32_t flags,uint32_t options,uint32_t timeout)93 uint32_t osEventFlagsWait(osEventFlagsId_t ef_id, uint32_t flags, uint32_t options,
94 uint32_t timeout)
95 {
96 struct cmsis_rtos_event_cb *events = (struct cmsis_rtos_event_cb *)ef_id;
97 uint32_t sub_opt = options & (osFlagsWaitAll | osFlagsNoClear);
98 uint32_t rv;
99 k_timeout_t event_timeout;
100
101 /*
102 * Return unknown error if called from ISR with a non-zero timeout
103 * or if flags is zero.
104 */
105 if (((timeout > 0U) && k_is_in_isr()) || (flags == 0U)) {
106 return osFlagsErrorUnknown;
107 }
108
109 if ((ef_id == NULL) || (flags & osFlagsError)) {
110 return osFlagsErrorParameter;
111 }
112
113 if (timeout == osWaitForever) {
114 event_timeout = K_FOREVER;
115 } else if (timeout == 0U) {
116 event_timeout = K_NO_WAIT;
117 } else {
118 event_timeout = K_TICKS(timeout);
119 }
120
121 switch (sub_opt) {
122 case osFlagsWaitAll | osFlagsNoClear:
123 rv = k_event_wait_all(&events->z_event, flags, false, event_timeout);
124 break;
125 case osFlagsWaitAll:
126 rv = k_event_wait_all_safe(&events->z_event, flags, false, event_timeout);
127 break;
128 case osFlagsNoClear:
129 rv = k_event_wait(&events->z_event, flags, false, event_timeout);
130 break;
131 case 0:
132 rv = k_event_wait_safe(&events->z_event, flags, false, event_timeout);
133 break;
134 default:
135 __ASSERT_NO_MSG(0);
136 }
137
138 if (rv != 0U) {
139 return rv;
140 }
141
142 return (timeout == 0U) ? osFlagsErrorResource : osFlagsErrorTimeout;
143 }
144
145 /**
146 * @brief Get name of an Event Flags object.
147 * This function may be called from Interrupt Service Routines.
148 */
osEventFlagsGetName(osEventFlagsId_t ef_id)149 const char *osEventFlagsGetName(osEventFlagsId_t ef_id)
150 {
151 struct cmsis_rtos_event_cb *events = (struct cmsis_rtos_event_cb *)ef_id;
152
153 if (events == NULL) {
154 return NULL;
155 }
156 return events->name;
157 }
158
159 /**
160 * @brief Get the current Event Flags.
161 */
osEventFlagsGet(osEventFlagsId_t ef_id)162 uint32_t osEventFlagsGet(osEventFlagsId_t ef_id)
163 {
164 struct cmsis_rtos_event_cb *events = (struct cmsis_rtos_event_cb *)ef_id;
165
166 if (ef_id == NULL) {
167 return 0;
168 }
169
170 return k_event_test(&events->z_event, 0xFFFFFFFF);
171 }
172
173 /**
174 * @brief Delete an Event Flags object.
175 */
osEventFlagsDelete(osEventFlagsId_t ef_id)176 osStatus_t osEventFlagsDelete(osEventFlagsId_t ef_id)
177 {
178 struct cmsis_rtos_event_cb *events = (struct cmsis_rtos_event_cb *)ef_id;
179
180 if (ef_id == NULL) {
181 return osErrorResource;
182 }
183
184 if (k_is_in_isr()) {
185 return osErrorISR;
186 }
187
188 /* The status code "osErrorParameter" (the value of the parameter
189 * ef_id is incorrect) is not supported in Zephyr.
190 */
191 if (events->is_cb_dynamic_allocation) {
192 k_mem_slab_free(&cmsis_rtos_event_cb_slab, (void *)events);
193 }
194 return osOK;
195 }
196