diff --git a/Micropendous/Firmware/VirtualSerial_FreeRTOS/Descriptors.c b/Micropendous/Firmware/VirtualSerial_FreeRTOS/Descriptors.c index c4b4b363..b8665fef 100644 --- a/Micropendous/Firmware/VirtualSerial_FreeRTOS/Descriptors.c +++ b/Micropendous/Firmware/VirtualSerial_FreeRTOS/Descriptors.c @@ -214,9 +214,9 @@ const USB_Descriptor_String_t PROGMEM ManufacturerString = */ const USB_Descriptor_String_t PROGMEM ProductString = { - .Header = {.Size = USB_STRING_LEN(35), .Type = DTYPE_String}, + .Header = {.Size = USB_STRING_LEN(40), .Type = DTYPE_String}, - .UnicodeString = L"LUFA-lib.org CDC VirtualSerial Demo" + .UnicodeString = L"LUFA-lib.org VirtualSerial FreeRTOS Demo" }; /** This function is called by the library when in device mode, and must be overridden (see library "USB Descriptors" diff --git a/Micropendous/Firmware/VirtualSerial_FreeRTOS/FreeRTOSConfig.h b/Micropendous/Firmware/VirtualSerial_FreeRTOS/FreeRTOSConfig.h new file mode 100644 index 00000000..269548a6 --- /dev/null +++ b/Micropendous/Firmware/VirtualSerial_FreeRTOS/FreeRTOSConfig.h @@ -0,0 +1,101 @@ +/* + FreeRTOS V6.1.0 - Copyright (C) 2010 Real Time Engineers Ltd. + + *************************************************************************** + * * + * If you are: * + * * + * + New to FreeRTOS, * + * + Wanting to learn FreeRTOS or multitasking in general quickly * + * + Looking for basic training, * + * + Wanting to improve your FreeRTOS skills and productivity * + * * + * then take a look at the FreeRTOS books - available as PDF or paperback * + * * + * "Using the FreeRTOS Real Time Kernel - a Practical Guide" * + * http://www.FreeRTOS.org/Documentation * + * * + * A pdf reference manual is also available. Both are usually delivered * + * to your inbox within 20 minutes to two hours when purchased between 8am * + * and 8pm GMT (although please allow up to 24 hours in case of * + * exceptional circumstances). Thank you for your support! * + * * + *************************************************************************** + + This file is part of the FreeRTOS distribution. + + FreeRTOS is free software; you can redistribute it and/or modify it under + the terms of the GNU General Public License (version 2) as published by the + Free Software Foundation AND MODIFIED BY the FreeRTOS exception. + ***NOTE*** The exception to the GPL is included to allow you to distribute + a combined work that includes FreeRTOS without being obliged to provide the + source code for proprietary components outside of the FreeRTOS kernel. + FreeRTOS is distributed in the hope that it will be useful, but WITHOUT + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + more details. You should have received a copy of the GNU General Public + License and the FreeRTOS license exception along with FreeRTOS; if not it + can be viewed here: http://www.freertos.org/a00114.html and also obtained + by writing to Richard Barry, contact details for whom are available on the + FreeRTOS WEB site. + + 1 tab == 4 spaces! + + http://www.FreeRTOS.org - Documentation, latest information, license and + contact details. + + http://www.SafeRTOS.com - A version that is certified for use in safety + critical systems. + + http://www.OpenRTOS.com - Commercial support, development, porting, + licensing and training services. +*/ + +#ifndef FREERTOS_CONFIG_H +#define FREERTOS_CONFIG_H + +#include + +/*----------------------------------------------------------- + * 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_PREEMPTION 1 +#define configUSE_IDLE_HOOK 0 +#define configUSE_TICK_HOOK 0 +#define configCPU_CLOCK_HZ ( ( unsigned long ) F_CPU ) +#define configTICK_RATE_HZ ( ( portTickType ) 5000 ) +#define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 5 ) +#define configMINIMAL_STACK_SIZE ( ( unsigned short ) 256 ) +#define configTOTAL_HEAP_SIZE ( (size_t ) ( 2048 ) ) +#define configMAX_TASK_NAME_LEN ( 8 ) +#define configUSE_TRACE_FACILITY 0 +#define configUSE_16_BIT_TICKS 1 +#define configIDLE_SHOULD_YIELD 1 +#define configQUEUE_REGISTRY_SIZE 0 + +/* Co-routine definitions. */ +#define configUSE_CO_ROUTINES 0 +#define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) + +/* 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 + + +#endif /* FREERTOS_CONFIG_H */ diff --git a/Micropendous/Firmware/VirtualSerial_FreeRTOS/TestThroughputOfVirtualSerial.py b/Micropendous/Firmware/VirtualSerial_FreeRTOS/TestThroughputOfVirtualSerial.py index 570edc6b..38197fe7 100644 --- a/Micropendous/Firmware/VirtualSerial_FreeRTOS/TestThroughputOfVirtualSerial.py +++ b/Micropendous/Firmware/VirtualSerial_FreeRTOS/TestThroughputOfVirtualSerial.py @@ -23,10 +23,11 @@ def SerialThroughputTest(comport, transferSize, transfersToComplete): i = 0 s = '' while (i < (transferSize - 1)): - s = s + 'A' + # U is 0x55 = 0b01010101 + s = s + 'U' i = i + 1 - # want last letter to be X - s = s + 'X' + # want last letter to be ? = 0x3F = 0b00111111 + s = s + '?' # complete a series of transfers i = 0 diff --git a/Micropendous/Firmware/VirtualSerial_FreeRTOS/VirtualSerial.c b/Micropendous/Firmware/VirtualSerial_FreeRTOS/VirtualSerial.c index cf6c1563..a11e0f51 100644 --- a/Micropendous/Firmware/VirtualSerial_FreeRTOS/VirtualSerial.c +++ b/Micropendous/Firmware/VirtualSerial_FreeRTOS/VirtualSerial.c @@ -9,8 +9,8 @@ /* Copyright 2011 Dean Camera (dean [at] fourwalledcubicle [dot] com) - Updated for Loopback by Opendous Inc. 2011-11-22 - www.Micropendous.org/VirtualSerial + Updated for FreeRTOS by Opendous Inc. 2011-11-25 + www.Micropendous.org/VirtualSerial_FreeRTOS Permission to use, copy, modify, distribute, and sell this software and its documentation for any purpose is hereby granted @@ -83,19 +83,18 @@ int main(void) CDC_Device_CreateStream(&VirtualSerial_CDC_Interface, &USBSerialStream); LEDs_SetAllLEDs(LEDMASK_USB_NOTREADY); - sei(); - for (;;) - { - MainTask(); + // Create Tasks for FreeRTOS + // The VirtualSerial/USB-CDC task is highest priority to ensure USB functions run in time + // TODO/NOTE: AVRlibc stdio functions are not thread-safe + xTaskCreate(MainTask, (signed portCHAR *) "MainTask", configMINIMAL_STACK_SIZE, NULL, MAIN_TASK_PRIORITY, NULL ); + xTaskCreate(VirtualSerialTask, (signed portCHAR *) "ViSeTask", configMINIMAL_STACK_SIZE, NULL, (ViSe_TASK_PRIORITY | portPRIVILEGE_BIT), NULL ); - // Must throw away unused bytes from the host, or it will lock up while waiting for the device - // TODO: this causes loopback to fail - //CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface); + // Start the scheduler + vTaskStartScheduler(); - CDC_Device_USBTask(&VirtualSerial_CDC_Interface); - USB_USBTask(); - } + // Should never get here! + return 0; } @@ -121,6 +120,13 @@ void SetupHardware(void) } +// CoRoutines are not enabled, but FreeRTOS complains during compile +void vApplicationIdleHook(void) +{ + //vCoRoutineSchedule(); +} + + /** Event handler for the library USB Connection event. */ void EVENT_USB_Device_Connect(void) { @@ -150,23 +156,69 @@ void EVENT_USB_Device_ControlRequest(void) } +static void VirtualSerialTask(void *pvParameters) +{ -void MainTask(void) + for (;;) + { + // Must throw away unused bytes from the host, or it will lock up while waiting for the device + // TODO: this causes loopback to fail + //CDC_Device_ReceiveByte(&VirtualSerial_CDC_Interface); + + // want CDC and USB functions to run without interruption but + // with interrupts enabled so ENTER/EXIT_CRITICAL won't work + vTaskSuspendAll(); + + CDC_Device_USBTask(&VirtualSerial_CDC_Interface); + USB_USBTask(); + + xTaskResumeAll(); + + vTaskDelay((portTickType) taskDelayPeriod ); + } + +} + + + +static void MainTask(void *pvParameters) +{ + for(;;) { + MainTaskLoop(); + portYIELD(); + } +} + + + +void MainTaskLoop(void) { int count = 0; // If the host has sent data then echo it back // Throughput is maximized if the full EP buffer is read and sent each time // Throughput approaches CDC_TXRX_EPSIZE kbytes/second and depends on transfer size from host - if ((count = fread(&buffer, 1, CDC_TXRX_EPSIZE, &USBSerialStream)) > 0) { - fwrite(&buffer, 1, count, &USBSerialStream); - } + // NOTE: AVRlibc stdio functions are not thread-safe and must therefore be in a Suspend-Resume section + vTaskSuspendAll(); + count = fread(&buffer, 1, CDC_TXRX_EPSIZE, &USBSerialStream); + xTaskResumeAll(); + + //TODO: you can process the received buffer data here + + vTaskSuspendAll(); + if (count > 0) { + fwrite(&buffer, 1, count, &USBSerialStream); + } + xTaskResumeAll(); // If HWB Button is pressed then send formatted strings if (Buttons_GetStatus()) { - fprintf_P(&USBSerialStream, PSTR("\r\nHWB has been pressed!\r\n")); // send a constant string stored in FLASH - fprintf(&USBSerialStream, "PORTD = %3x\r\n", PIND); // send a string that is dynamic and stored in SRAM + // NOTE: AVRlibc stdio functions are not thread-safe and must therefore be in a Suspend-Resume section + vTaskSuspendAll(); + fprintf_P(&USBSerialStream, PSTR("\r\nHWB has been pressed!\r\n")); // send a constant string stored in FLASH + fprintf(&USBSerialStream, "PORTD = %3x\r\n", PIND); // send a string that is dynamic and stored in SRAM + xTaskResumeAll(); } } diff --git a/Micropendous/Firmware/VirtualSerial_FreeRTOS/VirtualSerial.h b/Micropendous/Firmware/VirtualSerial_FreeRTOS/VirtualSerial.h index f35c2fb4..e5d16002 100644 --- a/Micropendous/Firmware/VirtualSerial_FreeRTOS/VirtualSerial.h +++ b/Micropendous/Firmware/VirtualSerial_FreeRTOS/VirtualSerial.h @@ -51,6 +51,19 @@ #include #include + // FreeRTOS include files + #include "FreeRTOS.h" + #include "task.h" + #include "croutine.h" + #include "FreeRTOSConfig.h" + + // FreeRTOS Task Settings + // USB-CDC/VirtualSerial Task must run at higher priority than the MainTask loop + #define MAIN_TASK_PRIORITY ( configMAX_PRIORITIES - 3 ) + #define ViSe_TASK_PRIORITY ( configMAX_PRIORITIES - 1 ) // highest priority + + #define taskDelayPeriod 3 + /* Macros: */ /** LED mask for the library LED driver, to indicate that the USB interface is not ready. */ #define LEDMASK_USB_NOTREADY LEDS_LED1 @@ -66,7 +79,10 @@ /* Function Prototypes: */ void SetupHardware(void); - void MainTask(void); + void MainTaskLoop(void); + void vApplicationIdleHook(void); + static void VirtualSerialTask(void *pvParameters); + static void MainTask(void *pvParameters); void EVENT_USB_Device_Connect(void); void EVENT_USB_Device_Disconnect(void); diff --git a/Micropendous/Firmware/VirtualSerial_FreeRTOS/makefile b/Micropendous/Firmware/VirtualSerial_FreeRTOS/makefile index ec9d34cb..e0f03d44 100644 --- a/Micropendous/Firmware/VirtualSerial_FreeRTOS/makefile +++ b/Micropendous/Firmware/VirtualSerial_FreeRTOS/makefile @@ -64,10 +64,8 @@ # MCU name - uncomment _ONE_ of the following -#MCU = at90usb82 -#MCU = at90usb162 -#MCU = atmega16u2 -#MCU = atmega32u2 +# NOTE that the current VirtualSerial_FreeRTOS demo requires 2.5kb+ SRAM as FreeRTOSConfig.h +# sets configMINIMAL_STACK_SIZE=256 and configTOTAL_HEAP_SIZE=2048 #MCU = atmega32u4 #MCU = at90usb646 #MCU = at90usb647 @@ -159,8 +157,10 @@ OBJDIR = . # Path to the LUFA library LUFA_PATH = ../../libs/LUFA -AVRLIB_PATH = ../../libs/avrlib -ARDUINO_PATH = ../../libs/Arduino1 +FREERTOS_PATH = ../../libs/FreeRTOS +FREERTOS_DEMO_DIR = $(FREERTOS_PATH)/Demo/Common/Minimal +FREERTOS_SOURCE_DIR = $(FREERTOS_PATH)/Source +FREERTOS_PORT_DIR = $(FREERTOS_PATH)/Source/portable/GCC/AT90USB_ATmegaXXUY # LUFA library compile-time options and predefined tokens @@ -186,7 +186,12 @@ include $(LUFA_PATH)/LUFA/makefile SRC = $(TARGET).c \ Descriptors.c \ $(LUFA_SRC_USB) \ - $(LUFA_SRC_USBCLASS) + $(LUFA_SRC_USBCLASS) \ + $(FREERTOS_SOURCE_DIR)/tasks.c \ + $(FREERTOS_SOURCE_DIR)/queue.c \ + $(FREERTOS_SOURCE_DIR)/list.c \ + $(FREERTOS_SOURCE_DIR)/portable/MemMang/heap_1.c \ + $(FREERTOS_PORT_DIR)/port.c # List C++ source files here. (C dependencies are automatically generated.) @@ -242,7 +247,9 @@ DEBUG = dwarf-2 # Each directory must be seperated by a space. # Use forward slashes for directory separators. # For a directory that has spaces, enclose it in quotes. -EXTRAINCDIRS = $(LUFA_PATH)/ $(AVRLIB_PATH)/ $(ARDUINO_PATH)/ +EXTRAINCDIRS = $(LUFA_PATH)/ +EXTRAINCDIRS += $(FREERTOS_SOURCE_DIR)/include/ $(FREERTOS_PORT_DIR)/ +EXTRAINCDIRS += $(FREERTOS_PATH)/Demo/Common/include/ # Compiler flag to set the C Standard level.