diff options
Diffstat (limited to 'lib/chibios-contrib/ext/mcux-sdk/devices/MK27FA15/utilities')
4 files changed, 1823 insertions, 0 deletions
diff --git a/lib/chibios-contrib/ext/mcux-sdk/devices/MK27FA15/utilities/fsl_notifier.c b/lib/chibios-contrib/ext/mcux-sdk/devices/MK27FA15/utilities/fsl_notifier.c new file mode 100644 index 000000000..7b7c02dc3 --- /dev/null +++ b/lib/chibios-contrib/ext/mcux-sdk/devices/MK27FA15/utilities/fsl_notifier.c | |||
@@ -0,0 +1,209 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2015, Freescale Semiconductor, Inc. | ||
3 | * Copyright 2016-2017 NXP | ||
4 | * All rights reserved. | ||
5 | * | ||
6 | * SPDX-License-Identifier: BSD-3-Clause | ||
7 | */ | ||
8 | |||
9 | #include "fsl_notifier.h" | ||
10 | |||
11 | /******************************************************************************* | ||
12 | * Definitions | ||
13 | ******************************************************************************/ | ||
14 | |||
15 | /******************************************************************************* | ||
16 | * Prototypes | ||
17 | ******************************************************************************/ | ||
18 | |||
19 | /******************************************************************************* | ||
20 | * Variables | ||
21 | ******************************************************************************/ | ||
22 | |||
23 | /******************************************************************************* | ||
24 | * Code | ||
25 | ******************************************************************************/ | ||
26 | |||
27 | /*! | ||
28 | * brief Creates a Notifier handle. | ||
29 | * | ||
30 | * param notifierHandle A pointer to the notifier handle. | ||
31 | * param configs A pointer to an array with references to all configurations which is handled by the Notifier. | ||
32 | * param configsNumber Number of configurations. Size of the configuration array. | ||
33 | * param callbacks A pointer to an array of callback configurations. | ||
34 | * If there are no callbacks to register during Notifier initialization, use NULL value. | ||
35 | * param callbacksNumber Number of registered callbacks. Size of the callbacks array. | ||
36 | * param userFunction User function. | ||
37 | * param userData User data passed to user function. | ||
38 | * return An error Code or kStatus_Success. | ||
39 | */ | ||
40 | status_t NOTIFIER_CreateHandle(notifier_handle_t *notifierHandle, | ||
41 | notifier_user_config_t **configs, | ||
42 | uint8_t configsNumber, | ||
43 | notifier_callback_config_t *callbacks, | ||
44 | uint8_t callbacksNumber, | ||
45 | notifier_user_function_t userFunction, | ||
46 | void *userData) | ||
47 | { | ||
48 | /* Check input parameter - at least one configuration is required and userFunction must exist */ | ||
49 | if ((configs == NULL) || (configsNumber == 0U) || (userFunction == NULL)) | ||
50 | { | ||
51 | return kStatus_Fail; | ||
52 | } | ||
53 | /* Initialize handle structure */ | ||
54 | (void)memset(notifierHandle, 0, sizeof(notifier_handle_t)); | ||
55 | /* Store references to user-defined configurations */ | ||
56 | notifierHandle->configsTable = configs; | ||
57 | notifierHandle->configsNumber = configsNumber; | ||
58 | /* Store references to user-defined callback configurations */ | ||
59 | if (callbacks != NULL) | ||
60 | { | ||
61 | notifierHandle->callbacksTable = callbacks; | ||
62 | notifierHandle->callbacksNumber = callbacksNumber; | ||
63 | /* If all callbacks return success, then the errorCallbackIndex is callbacksNumber */ | ||
64 | notifierHandle->errorCallbackIndex = callbacksNumber; | ||
65 | } | ||
66 | notifierHandle->userFunction = userFunction; | ||
67 | notifierHandle->userData = userData; | ||
68 | |||
69 | return kStatus_Success; | ||
70 | } | ||
71 | |||
72 | /*! | ||
73 | * brief Switches the configuration according to a pre-defined structure. | ||
74 | * | ||
75 | * This function sets the system to the target configuration. Before transition, | ||
76 | * the Notifier sends notifications to all callbacks registered to the callback table. | ||
77 | * Callbacks are invoked in the following order: All registered callbacks are notified | ||
78 | * ordered by index in the callbacks array. The same order is used for before and after switch notifications. | ||
79 | * The notifications before the configuration switch can be used to obtain confirmation about | ||
80 | * the change from registered callbacks. If any registered callback denies the | ||
81 | * configuration change, further execution of this function depends on the notifier policy: the | ||
82 | * configuration change is either forced (kNOTIFIER_PolicyForcible) or exited (kNOTIFIER_PolicyAgreement). | ||
83 | * When configuration change is forced, the result of the before switch notifications are ignored. If an | ||
84 | * agreement is required, if any callback returns an error code, further notifications | ||
85 | * before switch notifications are cancelled and all already notified callbacks are re-invoked. | ||
86 | * The index of the callback which returned error code during pre-switch notifications is stored | ||
87 | * (any error codes during callbacks re-invocation are ignored) and NOTIFIER_GetErrorCallback() can be used to get it. | ||
88 | * Regardless of the policies, if any callback returns an error code, an error code indicating in which phase | ||
89 | * the error occurred is returned when NOTIFIER_SwitchConfig() exits. | ||
90 | * param notifierHandle pointer to notifier handle | ||
91 | * param configIndex Index of the target configuration. | ||
92 | * param policy Transaction policy, kNOTIFIER_PolicyAgreement or kNOTIFIER_PolicyForcible. | ||
93 | * | ||
94 | * return An error code or kStatus_Success. | ||
95 | * | ||
96 | */ | ||
97 | status_t NOTIFIER_SwitchConfig(notifier_handle_t *notifierHandle, uint8_t configIndex, notifier_policy_t policy) | ||
98 | { | ||
99 | uint8_t currentStaticCallback = 0U; /* Index to array of statically registered call-backs */ | ||
100 | status_t returnCode = kStatus_Success; /* Function return */ | ||
101 | |||
102 | notifier_notification_block_t notifyBlock; /* Callback notification block */ | ||
103 | notifier_callback_config_t *callbackConfig; /* Pointer to callback configuration */ | ||
104 | |||
105 | /* Set errorcallbackindex as callbacksNumber, which means no callback error now */ | ||
106 | notifierHandle->errorCallbackIndex = notifierHandle->callbacksNumber; | ||
107 | |||
108 | /* Requested configuration availability check */ | ||
109 | if (configIndex >= notifierHandle->configsNumber) | ||
110 | { | ||
111 | return kStatus_OutOfRange; | ||
112 | } | ||
113 | |||
114 | /* Initialization of local variables from the Notifier handle structure */ | ||
115 | |||
116 | notifyBlock.policy = policy; | ||
117 | notifyBlock.targetConfig = notifierHandle->configsTable[configIndex]; | ||
118 | notifyBlock.notifyType = kNOTIFIER_NotifyBefore; | ||
119 | |||
120 | /* From all statically registered call-backs... */ | ||
121 | for (currentStaticCallback = 0U; currentStaticCallback < notifierHandle->callbacksNumber; currentStaticCallback++) | ||
122 | { | ||
123 | callbackConfig = &(notifierHandle->callbacksTable[currentStaticCallback]); | ||
124 | /* ...notify only those which asked to be called before the configuration switch */ | ||
125 | if (((uint32_t)callbackConfig->callbackType & (uint32_t)kNOTIFIER_CallbackBefore) != 0U) | ||
126 | { | ||
127 | /* In case that call-back returned error code mark it, store the call-back handle and eventually cancel | ||
128 | * the configuration switch */ | ||
129 | if (callbackConfig->callback(¬ifyBlock, callbackConfig->callbackData) != kStatus_Success) | ||
130 | { | ||
131 | returnCode = (status_t)kStatus_NOTIFIER_ErrorNotificationBefore; | ||
132 | notifierHandle->errorCallbackIndex = currentStaticCallback; | ||
133 | /* If not forcing configuration switch, call all already notified call-backs to revert their state | ||
134 | * as the switch is canceled */ | ||
135 | if (policy != kNOTIFIER_PolicyForcible) | ||
136 | { | ||
137 | break; | ||
138 | } | ||
139 | } | ||
140 | } | ||
141 | } | ||
142 | |||
143 | /* Set configuration */ | ||
144 | |||
145 | /* In case that any call-back returned error code and policy doesn't force the configuration set, go to after | ||
146 | * switch call-backs */ | ||
147 | if ((policy == kNOTIFIER_PolicyForcible) || (returnCode == kStatus_Success)) | ||
148 | { | ||
149 | returnCode = notifierHandle->userFunction(notifierHandle->configsTable[configIndex], notifierHandle->userData); | ||
150 | if (returnCode != kStatus_Success) | ||
151 | { | ||
152 | return returnCode; | ||
153 | } | ||
154 | /* Update current configuration index */ | ||
155 | notifierHandle->currentConfigIndex = configIndex; | ||
156 | notifyBlock.notifyType = kNOTIFIER_NotifyAfter; | ||
157 | /* From all statically registered call-backs... */ | ||
158 | for (currentStaticCallback = 0U; currentStaticCallback < notifierHandle->callbacksNumber; | ||
159 | currentStaticCallback++) | ||
160 | { | ||
161 | callbackConfig = &(notifierHandle->callbacksTable[currentStaticCallback]); | ||
162 | /* ...notify only those which asked to be called after the configuration switch */ | ||
163 | if (((uint32_t)callbackConfig->callbackType & (uint32_t)kNOTIFIER_CallbackAfter) != 0U) | ||
164 | { | ||
165 | /* In case that call-back returned error code mark it and store the call-back handle */ | ||
166 | if (callbackConfig->callback(¬ifyBlock, callbackConfig->callbackData) != kStatus_Success) | ||
167 | { | ||
168 | returnCode = (status_t)kStatus_NOTIFIER_ErrorNotificationAfter; | ||
169 | notifierHandle->errorCallbackIndex = currentStaticCallback; | ||
170 | if (policy != kNOTIFIER_PolicyForcible) | ||
171 | { | ||
172 | break; | ||
173 | } | ||
174 | } | ||
175 | } | ||
176 | } | ||
177 | } | ||
178 | else | ||
179 | { | ||
180 | /* End of unsuccessful switch */ | ||
181 | notifyBlock.notifyType = kNOTIFIER_NotifyRecover; | ||
182 | while (currentStaticCallback-- > 0U) | ||
183 | { | ||
184 | callbackConfig = &(notifierHandle->callbacksTable[currentStaticCallback]); | ||
185 | if (((uint32_t)callbackConfig->callbackType & (uint32_t)kNOTIFIER_CallbackBefore) != 0U) | ||
186 | { | ||
187 | (void)callbackConfig->callback(¬ifyBlock, callbackConfig->callbackData); | ||
188 | } | ||
189 | } | ||
190 | } | ||
191 | |||
192 | return returnCode; | ||
193 | } | ||
194 | |||
195 | /*! | ||
196 | * brief This function returns the last failed notification callback. | ||
197 | * | ||
198 | * This function returns an index of the last callback that failed during the configuration switch while | ||
199 | * the last NOTIFIER_SwitchConfig() was called. If the last NOTIFIER_SwitchConfig() call ended successfully | ||
200 | * value equal to callbacks number is returned. The returned value represents an index in the array of | ||
201 | * static call-backs. | ||
202 | * | ||
203 | * param notifierHandle Pointer to the notifier handle | ||
204 | * return Callback Index of the last failed callback or value equal to callbacks count. | ||
205 | */ | ||
206 | uint8_t NOTIFIER_GetErrorCallbackIndex(notifier_handle_t *notifierHandle) | ||
207 | { | ||
208 | return notifierHandle->errorCallbackIndex; | ||
209 | } | ||
diff --git a/lib/chibios-contrib/ext/mcux-sdk/devices/MK27FA15/utilities/fsl_notifier.h b/lib/chibios-contrib/ext/mcux-sdk/devices/MK27FA15/utilities/fsl_notifier.h new file mode 100644 index 000000000..d93578c13 --- /dev/null +++ b/lib/chibios-contrib/ext/mcux-sdk/devices/MK27FA15/utilities/fsl_notifier.h | |||
@@ -0,0 +1,237 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2015, Freescale Semiconductor, Inc. | ||
3 | * Copyright 2016-2017 NXP | ||
4 | * All rights reserved. | ||
5 | * | ||
6 | * SPDX-License-Identifier: BSD-3-Clause | ||
7 | */ | ||
8 | |||
9 | #ifndef _FSL_NOTIFIER_H_ | ||
10 | #define _FSL_NOTIFIER_H_ | ||
11 | |||
12 | #include "fsl_common.h" | ||
13 | /*! | ||
14 | * @addtogroup notifier | ||
15 | * @{ | ||
16 | */ | ||
17 | |||
18 | /******************************************************************************* | ||
19 | * Definitions | ||
20 | ******************************************************************************/ | ||
21 | |||
22 | /*! | ||
23 | * @brief Notifier error codes. | ||
24 | * | ||
25 | * Used as return value of Notifier functions. | ||
26 | */ | ||
27 | enum _notifier_status | ||
28 | { | ||
29 | kStatus_NOTIFIER_ErrorNotificationBefore = | ||
30 | MAKE_STATUS(kStatusGroup_NOTIFIER, 0), /*!< An error occurs during send "BEFORE" notification. */ | ||
31 | kStatus_NOTIFIER_ErrorNotificationAfter = | ||
32 | MAKE_STATUS(kStatusGroup_NOTIFIER, 1), /*!< An error occurs during send "AFTER" notification. */ | ||
33 | }; | ||
34 | |||
35 | /*! | ||
36 | * @brief Notifier policies. | ||
37 | * | ||
38 | * Defines whether the user function execution is forced or not. | ||
39 | * For kNOTIFIER_PolicyForcible, the user function is executed regardless of the callback results, | ||
40 | * while kNOTIFIER_PolicyAgreement policy is used to exit NOTIFIER_SwitchConfig() | ||
41 | * when any of the callbacks returns error code. | ||
42 | * See also NOTIFIER_SwitchConfig() description. | ||
43 | */ | ||
44 | typedef enum _notifier_policy | ||
45 | { | ||
46 | kNOTIFIER_PolicyAgreement, /*!< NOTIFIER_SwitchConfig() method is exited when any of the callbacks returns error | ||
47 | code. */ | ||
48 | kNOTIFIER_PolicyForcible, /*!< The user function is executed regardless of the results. */ | ||
49 | } notifier_policy_t; | ||
50 | |||
51 | /*! @brief Notification type. Used to notify registered callbacks */ | ||
52 | typedef enum _notifier_notification_type | ||
53 | { | ||
54 | kNOTIFIER_NotifyRecover = 0x00U, /*!< Notify IP to recover to previous work state. */ | ||
55 | kNOTIFIER_NotifyBefore = 0x01U, /*!< Notify IP that configuration setting is going to change. */ | ||
56 | kNOTIFIER_NotifyAfter = 0x02U, /*!< Notify IP that configuration setting has been changed. */ | ||
57 | } notifier_notification_type_t; | ||
58 | |||
59 | /*! | ||
60 | * @brief The callback type, which indicates kinds of notification the callback handles. | ||
61 | * | ||
62 | * Used in the callback configuration structure (notifier_callback_config_t) | ||
63 | * to specify when the registered callback is called during configuration switch initiated by the | ||
64 | * NOTIFIER_SwitchConfig(). | ||
65 | * Callback can be invoked in following situations. | ||
66 | * - Before the configuration switch (Callback return value can affect NOTIFIER_SwitchConfig() | ||
67 | * execution. See the NOTIFIER_SwitchConfig() and notifier_policy_t documentation). | ||
68 | * - After an unsuccessful attempt to switch configuration | ||
69 | * - After a successful configuration switch | ||
70 | */ | ||
71 | typedef enum _notifier_callback_type | ||
72 | { | ||
73 | kNOTIFIER_CallbackBefore = 0x01U, /*!< Callback handles BEFORE notification. */ | ||
74 | kNOTIFIER_CallbackAfter = 0x02U, /*!< Callback handles AFTER notification. */ | ||
75 | kNOTIFIER_CallbackBeforeAfter = 0x03U, /*!< Callback handles BEFORE and AFTER notification. */ | ||
76 | } notifier_callback_type_t; | ||
77 | |||
78 | /*! @brief Notifier user configuration type. | ||
79 | * | ||
80 | * Reference of the user defined configuration is stored in an array; the notifier switches between these configurations | ||
81 | * based on this array. | ||
82 | */ | ||
83 | typedef void notifier_user_config_t; | ||
84 | |||
85 | /*! @brief Notifier user function prototype | ||
86 | * Use this function to execute specific operations in configuration switch. | ||
87 | * Before and after this function execution, different notification is sent to registered callbacks. | ||
88 | * If this function returns any error code, NOTIFIER_SwitchConfig() exits. | ||
89 | * | ||
90 | * @param targetConfig target Configuration. | ||
91 | * @param userData Refers to other specific data passed to user function. | ||
92 | * @return An error code or kStatus_Success. | ||
93 | */ | ||
94 | typedef status_t (*notifier_user_function_t)(notifier_user_config_t *targetConfig, void *userData); | ||
95 | |||
96 | /*! @brief notification block passed to the registered callback function. */ | ||
97 | typedef struct _notifier_notification_block | ||
98 | { | ||
99 | notifier_user_config_t *targetConfig; /*!< Pointer to target configuration. */ | ||
100 | notifier_policy_t policy; /*!< Configure transition policy. */ | ||
101 | notifier_notification_type_t notifyType; /*!< Configure notification type. */ | ||
102 | } notifier_notification_block_t; | ||
103 | |||
104 | /*! | ||
105 | * @brief Callback prototype. | ||
106 | * | ||
107 | * Declaration of a callback. It is common for registered callbacks. | ||
108 | * Reference to function of this type is part of the notifier_callback_config_t callback configuration structure. | ||
109 | * Depending on callback type, function of this prototype is called (see NOTIFIER_SwitchConfig()) | ||
110 | * before configuration switch, after it or in both use cases to notify about | ||
111 | * the switch progress (see notifier_callback_type_t). When called, the type of the notification | ||
112 | * is passed as a parameter along with the reference to the target configuration structure (see | ||
113 | * notifier_notification_block_t) and any data passed during the callback registration. When notified before the | ||
114 | * configuration switch, depending on the configuration switch policy (see notifier_policy_t), the callback may deny the | ||
115 | * execution of the user function by returning an error code different than kStatus_Success (see | ||
116 | * NOTIFIER_SwitchConfig()). | ||
117 | * | ||
118 | * @param notify Notification block. | ||
119 | * @param data Callback data. Refers to the data passed during callback registration. Intended to | ||
120 | * pass any driver or application data such as internal state information. | ||
121 | * @return An error code or kStatus_Success. | ||
122 | */ | ||
123 | typedef status_t (*notifier_callback_t)(notifier_notification_block_t *notify, void *data); | ||
124 | |||
125 | /*! | ||
126 | * @brief Callback configuration structure. | ||
127 | * | ||
128 | * This structure holds the configuration of callbacks. | ||
129 | * Callbacks of this type are expected to be statically allocated. | ||
130 | * This structure contains the following application-defined data. | ||
131 | * callback - pointer to the callback function | ||
132 | * callbackType - specifies when the callback is called | ||
133 | * callbackData - pointer to the data passed to the callback. | ||
134 | */ | ||
135 | typedef struct _notifier_callback_config | ||
136 | { | ||
137 | notifier_callback_t callback; /*!< Pointer to the callback function. */ | ||
138 | notifier_callback_type_t callbackType; /*!< Callback type. */ | ||
139 | void *callbackData; /*!< Pointer to the data passed to the callback. */ | ||
140 | } notifier_callback_config_t; | ||
141 | |||
142 | /*! | ||
143 | * @brief Notifier handle structure. | ||
144 | * | ||
145 | * Notifier handle structure. Contains data necessary for the Notifier proper function. | ||
146 | * Stores references to registered configurations, callbacks, information about their numbers, | ||
147 | * user function, user data, and other internal data. | ||
148 | * NOTIFIER_CreateHandle() must be called to initialize this handle. | ||
149 | */ | ||
150 | typedef struct _notifier_handle | ||
151 | { | ||
152 | notifier_user_config_t **configsTable; /*!< Pointer to configure table. */ | ||
153 | uint8_t configsNumber; /*!< Number of configurations. */ | ||
154 | notifier_callback_config_t *callbacksTable; /*!< Pointer to callback table. */ | ||
155 | uint8_t callbacksNumber; /*!< Maximum number of callback configurations. */ | ||
156 | uint8_t errorCallbackIndex; /*!< Index of callback returns error. */ | ||
157 | uint8_t currentConfigIndex; /*!< Index of current configuration. */ | ||
158 | notifier_user_function_t userFunction; /*!< User function. */ | ||
159 | void *userData; /*!< User data passed to user function. */ | ||
160 | } notifier_handle_t; | ||
161 | |||
162 | /******************************************************************************* | ||
163 | * API | ||
164 | ******************************************************************************/ | ||
165 | |||
166 | #if defined(__cplusplus) | ||
167 | extern "C" { | ||
168 | #endif | ||
169 | |||
170 | /*! | ||
171 | * @brief Creates a Notifier handle. | ||
172 | * | ||
173 | * @param notifierHandle A pointer to the notifier handle. | ||
174 | * @param configs A pointer to an array with references to all configurations which is handled by the Notifier. | ||
175 | * @param configsNumber Number of configurations. Size of the configuration array. | ||
176 | * @param callbacks A pointer to an array of callback configurations. | ||
177 | * If there are no callbacks to register during Notifier initialization, use NULL value. | ||
178 | * @param callbacksNumber Number of registered callbacks. Size of the callbacks array. | ||
179 | * @param userFunction User function. | ||
180 | * @param userData User data passed to user function. | ||
181 | * @return An error Code or kStatus_Success. | ||
182 | */ | ||
183 | status_t NOTIFIER_CreateHandle(notifier_handle_t *notifierHandle, | ||
184 | notifier_user_config_t **configs, | ||
185 | uint8_t configsNumber, | ||
186 | notifier_callback_config_t *callbacks, | ||
187 | uint8_t callbacksNumber, | ||
188 | notifier_user_function_t userFunction, | ||
189 | void *userData); | ||
190 | |||
191 | /*! | ||
192 | * @brief Switches the configuration according to a pre-defined structure. | ||
193 | * | ||
194 | * This function sets the system to the target configuration. Before transition, | ||
195 | * the Notifier sends notifications to all callbacks registered to the callback table. | ||
196 | * Callbacks are invoked in the following order: All registered callbacks are notified | ||
197 | * ordered by index in the callbacks array. The same order is used for before and after switch notifications. | ||
198 | * The notifications before the configuration switch can be used to obtain confirmation about | ||
199 | * the change from registered callbacks. If any registered callback denies the | ||
200 | * configuration change, further execution of this function depends on the notifier policy: the | ||
201 | * configuration change is either forced (kNOTIFIER_PolicyForcible) or exited (kNOTIFIER_PolicyAgreement). | ||
202 | * When configuration change is forced, the result of the before switch notifications are ignored. If an | ||
203 | * agreement is required, if any callback returns an error code, further notifications | ||
204 | * before switch notifications are cancelled and all already notified callbacks are re-invoked. | ||
205 | * The index of the callback which returned error code during pre-switch notifications is stored | ||
206 | * (any error codes during callbacks re-invocation are ignored) and NOTIFIER_GetErrorCallback() can be used to get it. | ||
207 | * Regardless of the policies, if any callback returns an error code, an error code indicating in which phase | ||
208 | * the error occurred is returned when NOTIFIER_SwitchConfig() exits. | ||
209 | * @param notifierHandle pointer to notifier handle | ||
210 | * @param configIndex Index of the target configuration. | ||
211 | * @param policy Transaction policy, kNOTIFIER_PolicyAgreement or kNOTIFIER_PolicyForcible. | ||
212 | * | ||
213 | * @return An error code or kStatus_Success. | ||
214 | * | ||
215 | */ | ||
216 | status_t NOTIFIER_SwitchConfig(notifier_handle_t *notifierHandle, uint8_t configIndex, notifier_policy_t policy); | ||
217 | |||
218 | /*! | ||
219 | * @brief This function returns the last failed notification callback. | ||
220 | * | ||
221 | * This function returns an index of the last callback that failed during the configuration switch while | ||
222 | * the last NOTIFIER_SwitchConfig() was called. If the last NOTIFIER_SwitchConfig() call ended successfully | ||
223 | * value equal to callbacks number is returned. The returned value represents an index in the array of | ||
224 | * static call-backs. | ||
225 | * | ||
226 | * @param notifierHandle Pointer to the notifier handle | ||
227 | * @return Callback Index of the last failed callback or value equal to callbacks count. | ||
228 | */ | ||
229 | uint8_t NOTIFIER_GetErrorCallbackIndex(notifier_handle_t *notifierHandle); | ||
230 | |||
231 | #if defined(__cplusplus) | ||
232 | } | ||
233 | #endif /* __cplusplus */ | ||
234 | |||
235 | /*! @}*/ | ||
236 | |||
237 | #endif /* _FSL_NOTIFIER_H_ */ | ||
diff --git a/lib/chibios-contrib/ext/mcux-sdk/devices/MK27FA15/utilities/fsl_shell.c b/lib/chibios-contrib/ext/mcux-sdk/devices/MK27FA15/utilities/fsl_shell.c new file mode 100644 index 000000000..2cc75f02e --- /dev/null +++ b/lib/chibios-contrib/ext/mcux-sdk/devices/MK27FA15/utilities/fsl_shell.c | |||
@@ -0,0 +1,1085 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2015, Freescale Semiconductor, Inc. | ||
3 | * Copyright 2016-2020 NXP | ||
4 | * All rights reserved. | ||
5 | * | ||
6 | * SPDX-License-Identifier: BSD-3-Clause | ||
7 | * | ||
8 | * POSIX getopt for Windows | ||
9 | * Code given out at the 1985 UNIFORUM conference in Dallas. | ||
10 | * | ||
11 | * From [email protected] (Moderator, John Quarterman) Sun Nov 3 14:34:15 1985 | ||
12 | * Relay-Version: version B 2.10.3 4.3bsd-beta 6/6/85; site gatech.CSNET | ||
13 | * Posting-Version: version B 2.10.2 9/18/84; site ut-sally.UUCP | ||
14 | * Path: gatech!akgua!mhuxv!mhuxt!mhuxr!ulysses!allegra!mit-eddie!genrad!panda!talcott!harvard!seismo!ut-sally!std-unix | ||
15 | * From: [email protected] (Moderator, John Quarterman) | ||
16 | * Newsgroups: mod.std.unix | ||
17 | * Subject: public domain AT&T getopt source | ||
18 | * Message-ID: <[email protected]> | ||
19 | * Date: 3 Nov 85 19:34:15 GMT | ||
20 | * Date-Received: 4 Nov 85 12:25:09 GMT | ||
21 | * Organization: IEEE/P1003 Portable Operating System Environment Committee | ||
22 | * Lines: 91 | ||
23 | * Approved: [email protected] | ||
24 | * Here's something you've all been waiting for: the AT&T public domain | ||
25 | * source for getopt(3). It is the code which was given out at the 1985 | ||
26 | * UNIFORUM conference in Dallas. I obtained it by electronic mail | ||
27 | * directly from AT&T. The people there assure me that it is indeed | ||
28 | * in the public domain | ||
29 | * There is no manual page. That is because the one they gave out at | ||
30 | * UNIFORUM was slightly different from the current System V Release 2 | ||
31 | * manual page. The difference apparently involved a note about the | ||
32 | * famous rules 5 and 6, recommending using white space between an option | ||
33 | * and its first argument, and not grouping options that have arguments. | ||
34 | * Getopt itself is currently lenient about both of these things White | ||
35 | * space is allowed, but not mandatory, and the last option in a group can | ||
36 | * have an argument. That particular version of the man page evidently | ||
37 | * has no official existence, and my source at AT&T did not send a copy. | ||
38 | * The current SVR2 man page reflects the actual behavor of this getopt. | ||
39 | * However, I am not about to post a copy of anything licensed by AT&T. | ||
40 | */ | ||
41 | |||
42 | #include <assert.h> | ||
43 | #include <stdarg.h> | ||
44 | #include <stdlib.h> | ||
45 | #include <stdio.h> | ||
46 | |||
47 | #include "fsl_common.h" | ||
48 | #include "fsl_str.h" | ||
49 | |||
50 | #include "fsl_component_generic_list.h" | ||
51 | #include "fsl_component_serial_manager.h" | ||
52 | |||
53 | #include "fsl_shell.h" | ||
54 | |||
55 | /* | ||
56 | * The OSA_USED macro can only be defined when the OSA component is used. | ||
57 | * If the source code of the OSA component does not exist, the OSA_USED cannot be defined. | ||
58 | * OR, If OSA component is not added into project event the OSA source code exists, the OSA_USED | ||
59 | * also cannot be defined. | ||
60 | * The source code path of the OSA component is <MCUXpresso_SDK>/components/osa. | ||
61 | * | ||
62 | */ | ||
63 | #if defined(OSA_USED) | ||
64 | |||
65 | #if (defined(SHELL_USE_COMMON_TASK) && (SHELL_USE_COMMON_TASK > 0U)) | ||
66 | #include "fsl_component_common_task.h" | ||
67 | #else | ||
68 | #include "fsl_os_abstraction.h" | ||
69 | #endif | ||
70 | |||
71 | #endif | ||
72 | |||
73 | /******************************************************************************* | ||
74 | * Definitions | ||
75 | ******************************************************************************/ | ||
76 | #define KEY_ESC (0x1BU) | ||
77 | #define KET_DEL (0x7FU) | ||
78 | |||
79 | #define SHELL_EVENT_DATA_ARRIVED (1U << 0) | ||
80 | #define SHELL_EVENT_DATA_SENT (1U << 1) | ||
81 | |||
82 | #define SHELL_SPRINTF_BUFFER_SIZE (64U) | ||
83 | |||
84 | /*! @brief A type for the handle special key. */ | ||
85 | typedef enum _fun_key_status | ||
86 | { | ||
87 | kSHELL_Normal = 0U, /*!< Normal key */ | ||
88 | kSHELL_Special = 1U, /*!< Special key */ | ||
89 | kSHELL_Function = 2U, /*!< Function key */ | ||
90 | } fun_key_status_t; | ||
91 | |||
92 | /*! @brief Data structure for Shell environment. */ | ||
93 | typedef struct _shell_context_handle | ||
94 | { | ||
95 | list_label_t commandContextListHead; /*!< Command shellContextHandle list queue head */ | ||
96 | serial_handle_t serialHandle; /*!< Serial manager handle */ | ||
97 | uint8_t | ||
98 | serialWriteHandleBuffer[SERIAL_MANAGER_WRITE_HANDLE_SIZE]; /*!< The buffer for serial manager write handle */ | ||
99 | serial_write_handle_t serialWriteHandle; /*!< The serial manager write handle */ | ||
100 | uint8_t serialReadHandleBuffer[SERIAL_MANAGER_READ_HANDLE_SIZE]; /*!< The buffer for serial manager read handle */ | ||
101 | serial_read_handle_t serialReadHandle; /*!< The serial manager read handle */ | ||
102 | char *prompt; /*!< Prompt string */ | ||
103 | #if (defined(SHELL_NON_BLOCKING_MODE) && (SHELL_NON_BLOCKING_MODE > 0U)) | ||
104 | |||
105 | #if defined(OSA_USED) | ||
106 | |||
107 | #if (defined(SHELL_USE_COMMON_TASK) && (SHELL_USE_COMMON_TASK > 0U)) | ||
108 | common_task_message_t commontaskMsg; /*!< Message for common task */ | ||
109 | #else | ||
110 | uint8_t event[OSA_EVENT_HANDLE_SIZE]; /*!< Event instance */ | ||
111 | uint8_t taskId[OSA_TASK_HANDLE_SIZE]; /*!< Task handle */ | ||
112 | #endif | ||
113 | |||
114 | #endif | ||
115 | |||
116 | #endif | ||
117 | char line[SHELL_BUFFER_SIZE]; /*!< Consult buffer */ | ||
118 | char hist_buf[SHELL_HISTORY_COUNT][SHELL_BUFFER_SIZE]; /*!< History buffer*/ | ||
119 | char printBuffer[SHELL_SPRINTF_BUFFER_SIZE]; /*!< Buffer for print */ | ||
120 | uint32_t printLength; /*!< All length has been printed */ | ||
121 | uint16_t hist_current; /*!< Current history command in hist buff*/ | ||
122 | uint16_t hist_count; /*!< Total history command in hist buff*/ | ||
123 | enum _fun_key_status stat; /*!< Special key status */ | ||
124 | uint8_t cmd_num; /*!< Number of user commands */ | ||
125 | uint8_t l_pos; /*!< Total line position */ | ||
126 | uint8_t c_pos; /*!< Current line position */ | ||
127 | volatile uint8_t notificationPost; /*!< The serial manager notification is post */ | ||
128 | uint8_t exit; /*!< Exit Flag*/ | ||
129 | uint8_t printBusy; /*!< Print is busy */ | ||
130 | } shell_context_handle_t; | ||
131 | |||
132 | #if 0 | ||
133 | #define SHELL_STRUCT_OFFSET(type, field) ((size_t) & (((type *)0)->field)) | ||
134 | #define SHEEL_COMMAND_POINTER(node) \ | ||
135 | ((shell_command_t *)(((uint32_t)(node)) - SHELL_STRUCT_OFFSET(shell_command_t, link))) | ||
136 | #else | ||
137 | #define SHEEL_COMMAND_POINTER(node) \ | ||
138 | ((shell_command_t *)(((uint32_t)(node)) - (sizeof(shell_command_t) - sizeof(list_element_t)))) | ||
139 | #endif | ||
140 | /******************************************************************************* | ||
141 | * Prototypes | ||
142 | ******************************************************************************/ | ||
143 | static shell_status_t SHELL_HelpCommand(shell_handle_t shellHandle, int32_t argc, char **argv); /*!< help command */ | ||
144 | |||
145 | static shell_status_t SHELL_ExitCommand(shell_handle_t shellHandle, int32_t argc, char **argv); /*!< exit command */ | ||
146 | |||
147 | static int32_t SHELL_ParseLine(const char *cmd, uint32_t len, char *argv[]); /*!< parse line command */ | ||
148 | |||
149 | static int32_t SHELL_StringCompare(const char *str1, const char *str2, int32_t count); /*!< compare string command */ | ||
150 | |||
151 | static void SHELL_ProcessCommand(shell_context_handle_t *shellContextHandle, const char *cmd); /*!< process a command */ | ||
152 | |||
153 | static void SHELL_GetHistoryCommand(shell_context_handle_t *shellContextHandle, | ||
154 | uint8_t hist_pos); /*!< get commands history */ | ||
155 | |||
156 | static void SHELL_AutoComplete(shell_context_handle_t *shellContextHandle); /*!< auto complete command */ | ||
157 | |||
158 | static shell_status_t SHELL_GetChar(shell_context_handle_t *shellContextHandle, | ||
159 | uint8_t *ch); /*!< get a char from communication interface */ | ||
160 | |||
161 | static void SHELL_WriteWithCopy(shell_handle_t shellHandle, const char *buffer, uint32_t length); | ||
162 | |||
163 | #if (defined(SHELL_NON_BLOCKING_MODE) && (SHELL_NON_BLOCKING_MODE > 0U)) | ||
164 | static void SHELL_Task(void *param); /*!< Shell task*/ | ||
165 | #endif | ||
166 | |||
167 | /******************************************************************************* | ||
168 | * Variables | ||
169 | ******************************************************************************/ | ||
170 | |||
171 | static SHELL_COMMAND_DEFINE(help, "\r\n\"help\": List all the registered commands\r\n", SHELL_HelpCommand, 0); | ||
172 | static SHELL_COMMAND_DEFINE(exit, "\r\n\"exit\": Exit program\r\n", SHELL_ExitCommand, 0); | ||
173 | |||
174 | static char s_paramBuffer[SHELL_BUFFER_SIZE]; | ||
175 | |||
176 | #if (defined(SHELL_NON_BLOCKING_MODE) && (SHELL_NON_BLOCKING_MODE > 0U)) | ||
177 | #if defined(OSA_USED) | ||
178 | #if (defined(SHELL_USE_COMMON_TASK) && (SHELL_USE_COMMON_TASK > 0U)) | ||
179 | #else | ||
180 | /* | ||
181 | * \brief Defines the serial manager task's stack | ||
182 | */ | ||
183 | static OSA_TASK_DEFINE(SHELL_Task, SHELL_TASK_PRIORITY, 1, SHELL_TASK_STACK_SIZE, false); | ||
184 | #endif | ||
185 | #endif /* OSA_USED */ | ||
186 | #endif /* SHELL_NON_BLOCKING_MODE */ | ||
187 | /******************************************************************************* | ||
188 | * Code | ||
189 | ******************************************************************************/ | ||
190 | |||
191 | #if (defined(SHELL_NON_BLOCKING_MODE) && (SHELL_NON_BLOCKING_MODE > 0U)) | ||
192 | static void SHELL_SerialManagerRxCallback(void *callbackParam, | ||
193 | serial_manager_callback_message_t *message, | ||
194 | serial_manager_status_t status) | ||
195 | { | ||
196 | shell_context_handle_t *shellHandle; | ||
197 | |||
198 | assert(callbackParam); | ||
199 | assert(message); | ||
200 | |||
201 | shellHandle = (shell_context_handle_t *)callbackParam; | ||
202 | |||
203 | if (0U == shellHandle->notificationPost) | ||
204 | { | ||
205 | shellHandle->notificationPost = 1U; | ||
206 | #if defined(OSA_USED) | ||
207 | |||
208 | #if (defined(SHELL_USE_COMMON_TASK) && (SHELL_USE_COMMON_TASK > 0U)) | ||
209 | shellHandle->commontaskMsg.callback = SHELL_Task; | ||
210 | shellHandle->commontaskMsg.callbackParam = shellHandle; | ||
211 | (void)COMMON_TASK_post_message(&shellHandle->commontaskMsg); | ||
212 | #else | ||
213 | (void)OSA_EventSet((osa_event_handle_t)shellHandle->event, SHELL_EVENT_DATA_ARRIVED); | ||
214 | #endif | ||
215 | |||
216 | #else | ||
217 | SHELL_Task(shellHandle); | ||
218 | #endif | ||
219 | } | ||
220 | } | ||
221 | #endif | ||
222 | |||
223 | static void SHELL_WriteBuffer(char *buffer, int32_t *indicator, char val, int len) | ||
224 | { | ||
225 | shell_context_handle_t *shellContextHandle; | ||
226 | int i = 0; | ||
227 | shellContextHandle = (shell_context_handle_t *)(void *)buffer; | ||
228 | |||
229 | for (i = 0; i < len; i++) | ||
230 | { | ||
231 | if ((*indicator + 1) >= (int32_t)SHELL_SPRINTF_BUFFER_SIZE) | ||
232 | { | ||
233 | #if (!defined(SDK_DEBUGCONSOLE_UART) && (defined(SDK_DEBUGCONSOLE) && (SDK_DEBUGCONSOLE != 1))) | ||
234 | if (NULL == shellContextHandle->serialHandle) | ||
235 | { | ||
236 | for (uint32_t index = 0; index < ((uint32_t)*indicator); index++) | ||
237 | { | ||
238 | (void)putchar(shellContextHandle->printBuffer[index]); | ||
239 | } | ||
240 | } | ||
241 | else | ||
242 | #endif | ||
243 | { | ||
244 | (void)SerialManager_WriteBlocking(shellContextHandle->serialWriteHandle, | ||
245 | (uint8_t *)shellContextHandle->printBuffer, (uint32_t)*indicator); | ||
246 | } | ||
247 | |||
248 | shellContextHandle->printLength += (uint32_t)*indicator; | ||
249 | *indicator = 0; | ||
250 | } | ||
251 | |||
252 | shellContextHandle->printBuffer[*indicator] = val; | ||
253 | (*indicator)++; | ||
254 | } | ||
255 | } | ||
256 | |||
257 | static int SHELL_Sprintf(void *buffer, const char *formatString, va_list ap) | ||
258 | { | ||
259 | shell_context_handle_t *shellContextHandle; | ||
260 | uint32_t length; | ||
261 | shellContextHandle = (shell_context_handle_t *)buffer; | ||
262 | |||
263 | length = (uint32_t)StrFormatPrintf(formatString, ap, (char *)buffer, SHELL_WriteBuffer); | ||
264 | shellContextHandle->printLength += length; | ||
265 | return (int32_t)length; | ||
266 | } | ||
267 | |||
268 | #if (defined(SHELL_NON_BLOCKING_MODE) && (SHELL_NON_BLOCKING_MODE > 0U)) | ||
269 | static void SHELL_Task(void *param) | ||
270 | #else | ||
271 | void SHELL_Task(shell_handle_t shellHandle) | ||
272 | #endif | ||
273 | { | ||
274 | #if (defined(SHELL_NON_BLOCKING_MODE) && (SHELL_NON_BLOCKING_MODE > 0U)) | ||
275 | shell_context_handle_t *shellContextHandle = (shell_context_handle_t *)param; | ||
276 | #else | ||
277 | shell_context_handle_t *shellContextHandle = (shell_context_handle_t *)shellHandle; | ||
278 | #endif | ||
279 | uint8_t ch; | ||
280 | |||
281 | if (NULL != shellContextHandle) | ||
282 | { | ||
283 | #if (defined(SHELL_NON_BLOCKING_MODE) && (SHELL_NON_BLOCKING_MODE > 0U)) | ||
284 | |||
285 | #if defined(OSA_USED) | ||
286 | |||
287 | #if (defined(SHELL_USE_COMMON_TASK) && (SHELL_USE_COMMON_TASK > 0U)) | ||
288 | #else | ||
289 | osa_event_flags_t ev = 0; | ||
290 | |||
291 | do | ||
292 | { | ||
293 | if (KOSA_StatusSuccess == OSA_EventWait((osa_event_handle_t)shellContextHandle->event, osaEventFlagsAll_c, | ||
294 | 0U, osaWaitForever_c, &ev)) | ||
295 | { | ||
296 | if (0U != (ev & SHELL_EVENT_DATA_ARRIVED)) | ||
297 | #endif | ||
298 | |||
299 | #endif | ||
300 | |||
301 | #endif | ||
302 | { | ||
303 | shellContextHandle->notificationPost = 0; | ||
304 | do | ||
305 | { | ||
306 | if ((bool)shellContextHandle->exit) | ||
307 | { | ||
308 | if (shellContextHandle->serialReadHandle != NULL) | ||
309 | { | ||
310 | (void)SerialManager_CloseReadHandle(shellContextHandle->serialReadHandle); | ||
311 | shellContextHandle->serialReadHandle = NULL; | ||
312 | } | ||
313 | if (shellContextHandle->serialWriteHandle != NULL) | ||
314 | { | ||
315 | (void)SerialManager_CloseWriteHandle(shellContextHandle->serialWriteHandle); | ||
316 | shellContextHandle->serialWriteHandle = NULL; | ||
317 | } | ||
318 | break; | ||
319 | } | ||
320 | if (kStatus_SHELL_Success != (shell_status_t)SHELL_GetChar(shellContextHandle, &ch)) | ||
321 | { | ||
322 | /* If error occurred when getting a char, exit the task and waiting the new data arriving. */ | ||
323 | break; | ||
324 | } | ||
325 | |||
326 | /* Special key */ | ||
327 | if (ch == KEY_ESC) | ||
328 | { | ||
329 | shellContextHandle->stat = kSHELL_Special; | ||
330 | continue; | ||
331 | } | ||
332 | else if (shellContextHandle->stat == kSHELL_Special) | ||
333 | { | ||
334 | /* Function key */ | ||
335 | if ((char)ch == '[') | ||
336 | { | ||
337 | shellContextHandle->stat = kSHELL_Function; | ||
338 | continue; | ||
339 | } | ||
340 | shellContextHandle->stat = kSHELL_Normal; | ||
341 | } | ||
342 | else if (shellContextHandle->stat == kSHELL_Function) | ||
343 | { | ||
344 | shellContextHandle->stat = kSHELL_Normal; | ||
345 | |||
346 | switch ((char)ch) | ||
347 | { | ||
348 | /* History operation here */ | ||
349 | case 'A': /* Up key */ | ||
350 | SHELL_GetHistoryCommand(shellContextHandle, (uint8_t)shellContextHandle->hist_current); | ||
351 | if (shellContextHandle->hist_current < (shellContextHandle->hist_count - 1U)) | ||
352 | { | ||
353 | shellContextHandle->hist_current++; | ||
354 | } | ||
355 | break; | ||
356 | case 'B': /* Down key */ | ||
357 | SHELL_GetHistoryCommand(shellContextHandle, (uint8_t)shellContextHandle->hist_current); | ||
358 | if (shellContextHandle->hist_current > 0U) | ||
359 | { | ||
360 | shellContextHandle->hist_current--; | ||
361 | } | ||
362 | break; | ||
363 | case 'D': /* Left key */ | ||
364 | if ((bool)shellContextHandle->c_pos) | ||
365 | { | ||
366 | SHELL_WriteWithCopy(shellContextHandle, "\b", 1); | ||
367 | shellContextHandle->c_pos--; | ||
368 | } | ||
369 | break; | ||
370 | case 'C': /* Right key */ | ||
371 | if (shellContextHandle->c_pos < shellContextHandle->l_pos) | ||
372 | { | ||
373 | (void)SHELL_Write(shellContextHandle, | ||
374 | &shellContextHandle->line[shellContextHandle->c_pos], 1); | ||
375 | shellContextHandle->c_pos++; | ||
376 | } | ||
377 | break; | ||
378 | default: | ||
379 | /* MISRA C-2012 Rule 16.4 */ | ||
380 | break; | ||
381 | } | ||
382 | continue; | ||
383 | } | ||
384 | /* Handle tab key */ | ||
385 | else if ((char)ch == '\t') | ||
386 | { | ||
387 | #if SHELL_AUTO_COMPLETE | ||
388 | /* Move the cursor to the beginning of line */ | ||
389 | uint32_t i; | ||
390 | for (i = 0; i < (uint32_t)shellContextHandle->c_pos; i++) | ||
391 | { | ||
392 | SHELL_WriteWithCopy(shellContextHandle, "\b", 1); | ||
393 | } | ||
394 | /* Do auto complete */ | ||
395 | SHELL_AutoComplete(shellContextHandle); | ||
396 | /* Move position to end */ | ||
397 | shellContextHandle->l_pos = (uint8_t)strlen(shellContextHandle->line); | ||
398 | shellContextHandle->c_pos = shellContextHandle->l_pos; | ||
399 | #endif | ||
400 | continue; | ||
401 | } | ||
402 | /* Handle backspace key */ | ||
403 | else if ((ch == KET_DEL) || ((char)ch == '\b')) | ||
404 | { | ||
405 | /* There must be at last one char */ | ||
406 | if (shellContextHandle->c_pos == 0U) | ||
407 | { | ||
408 | continue; | ||
409 | } | ||
410 | |||
411 | shellContextHandle->l_pos--; | ||
412 | shellContextHandle->c_pos--; | ||
413 | |||
414 | if (shellContextHandle->l_pos > shellContextHandle->c_pos) | ||
415 | { | ||
416 | (void)memmove(&shellContextHandle->line[shellContextHandle->c_pos], | ||
417 | &shellContextHandle->line[shellContextHandle->c_pos + 1U], | ||
418 | (uint32_t)shellContextHandle->l_pos - (uint32_t)shellContextHandle->c_pos); | ||
419 | shellContextHandle->line[shellContextHandle->l_pos] = '\0'; | ||
420 | SHELL_WriteWithCopy(shellContextHandle, "\b", 1); | ||
421 | (void)SHELL_Write(shellContextHandle, &shellContextHandle->line[shellContextHandle->c_pos], | ||
422 | strlen(&shellContextHandle->line[shellContextHandle->c_pos])); | ||
423 | SHELL_WriteWithCopy(shellContextHandle, " \b", 3); | ||
424 | |||
425 | /* Reset position */ | ||
426 | uint32_t i; | ||
427 | for (i = (uint32_t)shellContextHandle->c_pos; i <= (uint32_t)shellContextHandle->l_pos; i++) | ||
428 | { | ||
429 | SHELL_WriteWithCopy(shellContextHandle, "\b", 1); | ||
430 | } | ||
431 | } | ||
432 | else /* Normal backspace operation */ | ||
433 | { | ||
434 | SHELL_WriteWithCopy(shellContextHandle, "\b \b", 3); | ||
435 | shellContextHandle->line[shellContextHandle->l_pos] = '\0'; | ||
436 | } | ||
437 | continue; | ||
438 | } | ||
439 | else | ||
440 | { | ||
441 | /* MISRA C-2012 Rule 15.7 */ | ||
442 | } | ||
443 | |||
444 | /* Input too long */ | ||
445 | if (shellContextHandle->l_pos >= (SHELL_BUFFER_SIZE - 1U)) | ||
446 | { | ||
447 | shellContextHandle->l_pos = 0U; | ||
448 | } | ||
449 | |||
450 | /* Handle end of line, break */ | ||
451 | if (((char)ch == '\r') || ((char)ch == '\n')) | ||
452 | { | ||
453 | static char endoflinechar = '\0'; | ||
454 | |||
455 | if (((uint8_t)endoflinechar != 0U) && ((uint8_t)endoflinechar != ch)) | ||
456 | { | ||
457 | continue; | ||
458 | } | ||
459 | else | ||
460 | { | ||
461 | endoflinechar = (char)ch; | ||
462 | /* Print new line. */ | ||
463 | SHELL_WriteWithCopy(shellContextHandle, "\r\n", 2U); /* MISRA C-2012 Rule 7.4 */ | ||
464 | /* If command line is not NULL, will start process it. */ | ||
465 | if (0U != strlen(shellContextHandle->line)) | ||
466 | { | ||
467 | SHELL_ProcessCommand(shellContextHandle, shellContextHandle->line); | ||
468 | } | ||
469 | /* Print prompt. */ | ||
470 | (void)SHELL_Write(shellContextHandle, shellContextHandle->prompt, | ||
471 | strlen(shellContextHandle->prompt)); | ||
472 | /* Reset all params */ | ||
473 | shellContextHandle->c_pos = shellContextHandle->l_pos = 0; | ||
474 | shellContextHandle->hist_current = 0; | ||
475 | (void)memset(shellContextHandle->line, 0, sizeof(shellContextHandle->line)); | ||
476 | continue; | ||
477 | } | ||
478 | } | ||
479 | |||
480 | /* Normal character */ | ||
481 | if (shellContextHandle->c_pos < shellContextHandle->l_pos) | ||
482 | { | ||
483 | (void)memmove(&shellContextHandle->line[shellContextHandle->c_pos + 1U], | ||
484 | &shellContextHandle->line[shellContextHandle->c_pos], | ||
485 | (uint32_t)shellContextHandle->l_pos - (uint32_t)shellContextHandle->c_pos); | ||
486 | shellContextHandle->line[shellContextHandle->c_pos] = (char)ch; | ||
487 | (void)SHELL_Write(shellContextHandle, &shellContextHandle->line[shellContextHandle->c_pos], | ||
488 | strlen(&shellContextHandle->line[shellContextHandle->c_pos])); | ||
489 | /* Move the cursor to new position */ | ||
490 | uint32_t i; | ||
491 | for (i = (uint32_t)shellContextHandle->c_pos; i < (uint32_t)shellContextHandle->l_pos; i++) | ||
492 | { | ||
493 | SHELL_WriteWithCopy(shellContextHandle, "\b", 1); | ||
494 | } | ||
495 | } | ||
496 | else | ||
497 | { | ||
498 | shellContextHandle->line[shellContextHandle->l_pos] = (char)ch; | ||
499 | (void)SHELL_Write(shellContextHandle, &shellContextHandle->line[shellContextHandle->l_pos], 1); | ||
500 | } | ||
501 | |||
502 | ch = 0; | ||
503 | shellContextHandle->l_pos++; | ||
504 | shellContextHandle->c_pos++; | ||
505 | } while (0U == shellContextHandle->exit); | ||
506 | } | ||
507 | #if (defined(SHELL_NON_BLOCKING_MODE) && (SHELL_NON_BLOCKING_MODE > 0U)) | ||
508 | |||
509 | #if defined(OSA_USED) | ||
510 | |||
511 | #if (defined(SHELL_USE_COMMON_TASK) && (SHELL_USE_COMMON_TASK > 0U)) | ||
512 | #else | ||
513 | } | ||
514 | } while (1U == gUseRtos_c); /* USE_RTOS = 0 for BareMetal and 1 for OS */ | ||
515 | #endif | ||
516 | |||
517 | #endif | ||
518 | |||
519 | #endif | ||
520 | } | ||
521 | } | ||
522 | |||
523 | static shell_status_t SHELL_HelpCommand(shell_handle_t shellHandle, int32_t argc, char **argv) | ||
524 | { | ||
525 | shell_context_handle_t *shellContextHandle = (shell_context_handle_t *)shellHandle; | ||
526 | shell_command_t *shellCommandContextHandle; | ||
527 | list_element_handle_t p = LIST_GetHead(&shellContextHandle->commandContextListHead); | ||
528 | |||
529 | while (p != NULL) | ||
530 | { | ||
531 | shellCommandContextHandle = SHEEL_COMMAND_POINTER(p); | ||
532 | if ((shellCommandContextHandle->pcHelpString != NULL) && (bool)strlen(shellCommandContextHandle->pcHelpString)) | ||
533 | { | ||
534 | (void)SHELL_Write(shellContextHandle, shellCommandContextHandle->pcHelpString, | ||
535 | strlen(shellCommandContextHandle->pcHelpString)); | ||
536 | } | ||
537 | |||
538 | p = LIST_GetNext(p); | ||
539 | } | ||
540 | return kStatus_SHELL_Success; | ||
541 | } | ||
542 | |||
543 | static shell_status_t SHELL_ExitCommand(shell_handle_t shellHandle, int32_t argc, char **argv) | ||
544 | { | ||
545 | shell_context_handle_t *shellContextHandle = (shell_context_handle_t *)shellHandle; | ||
546 | /* Skip warning */ | ||
547 | SHELL_WriteWithCopy(shellContextHandle, "\r\nSHELL exited\r\n", strlen("\r\nSHELL exited\r\n")); | ||
548 | shellContextHandle->exit = (uint8_t) true; | ||
549 | return kStatus_SHELL_Success; | ||
550 | } | ||
551 | |||
552 | static void SHELL_ProcessCommand(shell_context_handle_t *shellContextHandle, const char *cmd) | ||
553 | { | ||
554 | shell_command_t *tmpCommand = NULL; | ||
555 | const char *tmpCommandString; | ||
556 | int32_t argc; | ||
557 | char *argv[SHELL_BUFFER_SIZE] = {0}; | ||
558 | list_element_handle_t p; | ||
559 | uint8_t flag = 1; | ||
560 | uint8_t tmpCommandLen; | ||
561 | uint8_t tmpLen; | ||
562 | uint8_t i = 0; | ||
563 | |||
564 | tmpLen = (uint8_t)strlen(cmd); | ||
565 | argc = SHELL_ParseLine(cmd, tmpLen, argv); | ||
566 | |||
567 | if ((argc > 0)) | ||
568 | { | ||
569 | p = LIST_GetHead(&shellContextHandle->commandContextListHead); | ||
570 | while (p != NULL) | ||
571 | { | ||
572 | tmpCommand = SHEEL_COMMAND_POINTER(p); | ||
573 | tmpCommandString = tmpCommand->pcCommand; | ||
574 | tmpCommandLen = (uint8_t)strlen(tmpCommandString); | ||
575 | /* Compare with space or end of string */ | ||
576 | if ((cmd[tmpCommandLen] == ' ') || (cmd[tmpCommandLen] == (char)0x00)) | ||
577 | { | ||
578 | if (SHELL_StringCompare(tmpCommandString, argv[0], (int32_t)tmpCommandLen) == 0) | ||
579 | { | ||
580 | /* support commands with optional number of parameters */ | ||
581 | if (tmpCommand->cExpectedNumberOfParameters == (uint8_t)SHELL_IGNORE_PARAMETER_COUNT) | ||
582 | { | ||
583 | flag = 0; | ||
584 | } | ||
585 | else if ((tmpCommand->cExpectedNumberOfParameters == 0U) && (argc == 1)) | ||
586 | { | ||
587 | flag = 0; | ||
588 | } | ||
589 | else if (tmpCommand->cExpectedNumberOfParameters > 0U) | ||
590 | { | ||
591 | if ((argc - 1) == (int32_t)tmpCommand->cExpectedNumberOfParameters) | ||
592 | { | ||
593 | flag = 0; | ||
594 | } | ||
595 | } | ||
596 | else | ||
597 | { | ||
598 | flag = 1; | ||
599 | } | ||
600 | break; | ||
601 | } | ||
602 | } | ||
603 | p = LIST_GetNext(p); | ||
604 | } | ||
605 | if (NULL == p) | ||
606 | { | ||
607 | tmpCommand = NULL; | ||
608 | } | ||
609 | } | ||
610 | |||
611 | if ((tmpCommand != NULL) && (flag == 1U)) | ||
612 | { | ||
613 | SHELL_WriteWithCopy( | ||
614 | shellContextHandle, | ||
615 | "\r\nIncorrect command parameter(s). Enter \"help\" to view a list of available commands.\r\n\r\n", | ||
616 | strlen( | ||
617 | "\r\nIncorrect command parameter(s). Enter \"help\" to view a list of available commands.\r\n\r\n")); | ||
618 | } | ||
619 | else if (tmpCommand != NULL) | ||
620 | { | ||
621 | tmpLen = (uint8_t)strlen(cmd); | ||
622 | /* Compare with last command. Push back to history buffer if different */ | ||
623 | if (tmpLen != (uint8_t)SHELL_StringCompare(cmd, shellContextHandle->hist_buf[0], (int32_t)strlen(cmd))) | ||
624 | { | ||
625 | for (i = SHELL_HISTORY_COUNT - 1U; i > 0U; i--) | ||
626 | { | ||
627 | (void)memset(shellContextHandle->hist_buf[i], (int)'\0', SHELL_BUFFER_SIZE); | ||
628 | tmpLen = (uint8_t)strlen(shellContextHandle->hist_buf[i - 1U]); | ||
629 | (void)memcpy(shellContextHandle->hist_buf[i], shellContextHandle->hist_buf[i - 1U], tmpLen); | ||
630 | } | ||
631 | (void)memset(shellContextHandle->hist_buf[0], (int)'\0', SHELL_BUFFER_SIZE); | ||
632 | tmpLen = (uint8_t)strlen(cmd); | ||
633 | (void)memcpy(shellContextHandle->hist_buf[0], cmd, tmpLen); | ||
634 | if (shellContextHandle->hist_count < SHELL_HISTORY_COUNT) | ||
635 | { | ||
636 | shellContextHandle->hist_count++; | ||
637 | } | ||
638 | } | ||
639 | (void)tmpCommand->pFuncCallBack(shellContextHandle, argc, argv); | ||
640 | } | ||
641 | else | ||
642 | { | ||
643 | SHELL_WriteWithCopy( | ||
644 | shellContextHandle, | ||
645 | "\r\nCommand not recognized. Enter 'help' to view a list of available commands.\r\n\r\n", | ||
646 | strlen("\r\nCommand not recognized. Enter 'help' to view a list of available commands.\r\n\r\n")); | ||
647 | } | ||
648 | } | ||
649 | |||
650 | static void SHELL_GetHistoryCommand(shell_context_handle_t *shellContextHandle, uint8_t hist_pos) | ||
651 | { | ||
652 | uint32_t i; | ||
653 | uint32_t tmp; | ||
654 | |||
655 | if (shellContextHandle->hist_buf[0][0] == '\0') | ||
656 | { | ||
657 | shellContextHandle->hist_current = 0; | ||
658 | return; | ||
659 | } | ||
660 | |||
661 | #if 0 /*hist_pos is passed from hist_current. And hist_current is only changed in case 'A'/'B',as hist_count is 3 \ | ||
662 | most, it can't be more than 3 */ | ||
663 | if (hist_pos >= SHELL_HISTORY_COUNT) | ||
664 | { | ||
665 | hist_pos = SHELL_HISTORY_COUNT - 1U; | ||
666 | } | ||
667 | #endif | ||
668 | |||
669 | tmp = strlen(shellContextHandle->line); | ||
670 | /* Clear current if have */ | ||
671 | if (tmp > 0U) | ||
672 | { | ||
673 | (void)memset(shellContextHandle->line, (int)'\0', tmp); | ||
674 | for (i = 0U; i < tmp; i++) | ||
675 | { | ||
676 | SHELL_WriteWithCopy(shellContextHandle, "\b \b", 3); | ||
677 | } | ||
678 | } | ||
679 | |||
680 | shellContextHandle->l_pos = (uint8_t)strlen(shellContextHandle->hist_buf[hist_pos]); | ||
681 | shellContextHandle->c_pos = shellContextHandle->l_pos; | ||
682 | (void)memcpy(shellContextHandle->line, shellContextHandle->hist_buf[hist_pos], shellContextHandle->l_pos); | ||
683 | (void)SHELL_Write(shellContextHandle, shellContextHandle->hist_buf[hist_pos], | ||
684 | strlen(shellContextHandle->hist_buf[hist_pos])); | ||
685 | } | ||
686 | |||
687 | static void SHELL_AutoComplete(shell_context_handle_t *shellContextHandle) | ||
688 | { | ||
689 | int32_t minLen; | ||
690 | list_element_handle_t p; | ||
691 | shell_command_t *tmpCommand = NULL; | ||
692 | const char *namePtr; | ||
693 | const char *cmdName; | ||
694 | |||
695 | minLen = (int32_t)SHELL_BUFFER_SIZE; | ||
696 | namePtr = NULL; | ||
697 | |||
698 | /* Empty tab, list all commands */ | ||
699 | if (shellContextHandle->line[0] == '\0') | ||
700 | { | ||
701 | (void)SHELL_HelpCommand(shellContextHandle, 0, NULL); | ||
702 | return; | ||
703 | } | ||
704 | |||
705 | SHELL_WriteWithCopy(shellContextHandle, "\r\n", 2); | ||
706 | |||
707 | /* Do auto complete */ | ||
708 | p = LIST_GetHead(&shellContextHandle->commandContextListHead); | ||
709 | while (p != NULL) | ||
710 | { | ||
711 | tmpCommand = SHEEL_COMMAND_POINTER(p); | ||
712 | cmdName = tmpCommand->pcCommand; | ||
713 | if (SHELL_StringCompare(shellContextHandle->line, cmdName, (int32_t)strlen(shellContextHandle->line)) == 0) | ||
714 | { | ||
715 | /* Show possible matches */ | ||
716 | (void)SHELL_Printf(shellContextHandle, "%s ", cmdName); | ||
717 | if (minLen > ((int32_t)strlen(cmdName))) | ||
718 | { | ||
719 | namePtr = cmdName; | ||
720 | minLen = (int32_t)strlen(namePtr); | ||
721 | } | ||
722 | } | ||
723 | p = LIST_GetNext(p); | ||
724 | } | ||
725 | /* Auto complete string */ | ||
726 | if (namePtr != NULL) | ||
727 | { | ||
728 | (void)memcpy(shellContextHandle->line, namePtr, (uint32_t)minLen); | ||
729 | } | ||
730 | SHELL_PrintPrompt(shellContextHandle); | ||
731 | (void)SHELL_Write(shellContextHandle, shellContextHandle->line, strlen(shellContextHandle->line)); | ||
732 | return; | ||
733 | } | ||
734 | |||
735 | static int32_t SHELL_StringCompare(const char *str1, const char *str2, int32_t count) | ||
736 | { | ||
737 | while ((bool)(count--)) | ||
738 | { | ||
739 | if (*str1++ != *str2++) | ||
740 | { | ||
741 | return (int32_t)(*(str1 - 1) - *(str2 - 1)); | ||
742 | } | ||
743 | } | ||
744 | return 0; | ||
745 | } | ||
746 | |||
747 | static int32_t SHELL_ParseLine(const char *cmd, uint32_t len, char *argv[]) | ||
748 | { | ||
749 | uint32_t argc; | ||
750 | char *p; | ||
751 | uint32_t position; | ||
752 | |||
753 | /* Init params */ | ||
754 | (void)memset(s_paramBuffer, (int)'\0', len + 1U); | ||
755 | (void)memcpy(s_paramBuffer, cmd, len); | ||
756 | |||
757 | p = s_paramBuffer; | ||
758 | position = 0; | ||
759 | argc = 0; | ||
760 | |||
761 | while (position < len) | ||
762 | { | ||
763 | /* Skip all blanks */ | ||
764 | while ((position < len) && ((char)(*p) == ' ')) | ||
765 | { | ||
766 | *p = '\0'; | ||
767 | p++; | ||
768 | position++; | ||
769 | } | ||
770 | |||
771 | if (position >= len) | ||
772 | { | ||
773 | break; | ||
774 | } | ||
775 | |||
776 | /* Process begin of a string */ | ||
777 | if (*p == '"') | ||
778 | { | ||
779 | p++; | ||
780 | position++; | ||
781 | argv[argc] = p; | ||
782 | argc++; | ||
783 | /* Skip this string */ | ||
784 | while ((*p != '"') && (position < len)) | ||
785 | { | ||
786 | p++; | ||
787 | position++; | ||
788 | } | ||
789 | /* Skip '"' */ | ||
790 | *p = '\0'; | ||
791 | p++; | ||
792 | position++; | ||
793 | } | ||
794 | else /* Normal char */ | ||
795 | { | ||
796 | argv[argc] = p; | ||
797 | argc++; | ||
798 | while (((char)*p != ' ') && (position < len)) | ||
799 | { | ||
800 | p++; | ||
801 | position++; | ||
802 | } | ||
803 | } | ||
804 | } | ||
805 | return (int32_t)argc; | ||
806 | } | ||
807 | |||
808 | static shell_status_t SHELL_GetChar(shell_context_handle_t *shellContextHandle, uint8_t *ch) | ||
809 | { | ||
810 | shell_status_t status; | ||
811 | |||
812 | #if (!defined(SDK_DEBUGCONSOLE_UART) && (defined(SDK_DEBUGCONSOLE) && (SDK_DEBUGCONSOLE != 1))) | ||
813 | if (NULL == shellContextHandle->serialHandle) | ||
814 | { | ||
815 | int ret; | ||
816 | ret = getchar(); | ||
817 | if (ret > 0) | ||
818 | { | ||
819 | *ch = (uint8_t)ret; | ||
820 | status = kStatus_SHELL_Success; | ||
821 | } | ||
822 | else | ||
823 | { | ||
824 | status = kStatus_SHELL_Error; | ||
825 | } | ||
826 | } | ||
827 | else | ||
828 | #endif | ||
829 | { | ||
830 | #if (defined(SHELL_NON_BLOCKING_MODE) && (SHELL_NON_BLOCKING_MODE > 0U)) | ||
831 | uint32_t length = 0; | ||
832 | |||
833 | (void)SerialManager_TryRead(shellContextHandle->serialReadHandle, ch, 1, &length); | ||
834 | |||
835 | if (length > 0U) | ||
836 | { | ||
837 | status = kStatus_SHELL_Success; | ||
838 | } | ||
839 | else | ||
840 | { | ||
841 | status = kStatus_SHELL_Error; | ||
842 | } | ||
843 | #else | ||
844 | status = (shell_status_t)SerialManager_ReadBlocking(shellContextHandle->serialReadHandle, ch, 1); | ||
845 | #endif | ||
846 | } | ||
847 | |||
848 | return status; | ||
849 | } | ||
850 | |||
851 | shell_status_t SHELL_Init(shell_handle_t shellHandle, serial_handle_t serialHandle, char *prompt) | ||
852 | { | ||
853 | shell_context_handle_t *shellContextHandle; | ||
854 | serial_manager_status_t status = kStatus_SerialManager_Error; | ||
855 | (void)status; | ||
856 | |||
857 | assert(shellHandle); | ||
858 | #if !(!defined(SDK_DEBUGCONSOLE_UART) && (defined(SDK_DEBUGCONSOLE) && (SDK_DEBUGCONSOLE != 1))) | ||
859 | assert(serialHandle); | ||
860 | #endif | ||
861 | assert(prompt); | ||
862 | assert(SHELL_HANDLE_SIZE >= sizeof(shell_context_handle_t)); | ||
863 | |||
864 | shellContextHandle = (shell_context_handle_t *)shellHandle; | ||
865 | |||
866 | /* memory set for shellHandle */ | ||
867 | (void)memset(shellHandle, 0, SHELL_HANDLE_SIZE); | ||
868 | |||
869 | #if (!defined(SDK_DEBUGCONSOLE_UART) && (defined(SDK_DEBUGCONSOLE) && (SDK_DEBUGCONSOLE != 1))) | ||
870 | if (NULL == serialHandle) | ||
871 | { | ||
872 | } | ||
873 | else | ||
874 | #endif | ||
875 | { | ||
876 | #if (defined(SHELL_NON_BLOCKING_MODE) && (SHELL_NON_BLOCKING_MODE > 0U)) | ||
877 | |||
878 | #if defined(OSA_USED) | ||
879 | |||
880 | #if (defined(SHELL_USE_COMMON_TASK) && (SHELL_USE_COMMON_TASK > 0U)) | ||
881 | (void)COMMON_TASK_init(); | ||
882 | #else | ||
883 | if (KOSA_StatusSuccess != OSA_EventCreate((osa_event_handle_t)shellContextHandle->event, 1U)) | ||
884 | { | ||
885 | return kStatus_SHELL_Error; | ||
886 | } | ||
887 | |||
888 | if (KOSA_StatusSuccess != | ||
889 | OSA_TaskCreate((osa_task_handle_t)shellContextHandle->taskId, OSA_TASK(SHELL_Task), shellContextHandle)) | ||
890 | { | ||
891 | return kStatus_SHELL_Error; | ||
892 | } | ||
893 | #endif | ||
894 | |||
895 | #endif | ||
896 | |||
897 | #endif | ||
898 | } | ||
899 | |||
900 | shellContextHandle->prompt = prompt; | ||
901 | shellContextHandle->serialHandle = serialHandle; | ||
902 | |||
903 | #if (!defined(SDK_DEBUGCONSOLE_UART) && (defined(SDK_DEBUGCONSOLE) && (SDK_DEBUGCONSOLE != 1))) | ||
904 | if (NULL == serialHandle) | ||
905 | { | ||
906 | } | ||
907 | else | ||
908 | #endif | ||
909 | { | ||
910 | shellContextHandle->serialWriteHandle = (serial_write_handle_t)&shellContextHandle->serialWriteHandleBuffer[0]; | ||
911 | status = SerialManager_OpenWriteHandle(shellContextHandle->serialHandle, shellContextHandle->serialWriteHandle); | ||
912 | assert(kStatus_SerialManager_Success == status); | ||
913 | |||
914 | shellContextHandle->serialReadHandle = (serial_read_handle_t)&shellContextHandle->serialReadHandleBuffer[0]; | ||
915 | status = SerialManager_OpenReadHandle(shellContextHandle->serialHandle, shellContextHandle->serialReadHandle); | ||
916 | assert(kStatus_SerialManager_Success == status); | ||
917 | |||
918 | #if (defined(SHELL_NON_BLOCKING_MODE) && (SHELL_NON_BLOCKING_MODE > 0U)) | ||
919 | status = SerialManager_InstallRxCallback(shellContextHandle->serialReadHandle, SHELL_SerialManagerRxCallback, | ||
920 | shellContextHandle); | ||
921 | assert(kStatus_SerialManager_Success == status); | ||
922 | #endif | ||
923 | (void)status; | ||
924 | } | ||
925 | |||
926 | (void)SHELL_RegisterCommand(shellContextHandle, SHELL_COMMAND(help)); | ||
927 | (void)SHELL_RegisterCommand(shellContextHandle, SHELL_COMMAND(exit)); | ||
928 | |||
929 | SHELL_WriteWithCopy(shellContextHandle, "\r\nSHELL build: ", strlen("\r\nSHELL build: ")); | ||
930 | SHELL_WriteWithCopy(shellContextHandle, __DATE__, strlen(__DATE__)); | ||
931 | SHELL_WriteWithCopy(shellContextHandle, "\r\nCopyright 2020 NXP\r\n", strlen("\r\nCopyright 2020 NXP\r\n")); | ||
932 | SHELL_PrintPrompt(shellContextHandle); | ||
933 | |||
934 | return kStatus_SHELL_Success; | ||
935 | } | ||
936 | |||
937 | shell_status_t SHELL_RegisterCommand(shell_handle_t shellHandle, shell_command_t *shellCommand) | ||
938 | { | ||
939 | shell_context_handle_t *shellContextHandle = (shell_context_handle_t *)shellHandle; | ||
940 | assert(shellHandle); | ||
941 | assert(shellCommand); | ||
942 | |||
943 | /* memory set for shellHandle */ | ||
944 | (void)memset(&shellCommand->link, 0, sizeof(shellCommand->link)); | ||
945 | |||
946 | (void)LIST_AddTail(&shellContextHandle->commandContextListHead, &shellCommand->link); | ||
947 | |||
948 | return kStatus_SHELL_Success; | ||
949 | } | ||
950 | |||
951 | shell_status_t SHELL_UnregisterCommand(shell_command_t *shellCommand) | ||
952 | { | ||
953 | assert(shellCommand); | ||
954 | |||
955 | (void)LIST_RemoveElement(&shellCommand->link); | ||
956 | |||
957 | /* memory set for shellHandle */ | ||
958 | (void)memset(&shellCommand->link, 0, sizeof(shellCommand->link)); | ||
959 | |||
960 | return kStatus_SHELL_Success; | ||
961 | } | ||
962 | |||
963 | shell_status_t SHELL_Write(shell_handle_t shellHandle, char *buffer, uint32_t length) | ||
964 | { | ||
965 | shell_context_handle_t *shellContextHandle; | ||
966 | uint32_t primask; | ||
967 | shell_status_t status; | ||
968 | |||
969 | assert(shellHandle); | ||
970 | assert(buffer); | ||
971 | |||
972 | if (!(bool)length) | ||
973 | { | ||
974 | return kStatus_SHELL_Success; | ||
975 | } | ||
976 | |||
977 | shellContextHandle = (shell_context_handle_t *)shellHandle; | ||
978 | |||
979 | primask = DisableGlobalIRQ(); | ||
980 | if ((bool)shellContextHandle->printBusy) | ||
981 | { | ||
982 | EnableGlobalIRQ(primask); | ||
983 | return kStatus_SHELL_Error; | ||
984 | } | ||
985 | shellContextHandle->printBusy = 1U; | ||
986 | EnableGlobalIRQ(primask); | ||
987 | #if (!defined(SDK_DEBUGCONSOLE_UART) && (defined(SDK_DEBUGCONSOLE) && (SDK_DEBUGCONSOLE != 1))) | ||
988 | if (NULL == shellContextHandle->serialHandle) | ||
989 | { | ||
990 | status = kStatus_SHELL_Success; | ||
991 | for (uint32_t index = 0; index < length; index++) | ||
992 | { | ||
993 | (void)putchar(buffer[index]); | ||
994 | } | ||
995 | } | ||
996 | else | ||
997 | #endif | ||
998 | { | ||
999 | status = (shell_status_t)SerialManager_WriteBlocking(shellContextHandle->serialWriteHandle, (uint8_t *)buffer, | ||
1000 | length); | ||
1001 | } | ||
1002 | |||
1003 | shellContextHandle->printBusy = 0U; | ||
1004 | |||
1005 | return status; | ||
1006 | } | ||
1007 | |||
1008 | /* For MISRA to fix const */ | ||
1009 | static void SHELL_WriteWithCopy(shell_handle_t shellHandle, const char *buffer, uint32_t length) | ||
1010 | { | ||
1011 | char s_shellWriteCopyBuffer[128]; | ||
1012 | |||
1013 | assert(length <= 128UL); | ||
1014 | |||
1015 | (void)memcpy(s_shellWriteCopyBuffer, buffer, length); | ||
1016 | (void)SHELL_Write(shellHandle, s_shellWriteCopyBuffer, length); | ||
1017 | } | ||
1018 | |||
1019 | int SHELL_Printf(shell_handle_t shellHandle, const char *formatString, ...) | ||
1020 | { | ||
1021 | shell_context_handle_t *shellContextHandle; | ||
1022 | uint32_t length; | ||
1023 | uint32_t primask; | ||
1024 | va_list ap; | ||
1025 | |||
1026 | assert(shellHandle); | ||
1027 | assert(formatString); | ||
1028 | |||
1029 | shellContextHandle = (shell_context_handle_t *)shellHandle; | ||
1030 | |||
1031 | primask = DisableGlobalIRQ(); | ||
1032 | if ((bool)shellContextHandle->printBusy) | ||
1033 | { | ||
1034 | EnableGlobalIRQ(primask); | ||
1035 | return -1; | ||
1036 | } | ||
1037 | shellContextHandle->printBusy = 1U; | ||
1038 | EnableGlobalIRQ(primask); | ||
1039 | |||
1040 | va_start(ap, formatString); | ||
1041 | |||
1042 | shellContextHandle->printLength = 0U; | ||
1043 | length = (uint32_t)SHELL_Sprintf(shellHandle, formatString, ap); | ||
1044 | #if (!defined(SDK_DEBUGCONSOLE_UART) && (defined(SDK_DEBUGCONSOLE) && (SDK_DEBUGCONSOLE != 1))) | ||
1045 | if (NULL == shellContextHandle->serialHandle) | ||
1046 | { | ||
1047 | for (uint32_t index = 0; index < length; index++) | ||
1048 | { | ||
1049 | (void)putchar(shellContextHandle->printBuffer[index]); | ||
1050 | } | ||
1051 | } | ||
1052 | else | ||
1053 | #endif | ||
1054 | { | ||
1055 | (void)SerialManager_WriteBlocking(shellContextHandle->serialWriteHandle, | ||
1056 | (uint8_t *)shellContextHandle->printBuffer, length); | ||
1057 | } | ||
1058 | va_end(ap); | ||
1059 | |||
1060 | shellContextHandle->printBusy = 0U; | ||
1061 | return (int32_t)shellContextHandle->printLength; | ||
1062 | } | ||
1063 | |||
1064 | void SHELL_ChangePrompt(shell_handle_t shellHandle, char *prompt) | ||
1065 | { | ||
1066 | shell_context_handle_t *shellContextHandle; | ||
1067 | assert(shellHandle); | ||
1068 | assert(prompt); | ||
1069 | |||
1070 | shellContextHandle = (shell_context_handle_t *)shellHandle; | ||
1071 | |||
1072 | shellContextHandle->prompt = prompt; | ||
1073 | SHELL_PrintPrompt(shellContextHandle); | ||
1074 | } | ||
1075 | |||
1076 | void SHELL_PrintPrompt(shell_handle_t shellHandle) | ||
1077 | { | ||
1078 | shell_context_handle_t *shellContextHandle; | ||
1079 | assert(shellHandle); | ||
1080 | |||
1081 | shellContextHandle = (shell_context_handle_t *)shellHandle; | ||
1082 | |||
1083 | SHELL_WriteWithCopy(shellContextHandle, "\r\n", 2U); /* MISRA C-2012 Rule 7.4 */ | ||
1084 | (void)SHELL_Write(shellContextHandle, shellContextHandle->prompt, strlen(shellContextHandle->prompt)); | ||
1085 | } | ||
diff --git a/lib/chibios-contrib/ext/mcux-sdk/devices/MK27FA15/utilities/fsl_shell.h b/lib/chibios-contrib/ext/mcux-sdk/devices/MK27FA15/utilities/fsl_shell.h new file mode 100644 index 000000000..28eace717 --- /dev/null +++ b/lib/chibios-contrib/ext/mcux-sdk/devices/MK27FA15/utilities/fsl_shell.h | |||
@@ -0,0 +1,292 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2015, Freescale Semiconductor, Inc. | ||
3 | * Copyright 2016-2020 NXP | ||
4 | * All rights reserved. | ||
5 | * | ||
6 | * SPDX-License-Identifier: BSD-3-Clause | ||
7 | */ | ||
8 | |||
9 | #ifndef __FSL_SHELL_H__ | ||
10 | #define __FSL_SHELL_H__ | ||
11 | |||
12 | /*! | ||
13 | * @addtogroup SHELL | ||
14 | * @{ | ||
15 | */ | ||
16 | |||
17 | #include "fsl_common.h" | ||
18 | #include "fsl_component_serial_manager.h" | ||
19 | #include "fsl_component_generic_list.h" | ||
20 | |||
21 | /******************************************************************************* | ||
22 | * Definitions | ||
23 | ******************************************************************************/ | ||
24 | |||
25 | /*! @brief Whether use non-blocking mode. */ | ||
26 | #ifndef SHELL_NON_BLOCKING_MODE | ||
27 | #define SHELL_NON_BLOCKING_MODE SERIAL_MANAGER_NON_BLOCKING_MODE | ||
28 | #endif | ||
29 | |||
30 | /*! @brief Macro to set on/off auto-complete feature. */ | ||
31 | #define SHELL_AUTO_COMPLETE (1U) | ||
32 | |||
33 | /*! @brief Macro to set console buffer size. */ | ||
34 | #ifndef SHELL_BUFFER_SIZE | ||
35 | #define SHELL_BUFFER_SIZE (64U) | ||
36 | #endif | ||
37 | |||
38 | /*! @brief Macro to set maximum arguments in command. */ | ||
39 | #define SHELL_MAX_ARGS (8U) | ||
40 | |||
41 | /*! @brief Macro to set maximum count of history commands. */ | ||
42 | #ifndef SHELL_HISTORY_COUNT | ||
43 | #define SHELL_HISTORY_COUNT (3U) | ||
44 | #endif | ||
45 | |||
46 | /*! @brief Macro to bypass arguments check */ | ||
47 | #define SHELL_IGNORE_PARAMETER_COUNT (0xFF) | ||
48 | |||
49 | /*! @brief The handle size of the shell module. It is the sum of the SHELL_HISTORY_COUNT * SHELL_BUFFER_SIZE + | ||
50 | * SHELL_BUFFER_SIZE + SERIAL_MANAGER_READ_HANDLE_SIZE + SERIAL_MANAGER_WRITE_HANDLE_SIZE*/ | ||
51 | #define SHELL_HANDLE_SIZE \ | ||
52 | (160U + SHELL_HISTORY_COUNT * SHELL_BUFFER_SIZE + SHELL_BUFFER_SIZE + SERIAL_MANAGER_READ_HANDLE_SIZE + \ | ||
53 | SERIAL_MANAGER_WRITE_HANDLE_SIZE) | ||
54 | |||
55 | /*! @brief Macro to determine whether use common task. */ | ||
56 | #ifndef SHELL_USE_COMMON_TASK | ||
57 | #define SHELL_USE_COMMON_TASK (0U) | ||
58 | #endif | ||
59 | |||
60 | /*! @brief Macro to set shell task priority. */ | ||
61 | #ifndef SHELL_TASK_PRIORITY | ||
62 | #define SHELL_TASK_PRIORITY (2U) | ||
63 | #endif | ||
64 | |||
65 | /*! @brief Macro to set shell task stack size. */ | ||
66 | #ifndef SHELL_TASK_STACK_SIZE | ||
67 | #define SHELL_TASK_STACK_SIZE (1000U) | ||
68 | #endif | ||
69 | |||
70 | /*! @brief Shell status */ | ||
71 | typedef enum _shell_status | ||
72 | { | ||
73 | kStatus_SHELL_Success = kStatus_Success, /*!< Success */ | ||
74 | kStatus_SHELL_Error = MAKE_STATUS(kStatusGroup_SHELL, 1), /*!< Failed */ | ||
75 | kStatus_SHELL_OpenWriteHandleFailed = MAKE_STATUS(kStatusGroup_SHELL, 2), /*!< Open write handle failed */ | ||
76 | kStatus_SHELL_OpenReadHandleFailed = MAKE_STATUS(kStatusGroup_SHELL, 3), /*!< Open read handle failed */ | ||
77 | } shell_status_t; | ||
78 | |||
79 | /*! @brief The handle of the shell module */ | ||
80 | typedef void *shell_handle_t; | ||
81 | |||
82 | /*! @brief User command function prototype. */ | ||
83 | typedef shell_status_t (*cmd_function_t)(shell_handle_t shellHandle, int32_t argc, char **argv); | ||
84 | |||
85 | /*! @brief User command data configuration structure. */ | ||
86 | typedef struct _shell_command | ||
87 | { | ||
88 | const char *pcCommand; /*!< The command that is executed. For example "help". It must be all lower case. */ | ||
89 | char *pcHelpString; /*!< String that describes how to use the command. It should start with the command itself, | ||
90 | and end with "\r\n". For example "help: Returns a list of all the commands\r\n". */ | ||
91 | const cmd_function_t | ||
92 | pFuncCallBack; /*!< A pointer to the callback function that returns the output generated by the command. */ | ||
93 | uint8_t cExpectedNumberOfParameters; /*!< Commands expect a fixed number of parameters, which may be zero. */ | ||
94 | list_element_t link; /*!< link of the element */ | ||
95 | } shell_command_t; | ||
96 | |||
97 | /*! | ||
98 | * @brief Defines the shell handle | ||
99 | * | ||
100 | * This macro is used to define a 4 byte aligned shell handle. | ||
101 | * Then use "(shell_handle_t)name" to get the shell handle. | ||
102 | * | ||
103 | * The macro should be global and could be optional. You could also define shell handle by yourself. | ||
104 | * | ||
105 | * This is an example, | ||
106 | * @code | ||
107 | * SHELL_HANDLE_DEFINE(shellHandle); | ||
108 | * @endcode | ||
109 | * | ||
110 | * @param name The name string of the shell handle. | ||
111 | */ | ||
112 | #define SHELL_HANDLE_DEFINE(name) uint32_t name[((SHELL_HANDLE_SIZE + sizeof(uint32_t) - 1U) / sizeof(uint32_t))] | ||
113 | |||
114 | #if defined(__ICCARM__) | ||
115 | /* disable misra 19.13 */ | ||
116 | _Pragma("diag_suppress=Pm120") | ||
117 | #endif | ||
118 | /*! | ||
119 | * @brief Defines the shell command structure | ||
120 | * | ||
121 | * This macro is used to define the shell command structure #shell_command_t. | ||
122 | * And then uses the macro SHELL_COMMAND to get the command structure pointer. | ||
123 | * The macro should not be used in any function. | ||
124 | * | ||
125 | * This is a example, | ||
126 | * @code | ||
127 | * SHELL_COMMAND_DEFINE(exit, "\r\n\"exit\": Exit program\r\n", SHELL_ExitCommand, 0); | ||
128 | * SHELL_RegisterCommand(s_shellHandle, SHELL_COMMAND(exit)); | ||
129 | * @endcode | ||
130 | * | ||
131 | * @param command The command string of the command. The double quotes do not need. Such as exit for "exit", | ||
132 | * help for "Help", read for "read". | ||
133 | * @param descriptor The description of the command is used for showing the command usage when "help" is typing. | ||
134 | * @param callback The callback of the command is used to handle the command line when the input command is matched. | ||
135 | * @param paramCount The max parameter count of the current command. | ||
136 | */ | ||
137 | #define SHELL_COMMAND_DEFINE(command, descriptor, callback, paramCount) \ | ||
138 | \ | ||
139 | shell_command_t g_shellCommand##command = { \ | ||
140 | (#command), (descriptor), (callback), (paramCount), {0}, \ | ||
141 | } | ||
142 | |||
143 | /*! | ||
144 | * @brief Gets the shell command pointer | ||
145 | * | ||
146 | * This macro is used to get the shell command pointer. The macro should not be used before the macro | ||
147 | * SHELL_COMMAND_DEFINE is used. | ||
148 | * | ||
149 | * @param command The command string of the command. The double quotes do not need. Such as exit for "exit", | ||
150 | * help for "Help", read for "read". | ||
151 | */ | ||
152 | #define SHELL_COMMAND(command) &g_shellCommand##command | ||
153 | |||
154 | #if defined(__ICCARM__) | ||
155 | _Pragma("diag_default=Pm120") | ||
156 | #endif | ||
157 | |||
158 | /******************************************************************************* | ||
159 | * API | ||
160 | ******************************************************************************/ | ||
161 | |||
162 | #if defined(__cplusplus) | ||
163 | extern "C" | ||
164 | { | ||
165 | #endif /* _cplusplus */ | ||
166 | |||
167 | /*! | ||
168 | * @name Shell functional operation | ||
169 | * @{ | ||
170 | */ | ||
171 | |||
172 | /*! | ||
173 | * @brief Initializes the shell module | ||
174 | * | ||
175 | * This function must be called before calling all other Shell functions. | ||
176 | * Call operation the Shell commands with user-defined settings. | ||
177 | * The example below shows how to set up the Shell and | ||
178 | * how to call the SHELL_Init function by passing in these parameters. | ||
179 | * This is an example. | ||
180 | * @code | ||
181 | * static SHELL_HANDLE_DEFINE(s_shellHandle); | ||
182 | * SHELL_Init((shell_handle_t)s_shellHandle, (serial_handle_t)s_serialHandle, "Test@SHELL>"); | ||
183 | * @endcode | ||
184 | * @param shellHandle Pointer to point to a memory space of size #SHELL_HANDLE_SIZE allocated by the caller. | ||
185 | * The handle should be 4 byte aligned, because unaligned access doesn't be supported on some devices. | ||
186 | * You can define the handle in the following two ways: | ||
187 | * #SHELL_HANDLE_DEFINE(shellHandle); | ||
188 | * or | ||
189 | * uint32_t shellHandle[((SHELL_HANDLE_SIZE + sizeof(uint32_t) - 1U) / sizeof(uint32_t))]; | ||
190 | * @param serialHandle The serial manager module handle pointer. | ||
191 | * @param prompt The string prompt pointer of Shell. Only the global variable can be passed. | ||
192 | * @retval kStatus_SHELL_Success The shell initialization succeed. | ||
193 | * @retval kStatus_SHELL_Error An error occurred when the shell is initialized. | ||
194 | * @retval kStatus_SHELL_OpenWriteHandleFailed Open the write handle failed. | ||
195 | * @retval kStatus_SHELL_OpenReadHandleFailed Open the read handle failed. | ||
196 | */ | ||
197 | shell_status_t SHELL_Init(shell_handle_t shellHandle, serial_handle_t serialHandle, char *prompt); | ||
198 | |||
199 | /*! | ||
200 | * @brief Registers the shell command | ||
201 | * | ||
202 | * This function is used to register the shell command by using the command configuration shell_command_config_t. | ||
203 | * This is a example, | ||
204 | * @code | ||
205 | * SHELL_COMMAND_DEFINE(exit, "\r\n\"exit\": Exit program\r\n", SHELL_ExitCommand, 0); | ||
206 | * SHELL_RegisterCommand(s_shellHandle, SHELL_COMMAND(exit)); | ||
207 | * @endcode | ||
208 | * @param shellHandle The shell module handle pointer. | ||
209 | * @param shellCommand The command element. | ||
210 | * @retval kStatus_SHELL_Success Successfully register the command. | ||
211 | * @retval kStatus_SHELL_Error An error occurred. | ||
212 | */ | ||
213 | shell_status_t SHELL_RegisterCommand(shell_handle_t shellHandle, shell_command_t * shellCommand); | ||
214 | |||
215 | /*! | ||
216 | * @brief Unregisters the shell command | ||
217 | * | ||
218 | * This function is used to unregister the shell command. | ||
219 | * | ||
220 | * @param shellCommand The command element. | ||
221 | * @retval kStatus_SHELL_Success Successfully unregister the command. | ||
222 | */ | ||
223 | shell_status_t SHELL_UnregisterCommand(shell_command_t * shellCommand); | ||
224 | |||
225 | /*! | ||
226 | * @brief Sends data to the shell output stream. | ||
227 | * | ||
228 | * This function is used to send data to the shell output stream. | ||
229 | * | ||
230 | * @param shellHandle The shell module handle pointer. | ||
231 | * @param buffer Start address of the data to write. | ||
232 | * @param length Length of the data to write. | ||
233 | * @retval kStatus_SHELL_Success Successfully send data. | ||
234 | * @retval kStatus_SHELL_Error An error occurred. | ||
235 | */ | ||
236 | shell_status_t SHELL_Write(shell_handle_t shellHandle, char *buffer, uint32_t length); | ||
237 | |||
238 | /*! | ||
239 | * @brief Writes formatted output to the shell output stream. | ||
240 | * | ||
241 | * Call this function to write a formatted output to the shell output stream. | ||
242 | * | ||
243 | * @param shellHandle The shell module handle pointer. | ||
244 | * | ||
245 | * @param formatString Format string. | ||
246 | * @return Returns the number of characters printed or a negative value if an error occurs. | ||
247 | */ | ||
248 | int SHELL_Printf(shell_handle_t shellHandle, const char *formatString, ...); | ||
249 | |||
250 | /*! | ||
251 | * @brief Change shell prompt. | ||
252 | * | ||
253 | * Call this function to change shell prompt. | ||
254 | * | ||
255 | * @param shellHandle The shell module handle pointer. | ||
256 | * | ||
257 | * @param prompt The string which will be used for command prompt | ||
258 | * @return NULL. | ||
259 | */ | ||
260 | void SHELL_ChangePrompt(shell_handle_t shellHandle, char *prompt); | ||
261 | |||
262 | /*! | ||
263 | * @brief Print shell prompt. | ||
264 | * | ||
265 | * Call this function to print shell prompt. | ||
266 | * | ||
267 | * @param shellHandle The shell module handle pointer. | ||
268 | * | ||
269 | * @return NULL. | ||
270 | */ | ||
271 | void SHELL_PrintPrompt(shell_handle_t shellHandle); | ||
272 | |||
273 | /*! | ||
274 | * @brief The task function for Shell. | ||
275 | * The task function for Shell; The function should be polled by upper layer. | ||
276 | * This function does not return until Shell command exit was called. | ||
277 | * | ||
278 | * @param shellHandle The shell module handle pointer. | ||
279 | */ | ||
280 | #if !(defined(SHELL_NON_BLOCKING_MODE) && (SHELL_NON_BLOCKING_MODE > 0U)) | ||
281 | void SHELL_Task(shell_handle_t shellHandle); | ||
282 | #endif | ||
283 | |||
284 | /* @} */ | ||
285 | |||
286 | #if defined(__cplusplus) | ||
287 | } | ||
288 | #endif | ||
289 | |||
290 | /*! @}*/ | ||
291 | |||
292 | #endif /* __FSL_SHELL_H__ */ | ||