1 /*
2  * Copyright (c) 2015, Freescale Semiconductor, Inc.
3  * Copyright 2016-2024 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 Whether print copyright. */
71 #ifndef SHELL_PRINT_COPYRIGHT
72 #define SHELL_PRINT_COPYRIGHT (1U)
73 #endif
74 
75 /*! @brief Shell status */
76 typedef enum _shell_status
77 {
78     kStatus_SHELL_Success               = kStatus_Success,                    /*!< Success */
79     kStatus_SHELL_Error                 = MAKE_STATUS(kStatusGroup_SHELL, 1), /*!< Failed */
80     kStatus_SHELL_OpenWriteHandleFailed = MAKE_STATUS(kStatusGroup_SHELL, 2), /*!< Open write handle failed */
81     kStatus_SHELL_OpenReadHandleFailed  = MAKE_STATUS(kStatusGroup_SHELL, 3), /*!< Open read handle failed */
82     kStatus_SHELL_RetUsage              = MAKE_STATUS(kStatusGroup_SHELL, 4), /*!< RetUsage for print cmd usage */
83 } shell_status_t;
84 
85 /*! @brief The handle of the shell module */
86 typedef void *shell_handle_t;
87 
88 /*! @brief User command function prototype. */
89 typedef shell_status_t (*cmd_function_t)(shell_handle_t shellHandle, int32_t argc, char **argv);
90 
91 /*! @brief User command data configuration structure. */
92 typedef struct _shell_command
93 {
94     const char *pcCommand; /*!< The command that is executed.  For example "help".  It must be all lower case. */
95     char *pcHelpString;    /*!< String that describes how to use the command.  It should start with the command itself,
96                                     and end with "\r\n".  For example "help: Returns a list of all the commands\r\n". */
97     const cmd_function_t
98         pFuncCallBack; /*!< A pointer to the callback function that returns the output generated by the command. */
99     uint8_t cExpectedNumberOfParameters; /*!< Commands expect a fixed number of parameters, which may be zero. */
100     list_element_t link;                 /*!< link of the element */
101 } shell_command_t;
102 
103 /*!
104  * @brief Defines the shell handle
105  *
106  * This macro is used to define a 4 byte aligned shell handle.
107  * Then use "(shell_handle_t)name" to get the shell handle.
108  *
109  * The macro should be global and could be optional. You could also define shell handle by yourself.
110  *
111  * This is an example,
112  * @code
113  * SHELL_HANDLE_DEFINE(shellHandle);
114  * @endcode
115  *
116  * @param name The name string of the shell handle.
117  */
118 #define SHELL_HANDLE_DEFINE(name) uint32_t name[((SHELL_HANDLE_SIZE + sizeof(uint32_t) - 1U) / sizeof(uint32_t))]
119 
120 #if defined(__ICCARM__)
121 /* disable misra 19.13 */
122 _Pragma("diag_suppress=Pm120")
123 #endif
124 /*!
125  * @brief Defines the shell command structure
126  *
127  * This macro is used to define the shell command structure #shell_command_t.
128  * And then uses the macro SHELL_COMMAND to get the command structure pointer.
129  * The macro should not be used in any function.
130  *
131  * This is a example,
132  * @code
133  * SHELL_COMMAND_DEFINE(exit, "\r\n\"exit\": Exit program\r\n", SHELL_ExitCommand, 0);
134  * SHELL_RegisterCommand(s_shellHandle, SHELL_COMMAND(exit));
135  * @endcode
136  *
137  * @param command The command string of the command. The double quotes do not need. Such as exit for "exit",
138  *                help for "Help", read for "read".
139  * @param descriptor The description of the command is used for showing the command usage when "help" is typing.
140  * @param callback The callback of the command is used to handle the command line when the input command is matched.
141  * @param paramCount The max parameter count of the current command.
142  */
143 #define SHELL_COMMAND_DEFINE(command, descriptor, callback, paramCount) \
144                                                                         \
145     shell_command_t g_shellCommand##command = {                         \
146         (#command), (descriptor), (callback), (paramCount), {0},        \
147     }
148 
149 /*!
150  * @brief Gets the shell command pointer
151  *
152  * This macro is used to get the shell command pointer. The macro should not be used before the macro
153  * SHELL_COMMAND_DEFINE is used.
154  *
155  * @param command The command string of the command. The double quotes do not need. Such as exit for "exit",
156  *                help for "Help", read for "read".
157  */
158 #define SHELL_COMMAND(command) &g_shellCommand##command
159 
160 #if defined(__ICCARM__)
161     _Pragma("diag_default=Pm120")
162 #endif
163 
164 /*******************************************************************************
165  * API
166  ******************************************************************************/
167 
168 #if defined(__cplusplus)
169         extern "C"
170 {
171 #endif /* _cplusplus */
172 
173     /*!
174      * @name Shell functional operation
175      * @{
176      */
177 
178     /*!
179      * @brief Initializes the shell module
180      *
181      * This function must be called before calling all other Shell functions.
182      * Call operation the Shell commands with user-defined settings.
183      * The example below shows how to set up the Shell and
184      * how to call the SHELL_Init function by passing in these parameters.
185      * This is an example.
186      * @code
187      *   static SHELL_HANDLE_DEFINE(s_shellHandle);
188      *   SHELL_Init((shell_handle_t)s_shellHandle, (serial_handle_t)s_serialHandle, "Test@SHELL>");
189      * @endcode
190      * @param shellHandle Pointer to point to a memory space of size #SHELL_HANDLE_SIZE allocated by the caller.
191      * The handle should be 4 byte aligned, because unaligned access doesn't be supported on some devices.
192      * You can define the handle in the following two ways:
193      * #SHELL_HANDLE_DEFINE(shellHandle);
194      * or
195      * uint32_t shellHandle[((SHELL_HANDLE_SIZE + sizeof(uint32_t) - 1U) / sizeof(uint32_t))];
196      * @param serialHandle The serial manager module handle pointer.
197      * @param prompt  The string prompt pointer of Shell. Only the global variable can be passed.
198      * @retval kStatus_SHELL_Success The shell initialization succeed.
199      * @retval kStatus_SHELL_Error An error occurred when the shell is initialized.
200      * @retval kStatus_SHELL_OpenWriteHandleFailed Open the write handle failed.
201      * @retval kStatus_SHELL_OpenReadHandleFailed Open the read handle failed.
202      */
203     shell_status_t SHELL_Init(shell_handle_t shellHandle, serial_handle_t serialHandle, char *prompt);
204 
205     /*!
206      * @brief Registers the shell command
207      *
208      * This function is used to register the shell command by using the command configuration shell_command_config_t.
209      * This is a example,
210      * @code
211      * SHELL_COMMAND_DEFINE(exit, "\r\n\"exit\": Exit program\r\n", SHELL_ExitCommand, 0);
212      * SHELL_RegisterCommand(s_shellHandle, SHELL_COMMAND(exit));
213      * @endcode
214      * @param shellHandle The shell module handle pointer.
215      * @param shellCommand  The command element.
216      * @retval kStatus_SHELL_Success Successfully register the command.
217      * @retval kStatus_SHELL_Error An error occurred.
218      */
219     shell_status_t SHELL_RegisterCommand(shell_handle_t shellHandle, shell_command_t * shellCommand);
220 
221     /*!
222      * @brief Unregisters the shell command
223      *
224      * This function is used to unregister the shell command.
225      *
226      * @param shellCommand The command element.
227      * @retval kStatus_SHELL_Success Successfully unregister the command.
228      */
229     shell_status_t SHELL_UnregisterCommand(shell_command_t * shellCommand);
230 
231     /*!
232      * @brief Sends data to the shell output stream.
233      *
234      * This function is used to send data to the shell output stream.
235      *
236      * @param shellHandle The shell module handle pointer.
237      * @param buffer Start address of the data to write.
238      * @param length Length of the data to write.
239      * @retval kStatus_SHELL_Success Successfully send data.
240      * @retval kStatus_SHELL_Error An error occurred.
241      */
242     shell_status_t SHELL_Write(shell_handle_t shellHandle, const char *buffer, uint32_t length);
243 
244     /*!
245      * @brief Writes formatted output to the shell output stream.
246      *
247      * Call this function to write a formatted output to the shell output stream.
248      *
249      * @param shellHandle The shell module handle pointer.
250      *
251      * @param   formatString Format string.
252      * @return  Returns the number of characters printed or a negative value if an error occurs.
253      */
254     int SHELL_Printf(shell_handle_t shellHandle, const char *formatString, ...);
255     /*!
256      * @brief Sends data to the shell output stream with OS synchronization.
257      *
258      * This function is used to send data to the shell output stream with OS synchronization, note the function could
259      * not be called in ISR.
260      *
261      * @param shellHandle The shell module handle pointer.
262      * @param buffer Start address of the data to write.
263      * @param length Length of the data to write.
264      * @retval kStatus_SHELL_Success Successfully send data.
265      * @retval kStatus_SHELL_Error An error occurred.
266      */
267     shell_status_t SHELL_WriteSynchronization(shell_handle_t shellHandle, const char *buffer, uint32_t length);
268 
269     /*!
270      * @brief Writes formatted output to the shell output stream with OS synchronization.
271      *
272      * Call this function to write a formatted output to the shell output stream with OS synchronization, note the
273      * function could not be called in ISR.
274      *
275      * @param shellHandle The shell module handle pointer.
276      *
277      * @param   formatString Format string.
278      * @return  Returns the number of characters printed or a negative value if an error occurs.
279      */
280     int SHELL_PrintfSynchronization(shell_handle_t shellHandle, const char *formatString, ...);
281     /*!
282      * @brief Change shell prompt.
283      *
284      * Call this function to change shell prompt.
285      *
286      * @param shellHandle The shell module handle pointer.
287      *
288      * @param prompt The string which will be used for command prompt
289      * @return  NULL.
290      */
291     void SHELL_ChangePrompt(shell_handle_t shellHandle, char *prompt);
292 
293     /*!
294      * @brief Print shell prompt.
295      *
296      * Call this function to print shell prompt.
297      *
298      * @param shellHandle The shell module handle pointer.
299      *
300      * @return  NULL.
301      */
302     void SHELL_PrintPrompt(shell_handle_t shellHandle);
303 
304 /*!
305  * @brief The task function for Shell.
306  * The task function for Shell; The function should be polled by upper layer.
307  * This function does not return until Shell command exit was called.
308  *
309  * @param shellHandle The shell module handle pointer.
310  */
311 #if !(defined(SHELL_NON_BLOCKING_MODE) && (SHELL_NON_BLOCKING_MODE > 0U))
312     void SHELL_Task(shell_handle_t shellHandle);
313 #endif
314 
315     /*!
316      * @brief Check if code is running in ISR.
317      *
318      * This function is used to check if code running in ISR.
319      *
320      * @retval TRUE if code runing in ISR.
321      */
SHELL_checkRunningInIsr(void)322     static inline bool SHELL_checkRunningInIsr(void)
323     {
324 #if (defined(__DSC__) && defined(__CW__))
325         return !(isIRQAllowed());
326 #elif defined(__GIC_PRIO_BITS)
327     return (0x13 == (__get_CPSR() & CPSR_M_Msk));
328 #elif defined(__get_IPSR)
329     return (0U != __get_IPSR());
330 #else
331     return false;
332 #endif
333     }
334 
335     /* @} */
336 
337 #if defined(__cplusplus)
338 }
339 #endif
340 
341 /*! @}*/
342 
343 #endif /* __FSL_SHELL_H__ */
344