diff --git a/docs/05 - Steps to work with FreeRTOS b/docs/05 - Steps to work with FreeRTOS new file mode 100644 index 0000000..b629c19 --- /dev/null +++ b/docs/05 - Steps to work with FreeRTOS @@ -0,0 +1,7 @@ +1) clone the repository +2) Inside /esh clone the freeRTOS kernel source code : https://github.com/FreeRTOS/FreeRTOS-Kernel +3) Disable the configAssert of port.c in freeRTOS kernel Code (For the given example of GCC/ARM3/port.c Line 370) +4) make +5) make run + +This will start two tasks concurrently one to run shell and other to periodically print a statement diff --git a/examples/emulation/freertos/FreeRTOSConfig.h b/examples/emulation/freertos/FreeRTOSConfig.h new file mode 100644 index 0000000..98a42a3 --- /dev/null +++ b/examples/emulation/freertos/FreeRTOSConfig.h @@ -0,0 +1,189 @@ +/* + * FreeRTOS V202212.01 + * Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of + * this software and associated documentation files (the "Software"), to deal in + * the Software without restriction, including without limitation the rights to + * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of + * the Software, and to permit persons to whom the Software is furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all + * copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS + * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR + * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER + * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * https://www.FreeRTOS.org + * https://github.com/FreeRTOS + * + */ + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +/*----------------------------------------------------------- + * Application specific definitions. + * + * These definitions should be adjusted for your particular hardware and + * application requirements. + * + * THESE PARAMETERS ARE DESCRIBED WITHIN THE 'CONFIGURATION' SECTION OF THE + * FreeRTOS API DOCUMENTATION AVAILABLE ON THE FreeRTOS.org WEB SITE. + * + * See http://www.freertos.org/a00110.html + *----------------------------------------------------------*/ + +#define configUSE_TRACE_FACILITY 0 +#define configGENERATE_RUN_TIME_STATS 0 + +#define configUSE_TICKLESS_IDLE 0 +#define configUSE_PREEMPTION 1 +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 1 +#define configCPU_CLOCK_HZ ( ( unsigned long ) 25000000 ) +#define configTICK_RATE_HZ ( ( TickType_t ) 1000 ) +#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 80 ) +#define configTOTAL_HEAP_SIZE ( ( size_t ) ( 60 * 1024 ) ) +#define configMAX_TASK_NAME_LEN ( 12 ) +#define configUSE_16_BIT_TICKS 0 +#define configIDLE_SHOULD_YIELD 0 +#define configUSE_MUTEXES 1 +#define configUSE_RECURSIVE_MUTEXES 1 +#define configCHECK_FOR_STACK_OVERFLOW 2 +#define configUSE_MALLOC_FAILED_HOOK 1 +#define configUSE_QUEUE_SETS 1 +#define configUSE_COUNTING_SEMAPHORES 1 + +#define configMAX_PRIORITIES ( 9UL ) +#define configQUEUE_REGISTRY_SIZE 10 +#define configSUPPORT_STATIC_ALLOCATION 1 + +/* Timer related defines. */ +#define configUSE_TIMERS 1 +#define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 4 ) +#define configTIMER_QUEUE_LENGTH 20 +#define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE * 2 ) + +#define configUSE_TASK_NOTIFICATIONS 1 +#define configTASK_NOTIFICATION_ARRAY_ENTRIES 3 + +/* Set the following definitions to 1 to include the API function, or zero +to exclude the API function. */ + +#define INCLUDE_vTaskPrioritySet 1 +#define INCLUDE_uxTaskPriorityGet 1 +#define INCLUDE_vTaskDelete 1 +#define INCLUDE_vTaskCleanUpResources 0 +#define INCLUDE_vTaskSuspend 1 +#define INCLUDE_vTaskDelayUntil 1 +#define INCLUDE_vTaskDelay 1 +#define INCLUDE_uxTaskGetStackHighWaterMark 1 +#define INCLUDE_xTaskGetSchedulerState 1 +#define INCLUDE_xTimerGetTimerDaemonTaskHandle 1 +#define INCLUDE_xTaskGetIdleTaskHandle 1 +#define INCLUDE_xSemaphoreGetMutexHolder 1 +#define INCLUDE_eTaskGetState 1 +#define INCLUDE_xTimerPendFunctionCall 1 +#define INCLUDE_xTaskAbortDelay 1 +#define INCLUDE_xTaskGetHandle 1 + +/* This demo makes use of one or more example stats formatting functions. These +format the raw data provided by the uxTaskGetSystemState() function in to human +readable ASCII form. See the notes in the implementation of vTaskList() within +FreeRTOS/Source/tasks.c for limitations. */ +#define configUSE_STATS_FORMATTING_FUNCTIONS 0 + +#define configKERNEL_INTERRUPT_PRIORITY ( 255 ) /* All eight bits as QEMU doesn't model the priority bits. */ +/* !!!! configMAX_SYSCALL_INTERRUPT_PRIORITY must not be set to zero !!!! +See http://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html. */ +#define configMAX_SYSCALL_INTERRUPT_PRIORITY ( 191 ) + +/* Use the Cortex-M3 optimised task selection rather than the generic C code +version. */ +#define configUSE_PORT_OPTIMISED_TASK_SELECTION 1 + +/* The Win32 target is capable of running all the tests tasks at the same + * time. */ +#define configRUN_ADDITIONAL_TESTS 1 + +/* The test that checks the trigger level on stream buffers requires an +allowable margin of error on slower processors (slower than the Win32 +machine on which the test is developed). */ +#define configSTREAM_BUFFER_TRIGGER_LEVEL_TEST_MARGIN 4 + +#ifndef __IASMARM__ /* Prevent C code being included in IAR asm files. */ + void vAssertCalled( const char *pcFileName, uint32_t ulLine ); + #define configASSERT( x ) if( ( x ) == 0 ) vAssertCalled( __FILE__, __LINE__ ); +#endif + +#define intqHIGHER_PRIORITY ( configMAX_PRIORITIES - 5 ) +#define bktPRIMARY_PRIORITY ( configMAX_PRIORITIES - 3 ) +#define bktSECONDARY_PRIORITY ( configMAX_PRIORITIES - 4 ) + +#endif /* FREERTOS_CONFIG_H */ + +// #define configUSE_MALLOC_FAILED_HOOK 0 +// #define configUSE_MUTEXES 1 +// #define configUSE_RECURSIVE_MUTEXES 1 +// #define configUSE_TIMERS 1 +// #define configTIMER_TASK_STACK_DEPTH ( configMINIMAL_STACK_SIZE * 2 ) + +// #define INCLUDE_vTaskPrioritySet 1 +// #define INCLUDE_uxTaskPriorityGet 1 +// #define INCLUDE_vTaskDelete 1 +// #define INCLUDE_vTaskCleanUpResources 0 +// #define INCLUDE_vTaskSuspend 1 +// #define INCLUDE_vTaskDelayUntil 1 +// #define INCLUDE_vTaskDelay 1 +// #define INCLUDE_uxTaskGetStackHighWaterMark 1 +// #define INCLUDE_uxTaskGetStackHighWaterMark2 1 +// #define INCLUDE_xTaskGetSchedulerState 1 +// #define INCLUDE_xTimerGetTimerDaemonTaskHandle 1 +// #define INCLUDE_xTaskGetIdleTaskHandle 1 +// #define INCLUDE_xTaskGetHandle 1 +// #define INCLUDE_eTaskGetState 1 +// #define INCLUDE_xSemaphoreGetMutexHolder 1 +// #define INCLUDE_xTimerPendFunctionCall 1 +// #define INCLUDE_xTaskAbortDelay 1 + +// #define projCOVERAGE_TEST 0 +// #define configKERNEL_INTERRUPT_PRIORITY 255 +// #define configMAX_SYSCALL_INTERRUPT_PRIORITY 191 /* equivalent to 0xa0, or priority 5. */ +// #define configMAC_INTERRUPT_PRIORITY 5 + + +// #define configASSERT_DEFINED 1 +// extern void vAssertCalled( void ); +// #define configASSERT( x ) if( ( x ) == 0 ) vAssertCalled() +// #define configQUEUE_REGISTRY_SIZE 20 + +// #define configUSE_PREEMPTION 1 +// #define configUSE_TIME_SLICING 0 +// #define configUSE_PORT_OPTIMISED_TASK_SELECTION 0 + +// #define configUSE_IDLE_HOOK 0 +// #define configUSE_TICK_HOOK 0 +// #define configUSE_DAEMON_TASK_STARTUP_HOOK 0 +// #define configCPU_CLOCK_HZ ( ( unsigned long ) 25000000 ) +// #define configTICK_RATE_HZ ( ( TickType_t ) 10000 ) +// #define configMINIMAL_STACK_SIZE ( ( unsigned short ) 2000 ) +// #define configTOTAL_HEAP_SIZE ( ( size_t ) ( 80 * 1024 ) ) +// #define configMAX_TASK_NAME_LEN ( 10 ) +// #define configUSE_TRACE_FACILITY 1 +// #define configUSE_16_BIT_TICKS 0 +// #define configIDLE_SHOULD_YIELD 1 + +// #define configMAX_PRIORITIES ( 10 ) +// #define configTIMER_QUEUE_LENGTH 20 +// #define configTIMER_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) +// #define configUSE_COUNTING_SEMAPHORES 1 +// #define configSUPPORT_DYNAMIC_ALLOCATION 1 +// #define configSUPPORT_STATIC_ALLOCATION 0 +// #define configNUM_TX_DESCRIPTORS 15 +// #define configSTREAM_BUFFER_TRIGGER_LEVEL_TEST_MARGIN 2 \ No newline at end of file diff --git a/examples/emulation/freertos/Makefile b/examples/emulation/freertos/Makefile new file mode 100644 index 0000000..d93f254 --- /dev/null +++ b/examples/emulation/freertos/Makefile @@ -0,0 +1,79 @@ +# +# Copyright 2021 Google LLC +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + +# NOTE: the toolchain can be installed using - +# sudo apt install -y gcc-arm-none-eabi + +TOOLCHAIN_PREFIX ?= arm-none-eabi- +OPTIMIZATION = g + +EXTERN_SRC = ../../../../FreeRTOS-Kernel +SRC_C += ../../../../FreeRTOS-Kernel/portable/GCC/ARM_CM3/port.c +SRC_C += ../../../../FreeRTOS-Kernel/portable/MemMang/heap_4.c +IGNORE_SRC_PATH += ../../../../FreeRTOS-Kernel/examples +IGNORE_SRC_PATH += ../../../../FreeRTOS-Kernel/portable +IGNORE_HEADER_PATH += ../../../../FreeRTOS-Kernel/portable +IGNORE_HEADER_PATH += ../../../../FreeRTOS-Kernel/examples +INCLUDES += -I../../../../FreeRTOS-Kernel/include +INCLUDES += -I../../../../FreeRTOS-Kernel/portable/GCC/ARM_CM3/ +TOOLCHAIN_VERSION := $(shell $(TOOLCHAIN_PREFIX)gcc -dumpversion) +LIB_GCC_PATH = /usr/lib/gcc/arm-none-eabi/$(TOOLCHAIN_VERSION)/thumb/v7-m/nofp/ + +DEFINES = -mcpu=cortex-m3 -mthumb +ASM_FLAGS = -march=armv7-m +LD_FLAGS = -lgcc -L$(LIB_GCC_PATH) + +STARTUP = cortex-m + +# MANDATORY: +# These 3 parameters are needed for every port +# Provide all values in hex +ROM_BASE_PHYSICAL = 0x00000000 +ROM_SIZE = 0x3FFFF + +RAM_BASE_PHYSICAL = 0x20000000 +RAM_SIZE = 0x7FFFFF + +# to reduce binary size, set to 1 +# SHELL_LITE = 0 + +# setting the stack start manually for m class processors +DEFINES += -DSTACK_START=0x0003FFFF +DEFINES += -DSHELL_NO_PRINTF_LL + +# MANDATORY: +# Provide relative path to shell/ from current directory +# Only Variable should be set above this line +SHELL_ROOT=../../../shell +-include $(SHELL_ROOT)/Makefile +# ^^ Do not move the above line. All user targets to be defined below this line! + +# ------------------------ User targets below this line ------------------------ +### run: Launches QEMU and loads the project binary on it +run: $(PROJECT).elf + @echo "Use Ctrl+A X to exit Qemu" + @qemu-system-arm -M mps2-an385 -cpu cortex-m3 -nographic \ + -kernel $(PROJECT).elf +### debug: Qemu with GDB server. To be executed before 'make gdb' +debug: + @echo Please use \"make gdb\" in another terminal to attach gdb. + @echo Use \"cltr+a,x\" to quit qemu debug + @qemu-system-arm -S -M mps2-an385 -cpu cortex-m3 -nographic -kernel \ + $(PROJECT).elf -gdb tcp::1234 + +### gdb: Launches GDB and connects to qemu. To be executed after 'make debug' +gdb: + @gdb-multiarch shell.elf -ex "target remote localhost:1234" diff --git a/examples/emulation/freertos/hello.c b/examples/emulation/freertos/hello.c new file mode 100644 index 0000000..5817feb --- /dev/null +++ b/examples/emulation/freertos/hello.c @@ -0,0 +1,41 @@ +/** + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +/* + * This is a mandatory include. + * This has the ADD_CMD() macro + */ +#include "shell.h" + +/* + * There can be one or many function with same prototype, exposed as + * a command on the shell. They can be in same or multiple files. + */ +int hello(int argc, char** argv) { + for (int i = 0; i < argc; i++) { + printf(argv[i]); + printf(" "); + } + + printf("\nPress ctrl + a, x to exit !\n"); + return 0; +} + +/* + * One or many such can exist per file. + * Description: ADD_CMD(command, help string, function to be exposed) + */ +ADD_CMD(hello, "Echoes the commandline\n\tusage: hello ", hello); diff --git a/examples/emulation/freertos/platform/platform.c b/examples/emulation/freertos/platform/platform.c new file mode 100644 index 0000000..25f9021 --- /dev/null +++ b/examples/emulation/freertos/platform/platform.c @@ -0,0 +1,239 @@ +/** + * Copyright 2022 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +#include +#include "FreeRTOS.h" +#include "task.h" +#include "timers.h" +#include "queue.h" +#include "shell.h" +#include + +#include "shell_config.h" +#include "string.h" +#include "shell.h" +#include "uart.h" + +/** + * @brief Inilialize the platform + * + */ +static void vTaskRunShell(void *pvParameters); +static void vTaskRunShell2(void *pvParameters); +extern void prompt(); +extern void shell1(); +// extern void vApplicationTickHook(void); +void vApplicationMallocFailedHook( void ) +{ + /* vApplicationMallocFailedHook() will only be called if + configUSE_MALLOC_FAILED_HOOK is set to 1 in FreeRTOSConfig.h. It is a hook + function that will get called if a call to pvPortMalloc() fails. + pvPortMalloc() is called internally by the kernel whenever a task, queue, + timer or semaphore is created using the dynamic allocation (as opposed to + static allocation) option. It is also called by various parts of the + demo application. If heap_1.c, heap_2.c or heap_4.c is being used, then the + size of the heap available to pvPortMalloc() is defined by + configTOTAL_HEAP_SIZE in FreeRTOSConfig.h, and the xPortGetFreeHeapSize() + API function can be used to query the size of free heap space that remains + (although it does not provide information on how the remaining heap might be + fragmented). See http://www.freertos.org/a00111.html for more + information. */ + printf( "\r\n\r\nMalloc failed\r\n" ); + portDISABLE_INTERRUPTS(); + for( ;; ); +} +/*-----------------------------------------------------------*/ + +void vApplicationIdleHook( void ) +{ + /* vApplicationIdleHook() will only be called if configUSE_IDLE_HOOK is set + to 1 in FreeRTOSConfig.h. It will be called on each iteration of the idle + task. It is essential that code added to this hook function never attempts + to block in any way (for example, call xQueueReceive() with a block time + specified, or call vTaskDelay()). If application tasks make use of the + vTaskDelete() API function to delete themselves then it is also important + that vApplicationIdleHook() is permitted to return to its calling function, + because it is the responsibility of the idle task to clean up memory + allocated by the kernel to any task that has since deleted itself. */ +} +/*-----------------------------------------------------------*/ + +void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName ) +{ + ( void ) pcTaskName; + ( void ) pxTask; + + /* Run time stack overflow checking is performed if + configCHECK_FOR_STACK_OVERFLOW is defined to 1 or 2. This hook + function is called if a stack overflow is detected. */ + printf( "\r\n\r\nStack overflow in %s\r\n", pcTaskName ); + portDISABLE_INTERRUPTS(); + for( ;; ); +} +/*-----------------------------------------------------------*/ + +void vApplicationTickHook( void ) +{ + /* This function will be called by each tick interrupt if + configUSE_TICK_HOOK is set to 1 in FreeRTOSConfig.h. User code can be + added here, but the tick hook is called from an interrupt context, so + code must not attempt to block, and only the interrupt safe FreeRTOS API + functions can be used (those that end in FromISR()). */ + + // #if ( mainCREATE_SIMPLE_BLINKY_DEMO_ONLY != 1 ) + // { + // extern void vFullDemoTickHookFunction( void ); + + // vFullDemoTickHookFunction(); + // } + // #endif /* mainCREATE_SIMPLE_BLINKY_DEMO_ONLY */ +} +/*-----------------------------------------------------------*/ + +void vApplicationDaemonTaskStartupHook( void ) +{ + /* This function will be called once only, when the daemon task starts to + execute (sometimes called the timer task). This is useful if the + application includes initialisation code that would benefit from executing + after the scheduler has been started. */ +} +/*-----------------------------------------------------------*/ + +void vAssertCalled( const char *pcFileName, uint32_t ulLine ) +{ +volatile uint32_t ulSetToNonZeroInDebuggerToContinue = 0; + + /* Called if an assertion passed to configASSERT() fails. See + http://www.freertos.org/a00110.html#configASSERT for more information. */ + + printf( "ASSERT! Line %d, file %s\r\n", ( int ) ulLine, pcFileName ); + + taskENTER_CRITICAL(); + { + /* You can step out of this function to debug the assertion by using + the debugger to set ulSetToNonZeroInDebuggerToContinue to a non-zero + value. */ + while( ulSetToNonZeroInDebuggerToContinue == 0 ) + { + __asm volatile( "NOP" ); + __asm volatile( "NOP" ); + } + } + taskEXIT_CRITICAL(); +} +/*-----------------------------------------------------------*/ + +/* configUSE_STATIC_ALLOCATION is set to 1, so the application must provide an +implementation of vApplicationGetIdleTaskMemory() to provide the memory that is +used by the Idle task. */ +void vApplicationGetIdleTaskMemory( StaticTask_t **ppxIdleTaskTCBBuffer, StackType_t **ppxIdleTaskStackBuffer, uint32_t *pulIdleTaskStackSize ) +{ +/* If the buffers to be provided to the Idle task are declared inside this +function then they must be declared static - otherwise they will be allocated on +the stack and so not exists after this function exits. */ +static StaticTask_t xIdleTaskTCB; +static StackType_t uxIdleTaskStack[ configMINIMAL_STACK_SIZE ]; + + /* Pass out a pointer to the StaticTask_t structure in which the Idle task's + state will be stored. */ + *ppxIdleTaskTCBBuffer = &xIdleTaskTCB; + + /* Pass out the array that will be used as the Idle task's stack. */ + *ppxIdleTaskStackBuffer = uxIdleTaskStack; + + /* Pass out the size of the array pointed to by *ppxIdleTaskStackBuffer. + Note that, as the array is necessarily of type StackType_t, + configMINIMAL_STACK_SIZE is specified in words, not bytes. */ + *pulIdleTaskStackSize = configMINIMAL_STACK_SIZE; +} +/*-----------------------------------------------------------*/ + +/* configUSE_STATIC_ALLOCATION and configUSE_TIMERS are both set to 1, so the +application must provide an implementation of vApplicationGetTimerTaskMemory() +to provide the memory that is used by the Timer service task. */ +void vApplicationGetTimerTaskMemory( StaticTask_t **ppxTimerTaskTCBBuffer, StackType_t **ppxTimerTaskStackBuffer, uint32_t *pulTimerTaskStackSize ) +{ +/* If the buffers to be provided to the Timer task are declared inside this +function then they must be declared static - otherwise they will be allocated on +the stack and so not exists after this function exits. */ +static StaticTask_t xTimerTaskTCB; +static StackType_t uxTimerTaskStack[ configTIMER_TASK_STACK_DEPTH ]; + + /* Pass out a pointer to the StaticTask_t structure in which the Timer + task's state will be stored. */ + *ppxTimerTaskTCBBuffer = &xTimerTaskTCB; + + /* Pass out the array that will be used as the Timer task's stack. */ + *ppxTimerTaskStackBuffer = uxTimerTaskStack; + + /* Pass out the size of the array pointed to by *ppxTimerTaskStackBuffer. + Note that, as the array is necessarily of type StackType_t, + configMINIMAL_STACK_SIZE is specified in words, not bytes. */ + *pulTimerTaskStackSize = configTIMER_TASK_STACK_DEPTH; +} +/*-----------------------------------------------------------*/ + +void main_blinky1(void) +{ + // platform_init(); + prompt(); + xTaskCreate(vTaskRunShell, "ShellTask", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL); + xTaskCreate(vTaskRunShell2, "ShellTask", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL); + vTaskStartScheduler(); +} + +static void vTaskRunShell(void *pvParameters) +{ + (void)pvParameters; + for( ;; ) + { + /* Simply toggle the LED every 500ms, blocking between each toggle. */ + shell1(); + // printf("task1\n"); + // vTaskDelay( xDelay ); + + } + + +} +void platform_init() { + + uart_init(); + set_read_char(ugetc); + set_write_char(uputc); +} +static void vTaskRunShell2(void *pvParameters) +{ + // (void)pvParameters; + + // printf("hello"); + const TickType_t xDelay = 7000 / portTICK_PERIOD_MS; + for( ;; ) + { + /* Simply toggle the LED every 500ms, blocking between each toggle. */ + // shell1(); + // vTaskDelay( xDelay ); + printf("task2\n"); + printf("#"); + vTaskDelay( xDelay ); + } + +} +// int bootFreeRTOS(){ +// xTaskCreate(vTaskRunShell2, "ShellTask2", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY + 1, NULL); +// vTaskStartScheduler(); +// return 0; +// } +// ADD_CMD(bootFreeRTOS,"ABCD",bootFreeRTOS); \ No newline at end of file diff --git a/examples/emulation/freertos/platform/uart/uart.c b/examples/emulation/freertos/platform/uart/uart.c new file mode 100644 index 0000000..048d28c --- /dev/null +++ b/examples/emulation/freertos/platform/uart/uart.c @@ -0,0 +1,46 @@ +/** + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +#include "uart.h" + +/** + * @brief Default UART implementation in case the user hasn't provided + * putc(), get(), uart_init() implementation. + * + */ +#define UART_DR *((unsigned int *)(UART_BASE + 0x00)) +#define UART_STATE *((unsigned int *)(UART_BASE + 0x04)) +#define UART_CTRL *((unsigned int *)(UART_BASE + 0x08)) +#define UART_INT *((unsigned int *)(UART_BASE + 0x04)) + +void uputc(char c) { + while (UART_STATE & 1) + ; + + UART_DR = c; +} + +int ugetc(void) { + if (UART_STATE & (1 << 1)) return UART_DR; + + return -1; +} + +void uart_init(void) { + UART_CTRL = 0x0; + UART_INT = 0xF; + UART_CTRL = 0x3; +} diff --git a/examples/emulation/freertos/platform/uart/uart.h b/examples/emulation/freertos/platform/uart/uart.h new file mode 100644 index 0000000..8a89129 --- /dev/null +++ b/examples/emulation/freertos/platform/uart/uart.h @@ -0,0 +1,42 @@ +/** + * Copyright 2022 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +#ifndef __UART_H__ +#define __UART_H__ + +#define UART_BASE 0x40004000 + +/** + * @brief Put a character on uart data buffer + * + * @param c byte to be sent out + */ +void uputc(char c); + +/** + * @brief Get a character from uart data buffer + * + * @return int byte read from the uart data register + */ +int ugetc(void); + +/** + * @brief Init the uart, set baud etc + * + */ +void uart_init(void); + +#endif diff --git a/examples/emulation/freertos/platform/vector_table.c b/examples/emulation/freertos/platform/vector_table.c new file mode 100644 index 0000000..4cb6c44 --- /dev/null +++ b/examples/emulation/freertos/platform/vector_table.c @@ -0,0 +1,101 @@ +/** + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ +#include +extern void vPortSVCHandler( void ); +extern void xPortPendSVHandler(void); +extern void xPortSysTickHandler(void); +#define ISR_HANDLER(x) ((uint32_t)&x) + +extern void reset_handler(void); + +void default_handler(void) { + while (1) + ; +} + +uint32_t vector_table[240] __attribute__((section(".init_vector"))) = { + (uint32_t)STACK_START, ISR_HANDLER(reset_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(vPortSVCHandler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), 0, 0, 0, 0, ISR_HANDLER(vPortSVCHandler), + ISR_HANDLER(default_handler), 0, ISR_HANDLER(xPortPendSVHandler), ISR_HANDLER(xPortSysTickHandler), + // 132 IRQs + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler), + ISR_HANDLER(default_handler), ISR_HANDLER(default_handler)}; diff --git a/shell/Makefile b/shell/Makefile index 68c4583..d24eb99 100644 --- a/shell/Makefile +++ b/shell/Makefile @@ -146,7 +146,7 @@ $(BUILD_PATH)/%.o:%.S $(DEP_HEADERS) @$(OBJCOPY) -O binary $< $@ $(PRINT_ONLY_ERRORS) @echo "Done!" $(PRINT_ONLY_ERRORS) -## default target +## default targetf .DEFAULT_GOAL := all ### all: Builds the project binary. Same as just executing make. diff --git a/shell/build-magic/find-headers.mk b/shell/build-magic/find-headers.mk index fe22506..8092db4 100644 --- a/shell/build-magic/find-headers.mk +++ b/shell/build-magic/find-headers.mk @@ -33,6 +33,6 @@ H_FILES = $(filter-out $(IGNORE_H), $(ALL_H_FILES)) HPP_FILES = $(filter-out $(IGNORE_HPP), $(ALL_HPP_FILES)) # final list of include paths! -INCLUDES = $(shell dirname $(H_FILES) $(HPP_FILES) \ +INCLUDES += $(shell dirname $(H_FILES) $(HPP_FILES) \ sort | uniq | \ while read line; do echo "-I"$$line; done;) diff --git a/shell/build-magic/find-source.mk b/shell/build-magic/find-source.mk index b06efa1..cf4508e 100644 --- a/shell/build-magic/find-source.mk +++ b/shell/build-magic/find-source.mk @@ -27,7 +27,7 @@ IGNORE_CPP = $(shell realpath $(shell find $(IGNORE_SRC_PATH) \ -type f -name "*.cpp" ) 2>/dev/null) endif -SRC_C = $(filter-out $(IGNORE_C), $(ALL_SRC_C)) +SRC_C += $(filter-out $(IGNORE_C), $(ALL_SRC_C)) SRC_CPP = $(filter-out $(IGNORE_CPP), $(ALL_SRC_CPP)) # discover the ASM source files in project directory diff --git a/shell/shell/shell.c b/shell/shell/shell.c index 2f1459c..92c5d18 100644 --- a/shell/shell/shell.c +++ b/shell/shell/shell.c @@ -1,482 +1,488 @@ -/** - * Copyright 2021 Google LLC - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - **/ - -#include "shell.h" - -#include - -#include "shell_config.h" -#include "string.h" - -int (*__read_char__)(void); -void (*__write_char__)(char c); - -extern unsigned long int __CMD_TABLE_START__; -extern unsigned long int __AUTO_TABLE_START__; - -static const cmd_t *volatile table = (cmd_t *)&__CMD_TABLE_START__; -static const cmd_t *volatile auto_load = (cmd_t *)&__AUTO_TABLE_START__; -static volatile int __cmd_exec_status; - -/* - * To reduce the shell size the history feature - * is made optional. Skip history feature if - * SHELL_NO_HISTORY is defined. - */ -#ifndef SHELL_NO_HISTORY -static volatile int total_num_commands = 0; -static volatile int curr_command_ptr = 0; -static char cmd_history[NUM_HISTORY_ENTRIES][LINE_BUFF_SIZE]; -#endif - -static volatile bool __echo = ECHO_INIT_VALUE; // Should be set in the Makefile - -void set_read_char(int (*func)(void)) { __read_char__ = func; } - -void set_write_char(void (*func)(char)) { __write_char__ = func; } - -__attribute__((weak)) void setup(void) { - // to be provided by the user -} - -__attribute__((weak)) void loop(void) { - // to be provided by the user -} - -// This method is a place holder to prepend prompt -__attribute__((weak)) void prepend_prompt() { - ; // nothing by default -} - -// Check if prompt is active, by default true. -// Platforms can decide a logic for this. -__attribute__((weak)) int active_prompt() { return TRUE; } - -static void delete(void) { - __write_char__(BACK_SPACE); - __write_char__(SPACE); - __write_char__(BACK_SPACE); -} - -static void clear_prompt(int char_count) { - while (char_count) { - delete (); - char_count--; - } -} - -/* - * To reduce the shell size the history feature - * is made optional. Skip history feature if - * SHELL_NO_HISTORY is defined. - */ -#ifndef SHELL_NO_HISTORY -static void handle_up_arrow(char *cmd_buff, int *char_count) { - if (curr_command_ptr < total_num_commands - NUM_HISTORY_ENTRIES || - curr_command_ptr == 0) { - printf("%s", cmd_buff); - return; - } - - memset(cmd_buff, 0, LINE_BUFF_SIZE); - - curr_command_ptr--; - int index = (curr_command_ptr % NUM_HISTORY_ENTRIES); - memcpy(cmd_buff, &cmd_history[index], LINE_BUFF_SIZE); - *char_count = strlen(cmd_buff); - - printf("%s", cmd_buff); -} - -static void handle_down_arrow(char *cmd_buff, int *char_count) { - memset(cmd_buff, 0, LINE_BUFF_SIZE); - *char_count = 0; - if (curr_command_ptr == total_num_commands) return; - - curr_command_ptr++; - int index = (curr_command_ptr % NUM_HISTORY_ENTRIES); - memcpy(cmd_buff, &cmd_history[index], LINE_BUFF_SIZE); - *char_count = strlen(cmd_buff); - - printf("%s", cmd_buff); -} - -static void add_command_to_history(const char *cmd_str) { - - //add only if command is not empty - if (cmd_str == NULL || strcmp(cmd_str, "") == 0) { - return; - } - int index = total_num_commands % NUM_HISTORY_ENTRIES; - memcpy(&cmd_history[index], cmd_str, LINE_BUFF_SIZE); - total_num_commands++; - curr_command_ptr = total_num_commands; -} - -static int show_history(int argc, char **argv) { - uint32_t end_index = total_num_commands-1; - uint32_t beg_index = 0; - if (total_num_commands > NUM_HISTORY_ENTRIES) { - beg_index = total_num_commands - NUM_HISTORY_ENTRIES; - } - for (uint32_t index = beg_index; index <= end_index; ++index) { - printf("%s\n", cmd_history[index % NUM_HISTORY_ENTRIES]); - } - - return 0; -} - -ADD_CMD(history, "Show command history", show_history); - -#endif // SHELL_NO_HISTORY - - -#ifndef SHELL_NO_TAB_COMPLETE - -static int prefix_match(char *sub, int len, const char *str) { - if (sub == NULL || str == NULL || len <= 0 || len > strlen(str)) { - return FALSE; - } - - for (int i = 0; i 0) execute(argc, argv); -} - -static void exec_auto_cmds(void) { - for (int i = 0; auto_load[i].command_name != NULL; i++) { - auto_load[i].command(0, NULL); - } -} - -static int build_info(int argc, char **argv) { - printf("Build: [" SHELL_VERSION ":" USER_REPO_VERSION "] - [" BUILD_USER - "@" BUILD_HOST "] - " __DATE__ " - " __TIME__ "\n"); - return 0; -} - - -void __attribute__((optimize("O0"), weak)) initial_setup(void) { - /** - * Copy the data section from ROM to RAM and - * zero init the bss section if we are using - * Two segment memory. - * - * In case everything is in the RAM, skip copying the .data section - * and zero the .bss section. This helps keep the user/custom - * linker script and makefiles free from special variables to be declared. - * Less burden on the user. - */ - extern char _etext, _data, _edata, _bss, _ebss; - char *src = &_etext, *dst = &_data; - - /** - * Copy over the data section from ROM to RAM. - * In case of RAM based target, we skip this since - * src and dst would point to same location in RAM - */ - if (dst != src) - while (dst < &_edata) *(dst++) = *(src++); - - /* Clear .bss*/ - for (dst = &_bss; dst < &_ebss; dst++) *dst = 0; - - /** - * platform_init() is expected to be defined by the user. - * Expectation is that the user would do any needed hardware initialization - * And register two functions to read a byte and write a byte using - * - set_read_char(); - * - set_write_char(); - * - * typical implementation may look like: - * void platform_init(void) { - * uart_init(); - * set_read_char(uart_getchar); - * set_write_char(uart_putchar); - * } - */ - platform_init(); -} - -/** - * @brief spwans the prompt - * - */ -void prompt() { - initial_setup(); - exec_auto_cmds(); - setup(); - - while (TRUE) { - shell(); - } -} - -int exec(char *cmd_str) { - int argc; - - // TODO: this takes too much stack space. Optimize! - char *argv[MAX_ARG_COUNT]; - - // parse the line_buff - argc = parse_line(argv, cmd_str, MAX_ARG_COUNT); - - // execute the parsed commands - if (argc > 0) execute(argc, argv); - - return __cmd_exec_status; -} - -cmd get_function_addr(char *cmd_str) { - for (int i = 0; table[i].command_name != NULL; i++) { - if (strcmp(cmd_str, table[i].command_name) == 0) { - return table[i].command; - } - } - return NULL; -} - -int help(int argc, char **argv) { - int i = 0; - /* Default to Verbose */ - bool verbose = true; - - if (argc > 1 && (strcmp(argv[1], "-l")==0)) { - verbose = false; - } else { - printf("use: help -l for list only.\n\n"); - } - - while (table[i].command_name != NULL) { - printf(table[i].command_name); - - if (verbose) { - printf("\n\t"); - printf(table[i].command_help); - } - - printf("\n"); - i++; - } - - return 0; -} - -int cmd_exec_status(int argc, char **argv) { - printf("%d\n", __cmd_exec_status); - return 0; -} - -// DO NOT REMOVE THESE -AUTO_CMD(version, "Prints details of the build", build_info); -ADD_CMD(help, "Prints all available commands", help); -ADD_CMD(status, "Returns exit status of last executed command", - cmd_exec_status); - -// Mandatory! -__attribute__((section(".cmd_end"))) static volatile cmd_t cmd_end_ = { - NULL, NULL, NULL}; +/** + * Copyright 2021 Google LLC + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + **/ + +#include "shell.h" + +#include + +#include "shell_config.h" +#include "string.h" + +int (*__read_char__)(void); +void (*__write_char__)(char c); + +extern unsigned long int __CMD_TABLE_START__; +extern unsigned long int __AUTO_TABLE_START__; + +static const cmd_t *volatile table = (cmd_t *)&__CMD_TABLE_START__; +static const cmd_t *volatile auto_load = (cmd_t *)&__AUTO_TABLE_START__; +static volatile int __cmd_exec_status; + +/* + * To reduce the shell size the history feature + * is made optional. Skip history feature if + * SHELL_NO_HISTORY is defined. + */ +#ifndef SHELL_NO_HISTORY +static volatile int total_num_commands = 0; +static volatile int curr_command_ptr = 0; +static char cmd_history[NUM_HISTORY_ENTRIES][LINE_BUFF_SIZE]; +#endif + +static volatile bool __echo = ECHO_INIT_VALUE; // Should be set in the Makefile + +void set_read_char(int (*func)(void)) { __read_char__ = func; } + +void set_write_char(void (*func)(char)) { __write_char__ = func; } + +__attribute__((weak)) void setup(void) { + // to be provided by the user +} + +__attribute__((weak)) void loop(void) { + // to be provided by the user +} + +// This method is a place holder to prepend prompt +__attribute__((weak)) void prepend_prompt() { + ; // nothing by default +} + +// Check if prompt is active, by default true. +// Platforms can decide a logic for this. +__attribute__((weak)) int active_prompt() { return TRUE; } + +static void delete(void) { + __write_char__(BACK_SPACE); + __write_char__(SPACE); + __write_char__(BACK_SPACE); +} + +static void clear_prompt(int char_count) { + while (char_count) { + delete (); + char_count--; + } +} + +/* + * To reduce the shell size the history feature + * is made optional. Skip history feature if + * SHELL_NO_HISTORY is defined. + */ +#ifndef SHELL_NO_HISTORY +static void handle_up_arrow(char *cmd_buff, int *char_count) { + if (curr_command_ptr < total_num_commands - NUM_HISTORY_ENTRIES || + curr_command_ptr == 0) { + printf("%s", cmd_buff); + return; + } + + memset(cmd_buff, 0, LINE_BUFF_SIZE); + + curr_command_ptr--; + int index = (curr_command_ptr % NUM_HISTORY_ENTRIES); + memcpy(cmd_buff, &cmd_history[index], LINE_BUFF_SIZE); + *char_count = strlen(cmd_buff); + + printf("%s", cmd_buff); +} + +static void handle_down_arrow(char *cmd_buff, int *char_count) { + memset(cmd_buff, 0, LINE_BUFF_SIZE); + *char_count = 0; + if (curr_command_ptr == total_num_commands) return; + + curr_command_ptr++; + int index = (curr_command_ptr % NUM_HISTORY_ENTRIES); + memcpy(cmd_buff, &cmd_history[index], LINE_BUFF_SIZE); + *char_count = strlen(cmd_buff); + + printf("%s", cmd_buff); +} + +static void add_command_to_history(const char *cmd_str) { + + //add only if command is not empty + if (cmd_str == NULL || strcmp(cmd_str, "") == 0) { + return; + } + int index = total_num_commands % NUM_HISTORY_ENTRIES; + memcpy(&cmd_history[index], cmd_str, LINE_BUFF_SIZE); + total_num_commands++; + curr_command_ptr = total_num_commands; +} + +static int show_history(int argc, char **argv) { + uint32_t end_index = total_num_commands-1; + uint32_t beg_index = 0; + if (total_num_commands > NUM_HISTORY_ENTRIES) { + beg_index = total_num_commands - NUM_HISTORY_ENTRIES; + } + for (uint32_t index = beg_index; index <= end_index; ++index) { + printf("%s\n", cmd_history[index % NUM_HISTORY_ENTRIES]); + } + + return 0; +} + +ADD_CMD(history, "Show command history", show_history); + +#endif // SHELL_NO_HISTORY + + +#ifndef SHELL_NO_TAB_COMPLETE + +static int prefix_match(char *sub, int len, const char *str) { + if (sub == NULL || str == NULL || len <= 0 || len > strlen(str)) { + return FALSE; + } + + for (int i = 0; i 0) execute(argc, argv); +} + +static void exec_auto_cmds(void) { + for (int i = 0; auto_load[i].command_name != NULL; i++) { + auto_load[i].command(0, NULL); + } +} + +static int build_info(int argc, char **argv) { + printf("Build: [" SHELL_VERSION ":" USER_REPO_VERSION "] - [" BUILD_USER + "@" BUILD_HOST "] - " __DATE__ " - " __TIME__ "\n"); + return 0; +} + + +void __attribute__((optimize("O0"), weak)) initial_setup(void) { + /** + * Copy the data section from ROM to RAM and + * zero init the bss section if we are using + * Two segment memory. + * + * In case everything is in the RAM, skip copying the .data section + * and zero the .bss section. This helps keep the user/custom + * linker script and makefiles free from special variables to be declared. + * Less burden on the user. + */ + extern char _etext, _data, _edata, _bss, _ebss; + char *src = &_etext, *dst = &_data; + + /** + * Copy over the data section from ROM to RAM. + * In case of RAM based target, we skip this since + * src and dst would point to same location in RAM + */ + if (dst != src) + while (dst < &_edata) *(dst++) = *(src++); + + /* Clear .bss*/ + for (dst = &_bss; dst < &_ebss; dst++) *dst = 0; + + /** + * platform_init() is expected to be defined by the user. + * Expectation is that the user would do any needed hardware initialization + * And register two functions to read a byte and write a byte using + * - set_read_char(); + * - set_write_char(); + * + * typical implementation may look like: + * void platform_init(void) { + * uart_init(); + * set_read_char(uart_getchar); + * set_write_char(uart_putchar); + * } + */ + platform_init(); +} + +/** + * @brief spwans the prompt + * + */ +void prompt() { + initial_setup(); + exec_auto_cmds(); + setup(); + + // while (TRUE) { + // shell(); + // } +} + +void shell1(){ + while(1){ + shell(); + } +} + +int exec(char *cmd_str) { + int argc; + + // TODO: this takes too much stack space. Optimize! + char *argv[MAX_ARG_COUNT]; + + // parse the line_buff + argc = parse_line(argv, cmd_str, MAX_ARG_COUNT); + + // execute the parsed commands + if (argc > 0) execute(argc, argv); + + return __cmd_exec_status; +} + +cmd get_function_addr(char *cmd_str) { + for (int i = 0; table[i].command_name != NULL; i++) { + if (strcmp(cmd_str, table[i].command_name) == 0) { + return table[i].command; + } + } + return NULL; +} + +int help(int argc, char **argv) { + int i = 0; + /* Default to Verbose */ + bool verbose = true; + + if (argc > 1 && (strcmp(argv[1], "-l")==0)) { + verbose = false; + } else { + printf("use: help -l for list only.\n\n"); + } + + while (table[i].command_name != NULL) { + printf(table[i].command_name); + + if (verbose) { + printf("\n\t"); + printf(table[i].command_help); + } + + printf("\n"); + i++; + } + + return 0; +} + +int cmd_exec_status(int argc, char **argv) { + printf("%d\n", __cmd_exec_status); + return 0; +} + +// DO NOT REMOVE THESE +AUTO_CMD(version, "Prints details of the build", build_info); +ADD_CMD(help, "Prints all available commands", help); +ADD_CMD(status, "Returns exit status of last executed command", + cmd_exec_status); + +// Mandatory! +__attribute__((section(".cmd_end"))) static volatile cmd_t cmd_end_ = { + NULL, NULL, NULL}; \ No newline at end of file diff --git a/shell/startup/cortex-m.S b/shell/startup/cortex-m.S index 6e95303..212fa93 100644 --- a/shell/startup/cortex-m.S +++ b/shell/startup/cortex-m.S @@ -19,5 +19,5 @@ .globl reset_handler .type reset_handler, %function reset_handler: - bl prompt + bl main_blinky1 bl .