From cb117c39e5944d136cf31be904032b892d251012 Mon Sep 17 00:00:00 2001 From: richardbarry Date: Fri, 29 May 2009 14:30:24 +0000 Subject: [PATCH] Work in progress on the LPC1766 port. git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@745 1d2547de-c912-0410-9cb9-b8ca96c0e9e2 --- .../RTOSDemo/.cproject | 8 +- .../RTOSDemo/FreeRTOSConfig.h | 96 +-- .../RTOSDemo/LED.c | 93 +++ .../RTOSDemo/LED.h | 59 ++ .../RTOSDemo/LPC17xx_defs.h | 4 +- .../RTOSDemo/Makefile | 3 +- .../RTOSDemo/main.c | 264 +++++-- .../RTOSDemo/webserver/emac.c | 660 +++++++++--------- .../RTOSDemo/webserver/httpd-cgi.c | 34 +- .../RTOSDemo/webserver/httpd.c | 4 +- .../RTOSDemo/webserver/uIP_Task.c | 40 +- 11 files changed, 777 insertions(+), 488 deletions(-) create mode 100644 Demo/CORTEX_LPC1766_GCC_RedSuite/RTOSDemo/LED.c create mode 100644 Demo/CORTEX_LPC1766_GCC_RedSuite/RTOSDemo/LED.h diff --git a/Demo/CORTEX_LPC1766_GCC_RedSuite/RTOSDemo/.cproject b/Demo/CORTEX_LPC1766_GCC_RedSuite/RTOSDemo/.cproject index 02b7045cc..dc9ebb528 100644 --- a/Demo/CORTEX_LPC1766_GCC_RedSuite/RTOSDemo/.cproject +++ b/Demo/CORTEX_LPC1766_GCC_RedSuite/RTOSDemo/.cproject @@ -393,10 +393,7 @@ <?xml version="1.0" encoding="UTF-8"?> <TargetConfig> <Properties property_0="" property_1="" property_2="" property_3="NXP" property_4="LPC1766ENG" property_count="5" version="1"/> -<infoList vendor="NXP"> -<info chip="LPC1766ENG" match_id="0x00033f33" name="LPC1766ENG"> -<chip> -<name>LPC1766ENG</name> +<infoList vendor="NXP"><info chip="LPC1766ENG" match_id="0x00033f33" name="LPC1766ENG"><chip><name>LPC1766ENG</name> <family>LPC17xx</family> <vendor>NXP (formerly Philips)</vendor> <reset board="None" core="Real" sys="Real"/> @@ -448,8 +445,7 @@ <peripheralInstance derived_from="MPU" determined="infoFile" id="MPU" location="0xE000ED90"/> <peripheralInstance derived_from="LPC1x_WDT" determined="infoFile" id="WDT" location="0x40000000"/> </chip> -<processor> -<name gcc_name="cortex-m3">Cortex-M3</name> +<processor><name gcc_name="cortex-m3">Cortex-M3</name> <family>Cortex-M</family> </processor> <link href="nxp_lpcxxxx_peripheral.xme" show="embed" type="simple"/> diff --git a/Demo/CORTEX_LPC1766_GCC_RedSuite/RTOSDemo/FreeRTOSConfig.h b/Demo/CORTEX_LPC1766_GCC_RedSuite/RTOSDemo/FreeRTOSConfig.h index 262648ffd..2e28472c7 100644 --- a/Demo/CORTEX_LPC1766_GCC_RedSuite/RTOSDemo/FreeRTOSConfig.h +++ b/Demo/CORTEX_LPC1766_GCC_RedSuite/RTOSDemo/FreeRTOSConfig.h @@ -1,55 +1,60 @@ /* - FreeRTOS.org V5.0.3 - Copyright (C) 2003-2008 Richard Barry. + FreeRTOS.org V5.2.0 - Copyright (C) 2003-2009 Richard Barry. This file is part of the FreeRTOS.org distribution. - FreeRTOS.org is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. + FreeRTOS.org 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. - FreeRTOS.org 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. + FreeRTOS.org 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 - along with FreeRTOS.org; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + You should have received a copy of the GNU General Public License along + with FreeRTOS.org; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. - A special exception to the GPL can be applied should you wish to distribute - a combined work that includes FreeRTOS.org, without being obliged to provide + A special exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS.org without being obliged to provide the source code for any proprietary components. See the licensing section - of http://www.FreeRTOS.org for full details of how and when the exception - can be applied. - - *************************************************************************** - *************************************************************************** - * * - * SAVE TIME AND MONEY! We can port FreeRTOS.org to your own hardware, * - * and even write all or part of your application on your behalf. * - * See http://www.OpenRTOS.com for details of the services we provide to * - * expedite your project. * - * * - *************************************************************************** - *************************************************************************** + of http://www.FreeRTOS.org for full details. + + + *************************************************************************** + * * + * Get the FreeRTOS eBook! See http://www.FreeRTOS.org/Documentation * + * * + * This is a concise, step by step, 'hands on' guide that describes both * + * general multitasking concepts and FreeRTOS specifics. It presents and * + * explains numerous examples that are written using the FreeRTOS API. * + * Full source code for all the examples is provided in an accompanying * + * .zip file. * + * * + *************************************************************************** + + 1 tab == 4 spaces! Please ensure to read the configuration and relevant port sections of the online documentation. - http://www.FreeRTOS.org - Documentation, latest information, license and + http://www.FreeRTOS.org - Documentation, latest information, license and contact details. - http://www.SafeRTOS.com - A version that is certified for use in safety + http://www.SafeRTOS.com - A version that is certified for use in safety critical systems. - http://www.OpenRTOS.com - Commercial support, development, porting, + http://www.OpenRTOS.com - Commercial support, development, porting, licensing and training services. */ #ifndef FREERTOS_CONFIG_H #define FREERTOS_CONFIG_H +#include "LPC17xx.h" +#include "LPC17xx_defs.h" + /*----------------------------------------------------------- * Application specific definitions. * @@ -62,10 +67,11 @@ #define configUSE_PREEMPTION 1 #define configUSE_IDLE_HOOK 0 -#define configUSE_TICK_HOOK 0 +#define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 5 ) +#define configUSE_TICK_HOOK 1 #define configCPU_CLOCK_HZ ( ( unsigned portLONG ) 72000000 ) #define configTICK_RATE_HZ ( ( portTickType ) 1000 ) -#define configMINIMAL_STACK_SIZE ( ( unsigned portSHORT ) 70 ) +#define configMINIMAL_STACK_SIZE ( ( unsigned portSHORT ) 80 ) #define configTOTAL_HEAP_SIZE ( ( size_t ) ( 19 * 1024 ) ) #define configMAX_TASK_NAME_LEN ( 12 ) #define configUSE_TRACE_FACILITY 1 @@ -74,6 +80,8 @@ #define configUSE_CO_ROUTINES 0 #define configUSE_MUTEXES 1 +#define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) + #define configUSE_COUNTING_SEMAPHORES 0 #define configUSE_ALTERNATIVE_API 0 #define configCHECK_FOR_STACK_OVERFLOW 2 @@ -81,9 +89,6 @@ #define configQUEUE_REGISTRY_SIZE 10 #define configGENERATE_RUN_TIME_STATS 1 -#define configMAX_PRIORITIES ( ( unsigned portBASE_TYPE ) 5 ) -#define configMAX_CO_ROUTINE_PRIORITIES ( 2 ) - /* Set the following definitions to 1 to include the API function, or zero to exclude the API function. */ @@ -96,6 +101,9 @@ to exclude the API function. */ #define INCLUDE_vTaskDelay 1 #define INCLUDE_uxTaskGetStackHighWaterMark 1 +/*----------------------------------------------------------- + * Ethernet configuration. + *-----------------------------------------------------------*/ /* MAC address configuration. */ #define configMAC_ADDR0 0x00 @@ -130,27 +138,21 @@ to exclude the API function. */ #define configMAX_SYSCALL_INTERRUPT_PRIORITY ( 5 << (8 - configPRIO_BITS) ) -#define TMR0_BASE_ADDR 0x40004000 -#define T0TCR (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x04)) -#define T0CTCR (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x70)) -#define T0PR (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x0C)) -#define T0TC (*(volatile unsigned long *)(TMR0_BASE_ADDR + 0x08)) -#define TCR_COUNT_RESET ( 0x02 ) -#define TCR_COUNT_ENABLE ( 0x01 ) -#define CTCR_CTM_TIMER ( 0x00 ) -#define _PCLKSEL0 (*(volatile unsigned long *)(SCB_BASE_ADDR + 0x1A8)) + +/*----------------------------------------------------------- + * Macros required to setup the timer for the run time stats. + *-----------------------------------------------------------*/ extern void vConfigureTimerForRunTimeStats( void ); #define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() vConfigureTimerForRunTimeStats() #define portGET_RUN_TIME_COUNTER_VALUE() T0TC + +/* The structure that is passed on the xLCDQueue. Put here for convenience. */ typedef struct { - long xColumn; char *pcMessage; } xLCDMessage; - - #endif /* FREERTOS_CONFIG_H */ diff --git a/Demo/CORTEX_LPC1766_GCC_RedSuite/RTOSDemo/LED.c b/Demo/CORTEX_LPC1766_GCC_RedSuite/RTOSDemo/LED.c new file mode 100644 index 000000000..79e945ca0 --- /dev/null +++ b/Demo/CORTEX_LPC1766_GCC_RedSuite/RTOSDemo/LED.c @@ -0,0 +1,93 @@ +/* + FreeRTOS.org V5.2.0 - Copyright (C) 2003-2009 Richard Barry. + + This file is part of the FreeRTOS.org distribution. + + FreeRTOS.org 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. + + FreeRTOS.org 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 along + with FreeRTOS.org; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + A special exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS.org without being obliged to provide + the source code for any proprietary components. See the licensing section + of http://www.FreeRTOS.org for full details. + + + *************************************************************************** + * * + * Get the FreeRTOS eBook! See http://www.FreeRTOS.org/Documentation * + * * + * This is a concise, step by step, 'hands on' guide that describes both * + * general multitasking concepts and FreeRTOS specifics. It presents and * + * explains numerous examples that are written using the FreeRTOS API. * + * Full source code for all the examples is provided in an accompanying * + * .zip file. * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + 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. +*/ + +#include "FreeRTOS.h" +#include "task.h" + +void vToggleLED( unsigned long ulLED ) +{ + /* ulLED is a bit mask for the LED. */ + + taskENTER_CRITICAL(); + { + if( FIO2PIN & ulLED ) + { + FIO2CLR = ulLED; + } + else + { + FIO2SET = ulLED; + } + } + taskEXIT_CRITICAL(); +} +/*-----------------------------------------------------------*/ + +void vSetLEDState( unsigned long ulLED, long lState ) +{ + /* ulLED is a bit mask for the LED. */ + if( lState == 0 ) + { + FIO2CLR = ulLED; + } + else + { + FIO2SET = ulLED; + } +} +/*-----------------------------------------------------------*/ + +long lGetLEDState( unsigned long ulLED ) +{ + /* ulLED is a bit mask for the LED. */ + return FIO2PIN & ulLED; +} +/*-----------------------------------------------------------*/ diff --git a/Demo/CORTEX_LPC1766_GCC_RedSuite/RTOSDemo/LED.h b/Demo/CORTEX_LPC1766_GCC_RedSuite/RTOSDemo/LED.h new file mode 100644 index 000000000..9e12105c2 --- /dev/null +++ b/Demo/CORTEX_LPC1766_GCC_RedSuite/RTOSDemo/LED.h @@ -0,0 +1,59 @@ +/* + FreeRTOS.org V5.2.0 - Copyright (C) 2003-2009 Richard Barry. + + This file is part of the FreeRTOS.org distribution. + + FreeRTOS.org 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. + + FreeRTOS.org 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 along + with FreeRTOS.org; if not, write to the Free Software Foundation, Inc., 59 + Temple Place, Suite 330, Boston, MA 02111-1307 USA. + + A special exception to the GPL is included to allow you to distribute a + combined work that includes FreeRTOS.org without being obliged to provide + the source code for any proprietary components. See the licensing section + of http://www.FreeRTOS.org for full details. + + + *************************************************************************** + * * + * Get the FreeRTOS eBook! See http://www.FreeRTOS.org/Documentation * + * * + * This is a concise, step by step, 'hands on' guide that describes both * + * general multitasking concepts and FreeRTOS specifics. It presents and * + * explains numerous examples that are written using the FreeRTOS API. * + * Full source code for all the examples is provided in an accompanying * + * .zip file. * + * * + *************************************************************************** + + 1 tab == 4 spaces! + + Please ensure to read the configuration and relevant port sections of the + online documentation. + + 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 LED_HH +#define LED_HH + +void vToggleLED( unsigned long ulLED ); +void vSetLEDState( unsigned long ulLED, long lState ); +long lGetLEDState( unsigned long ulLED ); + +#endif diff --git a/Demo/CORTEX_LPC1766_GCC_RedSuite/RTOSDemo/LPC17xx_defs.h b/Demo/CORTEX_LPC1766_GCC_RedSuite/RTOSDemo/LPC17xx_defs.h index bdc0c8f7a..e7f2b2213 100644 --- a/Demo/CORTEX_LPC1766_GCC_RedSuite/RTOSDemo/LPC17xx_defs.h +++ b/Demo/CORTEX_LPC1766_GCC_RedSuite/RTOSDemo/LPC17xx_defs.h @@ -19,7 +19,9 @@ #define SRAM_BASE_AHB ((unsigned long)0x20000000) // 32 Kb /* System Control Space memory map */ -#define SCS_BASE ((unsigned long)0xE000E000) +#ifndef SCS_BASE + #define SCS_BASE ((unsigned long)0xE000E000) +#endif #define SysTick_BASE (SCS_BASE + 0x0010) #define NVIC_BASE (SCS_BASE + 0x0100) diff --git a/Demo/CORTEX_LPC1766_GCC_RedSuite/RTOSDemo/Makefile b/Demo/CORTEX_LPC1766_GCC_RedSuite/RTOSDemo/Makefile index cc78af7fd..e3a3f3e61 100644 --- a/Demo/CORTEX_LPC1766_GCC_RedSuite/RTOSDemo/Makefile +++ b/Demo/CORTEX_LPC1766_GCC_RedSuite/RTOSDemo/Makefile @@ -52,7 +52,7 @@ RM := rm -rf # Set the optimisation level - this should be set to 0, 1, 2, 3 or s (s for size). -OPTIM=0 +OPTIM=1 # Set the debug level DEBUG=-g3 @@ -118,6 +118,7 @@ Demo_OBJS= $(OUTPUT_DIR)/main.o \ $(OUTPUT_DIR)/blocktim.o \ $(OUTPUT_DIR)/printf-stdarg.o \ $(OUTPUT_DIR)/cr_startup_nxp_cm3.o \ + $(OUTPUT_DIR)/LED.o \ $(OUTPUT_DIR)/syscalls.o # This is just a dummy. # The TCP/IP and WEB server files. diff --git a/Demo/CORTEX_LPC1766_GCC_RedSuite/RTOSDemo/main.c b/Demo/CORTEX_LPC1766_GCC_RedSuite/RTOSDemo/main.c index cb412c443..86a3dcc8e 100644 --- a/Demo/CORTEX_LPC1766_GCC_RedSuite/RTOSDemo/main.c +++ b/Demo/CORTEX_LPC1766_GCC_RedSuite/RTOSDemo/main.c @@ -50,7 +50,39 @@ */ - +/* + * Creates all the demo application tasks, then starts the scheduler. The WEB + * documentation provides more details of the standard demo application tasks + * (which just exist to test the kernel port and provide an example of how to use + * each FreeRTOS API function). + * + * In addition to the standard demo tasks, the following tasks and tests are + * defined and/or created within this file: + * + * "LCD" task - the LCD task is a 'gatekeeper' task. It is the only task that + * is permitted to access the display directly. Other tasks wishing to write a + * message to the LCD send the message on a queue to the LCD task instead of + * accessing the LCD themselves. The LCD task just blocks on the queue waiting + * for messages - waking and displaying the messages as they arrive. The use + * of a gatekeeper in this manner permits both tasks and interrupts to write to + * the LCD without worrying about mutual exclusion. This is demonstrated by the + * check hook (see below) which sends messages to the display even though it + * executes from an interrupt context. + * + * "Check" hook - This only executes fully every five seconds from the tick + * hook. Its main function is to check that all the standard demo tasks are + * still operational. Should any unexpected behaviour be discovered within a + * demo task then the tick hook will write an error to the LCD (via the LCD task). + * If all the demo tasks are executing with their expected behaviour then the + * check task writes PASS to the LCD (again via the LCD task), as described above. + * + * LED tasks - These just demonstrate how multiple instances of a single task + * definition can be created. Each LED task simply toggles an LED. The task + * parameter is used to pass the number of the LED to be toggled into the task. + * + * "uIP" task - This is the task that handles the uIP stack. All TCP/IP + * processing is performed in this task. + */ /* Standard includes. */ #include @@ -64,9 +96,6 @@ /* Hardware library includes. */ #include "LPC17xx_defs.h" - -#define NUM_LEDS 8 - /* Demo app includes. */ #include "BlockQ.h" #include "integer.h" @@ -79,28 +108,33 @@ #include "QPeek.h" #include "recmutex.h" #include "lcd/portlcd.h" +#include "LED.h" /*-----------------------------------------------------------*/ +/* The number of LED tasks that will be created. */ +#define mainNUM_LED_TASKS ( 6 ) + /* The time between cycles of the 'check' functionality (defined within the tick hook. */ #define mainCHECK_DELAY ( ( portTickType ) 5000 / portTICK_RATE_MS ) /* Task priorities. */ #define mainQUEUE_POLL_PRIORITY ( tskIDLE_PRIORITY + 2 ) -#define mainCHECK_TASK_PRIORITY ( tskIDLE_PRIORITY + 3 ) #define mainSEM_TEST_PRIORITY ( tskIDLE_PRIORITY + 1 ) #define mainBLOCK_Q_PRIORITY ( tskIDLE_PRIORITY + 2 ) -#define mainCREATOR_TASK_PRIORITY ( tskIDLE_PRIORITY + 3 ) +#define mainUIP_TASK_PRIORITY ( tskIDLE_PRIORITY + 3 ) +#define mainLCD_TASK_PRIORITY ( tskIDLE_PRIORITY + 2 ) #define mainINTEGER_TASK_PRIORITY ( tskIDLE_PRIORITY ) #define mainGEN_QUEUE_TASK_PRIORITY ( tskIDLE_PRIORITY ) -/* The period of the system clock in nano seconds. This is used to calculate -the jitter time in nano seconds. */ -#define mainNS_PER_CLOCK ( ( unsigned portLONG ) ( ( 1.0 / ( double ) configCPU_CLOCK_HZ ) * 1000000000.0 ) ) - +/* The WEB server has a larger stack as it utilises stack hungry string +handling library calls. */ #define mainBASIC_WEB_STACK_SIZE ( configMINIMAL_STACK_SIZE * 4 ) + +/* The length of the queue used to send messages to the LCD task. */ #define mainQUEUE_SIZE ( 3 ) + /*-----------------------------------------------------------*/ /* @@ -108,11 +142,6 @@ the jitter time in nano seconds. */ */ static void prvSetupHardware( void ); -/* - * Simply toggles the indicated LED. - */ -static void vToggleLED( unsigned portBASE_TYPE uxLED ); - /* * Very simple task that toggles an LED. */ @@ -124,20 +153,29 @@ static void vLEDTask( void *pvParameters ); */ extern void vuIP_Task( void *pvParameters ); +/* + * The LCD gatekeeper task as described in the comments at the top of this file. + * */ static void vLCDTask( void *pvParameters ); +/*-----------------------------------------------------------*/ + /* The queue used to send messages to the LCD task. */ xQueueHandle xLCDQueue; + + /*-----------------------------------------------------------*/ int main( void ) { long l; + /* Configure the hardware for use by this demo. */ prvSetupHardware(); - /* Start the standard demo tasks. */ + /* Start the standard demo tasks. These are just here to exercise the + kernel port and provide examples of how the FreeRTOS API can be used. */ vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY ); vCreateBlockTimeTasks(); vStartSemaphoreTasks( mainSEM_TEST_PRIORITY ); @@ -147,34 +185,36 @@ long l; vStartQueuePeekTasks(); vStartRecursiveMutexTasks(); - /* Start 8 tasks, each of which toggles a different LED at a different rate. */ - for( l = 0; l < NUM_LEDS; l++ ) + /* Start the tasks that toggle LEDs - the LED to toggle is passed in as the + task parameter. */ + for( l = 0; l < mainNUM_LED_TASKS; l++ ) { - xTaskCreate( vLEDTask, (signed char *) "LED", configMINIMAL_STACK_SIZE, ( void * ) l, tskIDLE_PRIORITY+1, NULL ); + xTaskCreate( vLEDTask, (signed char *) "LED", configMINIMAL_STACK_SIZE, ( void * ) l, tskIDLE_PRIORITY, NULL ); } - /* Create the uIP task. This uses the lwIP RTOS abstraction layer.*/ - xTaskCreate( vuIP_Task, ( signed char * ) "uIP", mainBASIC_WEB_STACK_SIZE, ( void * ) NULL, mainCHECK_TASK_PRIORITY - 1, NULL ); + /* Create the uIP task. The WEB server runs in this task. */ + xTaskCreate( vuIP_Task, ( signed char * ) "uIP", mainBASIC_WEB_STACK_SIZE, ( void * ) NULL, mainUIP_TASK_PRIORITY, NULL ); /* Create the queue used by the LCD task. Messages for display on the LCD are received via this queue. */ xLCDQueue = xQueueCreate( mainQUEUE_SIZE, sizeof( xLCDMessage ) ); - /* Start the tasks defined within this file/specific to this demo. */ - xTaskCreate( vLCDTask, ( signed portCHAR * ) "LCD", configMINIMAL_STACK_SIZE * 2, NULL, mainCHECK_TASK_PRIORITY - 1, NULL ); + /* Start the LCD gatekeeper task - as described in the comments at the top + of this file. */ + xTaskCreate( vLCDTask, ( signed portCHAR * ) "LCD", configMINIMAL_STACK_SIZE * 2, NULL, mainLCD_TASK_PRIORITY, NULL ); /* Start the scheduler. */ vTaskStartScheduler(); /* Will only get here if there was insufficient memory to create the idle - task. */ + task. The idle task is created within vTaskStartScheduler(). */ for( ;; ); } /*-----------------------------------------------------------*/ static void vLEDTask( void *pvParameters ) { -/* The LED to toggle is passed in as the task paramter. */ +/* The LED to toggle is passed in as the task parameter. */ long lLED = ( long ) pvParameters; unsigned long ulLEDToToggle = 1 << lLED; @@ -183,46 +223,149 @@ unsigned long ulDelayPeriod = 100 * ( lLED + 1 ); for( ;; ) { + /* Delay for the calculated time. */ vTaskDelay( ulDelayPeriod ); + + /* Toggle the LED before going back to delay again. */ vToggleLED( ulLEDToToggle ); } } /*-----------------------------------------------------------*/ -static void vToggleLED( unsigned portBASE_TYPE uxLED ) +void vLCDTask( void *pvParameters ) { - if( FIO2PIN & uxLED ) +xLCDMessage xMessage; +unsigned long ulRow = 0; +char cIPAddr[ 17 ]; /* To fit max IP address length of xxx.xxx.xxx.xxx\0 */ + + ( void ) pvParameters; + + /* The LCD gatekeeper task as described in the comments at the top of this + file. */ + + /* Initialise the LCD and display a startup message that includes the + configured IP address. */ + LCD_init(); + LCD_cur_off(); + LCD_cls(); + LCD_gotoxy( 1, 1 ); + LCD_puts( "www.FreeRTOS.org" ); + LCD_gotoxy( 1, 2 ); + sprintf( cIPAddr, "%d.%d.%d.%d", configIP_ADDR0, configIP_ADDR1, configIP_ADDR2, configIP_ADDR3 ); + LCD_puts( cIPAddr ); + + for( ;; ) { - FIO2CLR = uxLED; + /* Wait for a message to arrive to be displayed. */ + while( xQueueReceive( xLCDQueue, &xMessage, portMAX_DELAY ) != pdPASS ); + + /* Clear the old message. */ + LCD_cls(); + + /* Switch LCD rows, jut to make it obvious that messages are arriving. */ + ulRow++; + LCD_gotoxy( 1, ( ulRow & 0x01 ) + 1 ); + + /* Display the received text. */ + LCD_puts( xMessage.pcMessage ); } - else +} +/*-----------------------------------------------------------*/ + +void vApplicationTickHook( void ) +{ +static xLCDMessage xMessage = { "PASS" }; +static unsigned portLONG ulTicksSinceLastDisplay = 0; +portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; + + /* Called from every tick interrupt as described in the comments at the top + of this file. + + Have enough ticks passed to make it time to perform our health status + check again? */ + ulTicksSinceLastDisplay++; + if( ulTicksSinceLastDisplay >= mainCHECK_DELAY ) { - FIO2SET = uxLED; + /* Reset the counter so these checks run again in mainCHECK_DELAY + ticks time. */ + ulTicksSinceLastDisplay = 0; + + /* Has an error been found in any task? */ + if( xAreGenericQueueTasksStillRunning() != pdTRUE ) + { + xMessage.pcMessage = "ERROR: GEN Q"; + } + else if( xAreQueuePeekTasksStillRunning() != pdTRUE ) + { + xMessage.pcMessage = "ERROR: PEEK Q"; + } + else if( xAreBlockingQueuesStillRunning() != pdTRUE ) + { + xMessage.pcMessage = "ERROR: BLOCK Q"; + } + else if( xAreBlockTimeTestTasksStillRunning() != pdTRUE ) + { + xMessage.pcMessage = "ERROR: BLOCK TIME"; + } + else if( xAreSemaphoreTasksStillRunning() != pdTRUE ) + { + xMessage.pcMessage = "ERROR: SEMAPHR"; + } + else if( xArePollingQueuesStillRunning() != pdTRUE ) + { + xMessage.pcMessage = "ERROR: POLL Q"; + } + else if( xAreIntegerMathsTaskStillRunning() != pdTRUE ) + { + xMessage.pcMessage = "ERROR: INT MATH"; + } + else if( xAreRecursiveMutexTasksStillRunning() != pdTRUE ) + { + xMessage.pcMessage = "ERROR: REC MUTEX"; + } + + /* Send the message to the OLED gatekeeper for display. The + xHigherPriorityTaskWoken parameter is not actually used here + as this function is running in the tick interrupt anyway - but + it must still be supplied. */ + xHigherPriorityTaskWoken = pdFALSE; + xQueueSendFromISR( xLCDQueue, &xMessage, &xHigherPriorityTaskWoken ); } } /*-----------------------------------------------------------*/ void prvSetupHardware( void ) { - PCONP = 0; /* Disable peripherals power. */ - PCONP = PCONP_PCGPIO; /* Enable GPIO power. */ - PINSEL10 = 0; /* Disable TPIU. */ + /* Disable peripherals power. */ + PCONP = 0; + + /* Enable GPIO power. */ + PCONP = PCONP_PCGPIO; - PLL0CON &= ~PLLCON_PLLC; /* Disconnect the main PLL. */ + /* Disable TPIU. */ + PINSEL10 = 0; + + /* Disconnect the main PLL. */ + PLL0CON &= ~PLLCON_PLLC; PLL0FEED = PLLFEED_FEED1; PLL0FEED = PLLFEED_FEED2; while ((PLL0STAT & PLLSTAT_PLLC) != 0); - PLL0CON &= ~PLLCON_PLLE; /* Turn off the main PLL. */ + /* Turn off the main PLL. */ + PLL0CON &= ~PLLCON_PLLE; PLL0FEED = PLLFEED_FEED1; PLL0FEED = PLLFEED_FEED2; while ((PLL0STAT & PLLSTAT_PLLE) != 0); - CCLKCFG = 0; /* No CPU clock divider. */ - SCS = 0x20; /* OSCEN. */ + /* No CPU clock divider. */ + CCLKCFG = 0; + + /* OSCEN. */ + SCS = 0x20; while ((SCS & 0x40) == 0); - CLKSRCSEL = 1; /* Use main oscillator. */ + /* Use main oscillator. */ + CLKSRCSEL = 1; PLL0CFG = (PLLCFG_MUL16 | PLLCFG_DIV1); PLL0FEED = PLLFEED_FEED1; @@ -234,7 +377,8 @@ void prvSetupHardware( void ) PLL0FEED = PLLFEED_FEED1; PLL0FEED = PLLFEED_FEED2; - CCLKCFG = 5; /* 6x CPU clock divider (72 MHz) */ + /* 6x CPU clock divider (72 MHz) */ + CCLKCFG = 5; /* Wait for the PLL to lock. */ while ((PLL0STAT & PLLSTAT_PLOCK) == 0); @@ -256,6 +400,8 @@ void prvSetupHardware( void ) void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed portCHAR *pcTaskName ) { + /* This function will get called if a task overflows its stack. */ + ( void ) pxTask; ( void ) pcTaskName; @@ -265,8 +411,17 @@ void vApplicationStackOverflowHook( xTaskHandle *pxTask, signed portCHAR *pcTask void vConfigureTimerForRunTimeStats( void ) { +const unsigned long TCR_COUNT_RESET = 2, CTCR_CTM_TIMER = 0x00, TCR_COUNT_ENABLE = 0x01; + + /* This function configures a timer that is used as the time base when + collecting run time statistical information - basically the percentage + of CPU time that each task is utilising. It is called automatically when + the scheduler is started (assuming configGENERATE_RUN_TIME_STATS is set + to 1. */ + + /* Power up and feed the timer. */ PCONP |= 0x02UL; - _PCLKSEL0 = (_PCLKSEL0 & (~(0x3<<2))) | (0x01 << 2); + PCLKSEL0 = (PCLKSEL0 & (~(0x3<<2))) | (0x01 << 2); /* Reset Timer 0 */ T0TCR = TCR_COUNT_RESET; @@ -283,32 +438,3 @@ void vConfigureTimerForRunTimeStats( void ) } /*-----------------------------------------------------------*/ -void vLCDTask( void *pvParameters ) -{ -xLCDMessage xMessage; -char cIPAddr[ 17 ]; /* To fit max IP address length of xxx.xxx.xxx.xxx\0 */ - - ( void ) pvParameters; - - /* Initialise the LCD and display a startup message. */ - LCD_init(); - LCD_cur_off(); - LCD_cls(); - LCD_gotoxy( 1, 1 ); - LCD_puts( "www.FreeRTOS.org" ); - LCD_gotoxy( 1, 2 ); - sprintf( cIPAddr, "%d.%d.%d.%d", configIP_ADDR0, configIP_ADDR1, configIP_ADDR2, configIP_ADDR3 ); - LCD_puts( cIPAddr ); - - for( ;; ) - { - /* Wait for a message to arrive that requires displaying. */ - while( xQueueReceive( xLCDQueue, &xMessage, portMAX_DELAY ) != pdPASS ); - - /* Display the message. Print each message to a different position. */ - LCD_cls(); - LCD_gotoxy( ( xMessage.xColumn & 0x07 ) + 1, ( xMessage.xColumn & 0x01 ) + 1 ); - LCD_puts( xMessage.pcMessage ); - } -} -/*-----------------------------------------------------------*/ diff --git a/Demo/CORTEX_LPC1766_GCC_RedSuite/RTOSDemo/webserver/emac.c b/Demo/CORTEX_LPC1766_GCC_RedSuite/RTOSDemo/webserver/emac.c index 472265f05..1368c2157 100644 --- a/Demo/CORTEX_LPC1766_GCC_RedSuite/RTOSDemo/webserver/emac.c +++ b/Demo/CORTEX_LPC1766_GCC_RedSuite/RTOSDemo/webserver/emac.c @@ -1,6 +1,5 @@ /****************************************************************** ***** ***** - ***** Name: cs8900.c ***** ***** Ver.: 1.0 ***** ***** Date: 07/05/2001 ***** ***** Auth: Andreas Dannenberg ***** @@ -16,416 +15,451 @@ ******************************************************************/ /* Adapted from file originally written by Andreas Dannenberg. Supplied with permission. */ - #include "FreeRTOS.h" -#include "semphr.h" +#include "semphr.h" #include "task.h" #include "emac.h" #include "LPC17xx_defs.h" -#define configPINSEL2_VALUE 0x50150105 +#define configPINSEL2_VALUE 0x50150105 /* The semaphore used to wake the uIP task when data arives. */ -xSemaphoreHandle xEMACSemaphore = NULL; - -static unsigned short *rptr; -static unsigned short *tptr; +xSemaphoreHandle xEMACSemaphore = NULL; -// easyWEB internal function -// help function to swap the byte order of a WORD +static unsigned short *rptr; +static unsigned short *tptr; -static unsigned short SwapBytes(unsigned short Data) +static unsigned short SwapBytes( unsigned short Data ) { - return (Data >> 8) | (Data << 8); + return( Data >> 8 ) | ( Data << 8 ); } // Keil: function added to write PHY -void write_PHY (int PhyReg, int Value) +int write_PHY( int PhyReg, int Value ) { - unsigned int tout; - const unsigned int uiMaxTime = 10; - - MAC_MADR = DP83848C_DEF_ADR | PhyReg; - MAC_MWTD = Value; - - /* Wait utill operation completed */ - tout = 0; - for (tout = 0; tout < uiMaxTime; tout++) { - if ((MAC_MIND & MIND_BUSY) == 0) { - break; - } - vTaskDelay( 2 ); - } + unsigned int tout; + const unsigned int uiMaxTime = 10; + + MAC_MADR = DP83848C_DEF_ADR | PhyReg; + MAC_MWTD = Value; + + /* Wait utill operation completed */ + tout = 0; + for( tout = 0; tout < uiMaxTime; tout++ ) + { + if( (MAC_MIND & MIND_BUSY) == 0 ) + { + break; + } + + vTaskDelay( 2 ); + } + + if( tout < uiMaxTime ) + { + return pdPASS; + } + else + { + return pdFAIL; + } } - // Keil: function added to read PHY -unsigned short read_PHY (unsigned char PhyReg) +unsigned short read_PHY( unsigned char PhyReg, portBASE_TYPE *pxStatus ) { - unsigned int tout; - const unsigned int uiMaxTime = 10; - - MAC_MADR = DP83848C_DEF_ADR | PhyReg; - MAC_MCMD = MCMD_READ; - - /* Wait until operation completed */ - tout = 0; - for (tout = 0; tout < uiMaxTime; tout++) { - if ((MAC_MIND & MIND_BUSY) == 0) { - break; - } - vTaskDelay( 2 ); - } - MAC_MCMD = 0; - return (MAC_MRDD); -} + unsigned int tout; + const unsigned int uiMaxTime = 10; + + MAC_MADR = DP83848C_DEF_ADR | PhyReg; + MAC_MCMD = MCMD_READ; + + /* Wait until operation completed */ + tout = 0; + for( tout = 0; tout < uiMaxTime; tout++ ) + { + if( (MAC_MIND & MIND_BUSY) == 0 ) + { + break; + } + + vTaskDelay( 2 ); + } + + MAC_MCMD = 0; + if( tout >= uiMaxTime ) + { + *pxStatus = pdFAIL; + } + + return( MAC_MRDD ); +} // Keil: function added to initialize Rx Descriptors -void rx_descr_init (void) +void rx_descr_init( void ) { - unsigned int i; - - for (i = 0; i < NUM_RX_FRAG; i++) { - RX_DESC_PACKET(i) = RX_BUF(i); - RX_DESC_CTRL(i) = RCTRL_INT | (ETH_FRAG_SIZE-1); - RX_STAT_INFO(i) = 0; - RX_STAT_HASHCRC(i) = 0; - } - - /* Set EMAC Receive Descriptor Registers. */ - MAC_RXDESCRIPTOR = RX_DESC_BASE; - MAC_RXSTATUS = RX_STAT_BASE; - MAC_RXDESCRIPTORNUM = NUM_RX_FRAG-1; - - /* Rx Descriptors Point to 0 */ - MAC_RXCONSUMEINDEX = 0; + unsigned int i; + + for( i = 0; i < NUM_RX_FRAG; i++ ) + { + RX_DESC_PACKET( i ) = RX_BUF( i ); + RX_DESC_CTRL( i ) = RCTRL_INT | ( ETH_FRAG_SIZE - 1 ); + RX_STAT_INFO( i ) = 0; + RX_STAT_HASHCRC( i ) = 0; + } + + /* Set EMAC Receive Descriptor Registers. */ + MAC_RXDESCRIPTOR = RX_DESC_BASE; + MAC_RXSTATUS = RX_STAT_BASE; + MAC_RXDESCRIPTORNUM = NUM_RX_FRAG - 1; + + /* Rx Descriptors Point to 0 */ + MAC_RXCONSUMEINDEX = 0; } - // Keil: function added to initialize Tx Descriptors -void tx_descr_init (void) { - unsigned int i; - - for (i = 0; i < NUM_TX_FRAG; i++) { - TX_DESC_PACKET(i) = TX_BUF(i); - TX_DESC_CTRL(i) = 0; - TX_STAT_INFO(i) = 0; - } - - /* Set EMAC Transmit Descriptor Registers. */ - MAC_TXDESCRIPTOR = TX_DESC_BASE; - MAC_TXSTATUS = TX_STAT_BASE; - MAC_TXDESCRIPTORNUM = NUM_TX_FRAG-1; - - /* Tx Descriptors Point to 0 */ - MAC_TXPRODUCEINDEX = 0; +void tx_descr_init( void ) +{ + unsigned int i; + + for( i = 0; i < NUM_TX_FRAG; i++ ) + { + TX_DESC_PACKET( i ) = TX_BUF( i ); + TX_DESC_CTRL( i ) = 0; + TX_STAT_INFO( i ) = 0; + } + + /* Set EMAC Transmit Descriptor Registers. */ + MAC_TXDESCRIPTOR = TX_DESC_BASE; + MAC_TXSTATUS = TX_STAT_BASE; + MAC_TXDESCRIPTORNUM = NUM_TX_FRAG - 1; + + /* Tx Descriptors Point to 0 */ + MAC_TXPRODUCEINDEX = 0; } - // configure port-pins for use with LAN-controller, // reset it and send the configuration-sequence - -portBASE_TYPE Init_EMAC(void) +portBASE_TYPE Init_EMAC( void ) { -portBASE_TYPE xReturn = pdPASS; - -// Keil: function modified to access the EMAC -// Initializes the EMAC ethernet controller - volatile unsigned int regv,tout,id1,id2; - - /* Enable P1 Ethernet Pins. */ - PINSEL2 = configPINSEL2_VALUE; - PINSEL3 = (PINSEL3 & ~0x0000000F) | 0x00000005; - - /* Power Up the EMAC controller. */ - PCONP |= PCONP_PCENET; - vTaskDelay( 2 ); - - /* Reset all EMAC internal modules. */ - MAC_MAC1 = MAC1_RES_TX | MAC1_RES_MCS_TX | MAC1_RES_RX | MAC1_RES_MCS_RX | MAC1_SIM_RES | MAC1_SOFT_RES; - MAC_COMMAND = CR_REG_RES | CR_TX_RES | CR_RX_RES | CR_PASS_RUNT_FRM; - - /* A short delay after reset. */ - vTaskDelay( 2 ); - - /* Initialize MAC control registers. */ - MAC_MAC1 = MAC1_PASS_ALL; - MAC_MAC2 = MAC2_CRC_EN | MAC2_PAD_EN; - MAC_MAXF = ETH_MAX_FLEN; - MAC_CLRT = CLRT_DEF; - MAC_IPGR = IPGR_DEF; - - /* Enable Reduced MII interface. */ - MAC_COMMAND = CR_RMII | CR_PASS_RUNT_FRM; - - /* Reset Reduced MII Logic. */ - MAC_SUPP = SUPP_RES_RMII; - vTaskDelay( 2 ); - MAC_SUPP = 0; - - /* Put the PHY in reset mode */ - write_PHY (PHY_REG_BMCR, 0x8000); - write_PHY (PHY_REG_BMCR, 0x8000); - - /* Wait for hardware reset to end. */ - for (tout = 0; tout < 100; tout++) { - vTaskDelay( 10 ); - regv = read_PHY (PHY_REG_BMCR); - if (!(regv & 0x8000)) { - /* Reset complete */ - break; - } - } - - /* Set the Ethernet MAC Address registers */ - MAC_SA0 = (emacETHADDR0 << 8) | emacETHADDR1; - MAC_SA1 = (emacETHADDR2 << 8) | emacETHADDR3; - MAC_SA2 = (emacETHADDR4 << 8) | emacETHADDR5; - - /* Initialize Tx and Rx DMA Descriptors */ - rx_descr_init (); - tx_descr_init (); - - /* Receive Broadcast and Perfect Match Packets */ - MAC_RXFILTERCTRL = RFC_UCAST_EN | RFC_BCAST_EN | RFC_PERFECT_EN; - - /* Create the semaphore used ot wake the uIP task. */ - vSemaphoreCreateBinary( xEMACSemaphore ); - - /* Check if this is a DP83848C PHY. */ - id1 = read_PHY (PHY_REG_IDR1); - id2 = read_PHY (PHY_REG_IDR2); - if (((id1 << 16) | (id2 & 0xFFF0)) == DP83848C_ID) { - /* Configure the PHY device */ - - /* Use autonegotiation about the link speed. */ - write_PHY (PHY_REG_BMCR, PHY_AUTO_NEG); - /* Wait to complete Auto_Negotiation. */ - for (tout = 0; tout < 10; tout++) { - vTaskDelay( 100 ); - regv = read_PHY (PHY_REG_BMSR); - if (regv & 0x0020) { - /* Autonegotiation Complete. */ - break; - } - } - } - else - { - xReturn = pdFAIL; - } - - /* Check the link status. */ - if( xReturn == pdPASS ) - { - xReturn = pdFAIL; - for (tout = 0; tout < 10; tout++) { - vTaskDelay( 100 ); - regv = read_PHY (PHY_REG_STS); - if (regv & 0x0001) { - /* Link is on. */ - xReturn = pdPASS; - break; - } - } - } - - if( xReturn == pdPASS ) - { - /* Configure Full/Half Duplex mode. */ - if (regv & 0x0004) { - /* Full duplex is enabled. */ - MAC_MAC2 |= MAC2_FULL_DUP; - MAC_COMMAND |= CR_FULL_DUP; - MAC_IPGT = IPGT_FULL_DUP; - } - else { - /* Half duplex mode. */ - MAC_IPGT = IPGT_HALF_DUP; - } - - /* Configure 100MBit/10MBit mode. */ - if (regv & 0x0002) { - /* 10MBit mode. */ - MAC_SUPP = 0; - } - else { - /* 100MBit mode. */ - MAC_SUPP = SUPP_SPEED; - } - - /* Reset all interrupts */ - MAC_INTCLEAR = 0xFFFF; - - /* Enable receive and transmit mode of MAC Ethernet core */ - MAC_COMMAND |= (CR_RX_EN | CR_TX_EN); - MAC_MAC1 |= MAC1_REC_EN; - } - - return xReturn; + portBASE_TYPE xReturn = pdPASS; + + // Keil: function modified to access the EMAC + // Initializes the EMAC ethernet controller + volatile unsigned int regv, tout, id1, id2; + + /* Enable P1 Ethernet Pins. */ + PINSEL2 = configPINSEL2_VALUE; + PINSEL3 = ( PINSEL3 &~0x0000000F ) | 0x00000005; + + /* Power Up the EMAC controller. */ + PCONP |= PCONP_PCENET; + vTaskDelay( 2 ); + + /* Reset all EMAC internal modules. */ + MAC_MAC1 = MAC1_RES_TX | MAC1_RES_MCS_TX | MAC1_RES_RX | MAC1_RES_MCS_RX | MAC1_SIM_RES | MAC1_SOFT_RES; + MAC_COMMAND = CR_REG_RES | CR_TX_RES | CR_RX_RES | CR_PASS_RUNT_FRM; + + /* A short delay after reset. */ + vTaskDelay( 2 ); + + /* Initialize MAC control registers. */ + MAC_MAC1 = MAC1_PASS_ALL; + MAC_MAC2 = MAC2_CRC_EN | MAC2_PAD_EN; + MAC_MAXF = ETH_MAX_FLEN; + MAC_CLRT = CLRT_DEF; + MAC_IPGR = IPGR_DEF; + + /* Enable Reduced MII interface. */ + MAC_COMMAND = CR_RMII | CR_PASS_RUNT_FRM; + + /* Reset Reduced MII Logic. */ + MAC_SUPP = SUPP_RES_RMII; + vTaskDelay( 2 ); + MAC_SUPP = 0; + + /* Put the PHY in reset mode */ + write_PHY( PHY_REG_BMCR, 0x8000 ); + xReturn = write_PHY( PHY_REG_BMCR, 0x8000 ); + + /* Wait for hardware reset to end. */ + for( tout = 0; tout < 100; tout++ ) + { + vTaskDelay( 10 ); + regv = read_PHY( PHY_REG_BMCR, &xReturn ); + if( !(regv & 0x8000) ) + { + /* Reset complete */ + break; + } + } + + /* Check if this is a DP83848C PHY. */ + id1 = read_PHY( PHY_REG_IDR1, &xReturn ); + id2 = read_PHY( PHY_REG_IDR2, &xReturn ); + if( ((id1 << 16) | (id2 & 0xFFF0)) == DP83848C_ID ) + { + /* Set the Ethernet MAC Address registers */ + MAC_SA0 = ( emacETHADDR0 << 8 ) | emacETHADDR1; + MAC_SA1 = ( emacETHADDR2 << 8 ) | emacETHADDR3; + MAC_SA2 = ( emacETHADDR4 << 8 ) | emacETHADDR5; + + /* Initialize Tx and Rx DMA Descriptors */ + rx_descr_init(); + tx_descr_init(); + + /* Receive Broadcast and Perfect Match Packets */ + MAC_RXFILTERCTRL = RFC_UCAST_EN | RFC_BCAST_EN | RFC_PERFECT_EN; + + /* Create the semaphore used ot wake the uIP task. */ + vSemaphoreCreateBinary( xEMACSemaphore ); + + /* Configure the PHY device */ + + /* Use autonegotiation about the link speed. */ + if( write_PHY(PHY_REG_BMCR, PHY_AUTO_NEG) ) + { + /* Wait to complete Auto_Negotiation. */ + for( tout = 0; tout < 10; tout++ ) + { + vTaskDelay( 100 ); + regv = read_PHY( PHY_REG_BMSR, &xReturn ); + if( regv & 0x0020 ) + { + /* Autonegotiation Complete. */ + break; + } + } + } + } + else + { + xReturn = pdFAIL; + } + + /* Check the link status. */ + if( xReturn == pdPASS ) + { + xReturn = pdFAIL; + for( tout = 0; tout < 10; tout++ ) + { + vTaskDelay( 100 ); + regv = read_PHY( PHY_REG_STS, &xReturn ); + if( regv & 0x0001 ) + { + /* Link is on. */ + xReturn = pdPASS; + break; + } + } + } + + if( xReturn == pdPASS ) + { + /* Configure Full/Half Duplex mode. */ + if( regv & 0x0004 ) + { + /* Full duplex is enabled. */ + MAC_MAC2 |= MAC2_FULL_DUP; + MAC_COMMAND |= CR_FULL_DUP; + MAC_IPGT = IPGT_FULL_DUP; + } + else + { + /* Half duplex mode. */ + MAC_IPGT = IPGT_HALF_DUP; + } + + /* Configure 100MBit/10MBit mode. */ + if( regv & 0x0002 ) + { + /* 10MBit mode. */ + MAC_SUPP = 0; + } + else + { + /* 100MBit mode. */ + MAC_SUPP = SUPP_SPEED; + } + + /* Reset all interrupts */ + MAC_INTCLEAR = 0xFFFF; + + /* Enable receive and transmit mode of MAC Ethernet core */ + MAC_COMMAND |= ( CR_RX_EN | CR_TX_EN ); + MAC_MAC1 |= MAC1_REC_EN; + } + + return xReturn; } - // reads a word in little-endian byte order from RX_BUFFER - -unsigned short ReadFrame_EMAC(void) +unsigned short ReadFrame_EMAC( void ) { - return (*rptr++); + return( *rptr++ ); } // reads a word in big-endian byte order from RX_FRAME_PORT // (useful to avoid permanent byte-swapping while reading // TCP/IP-data) - -unsigned short ReadFrameBE_EMAC(void) +unsigned short ReadFrameBE_EMAC( void ) { - unsigned short ReturnValue; + unsigned short ReturnValue; - ReturnValue = SwapBytes (*rptr++); - return (ReturnValue); + ReturnValue = SwapBytes( *rptr++ ); + return( ReturnValue ); } - // copies bytes from frame port to MCU-memory // NOTES: * an odd number of byte may only be transfered // if the frame is read to the end! // * MCU-memory MUST start at word-boundary - -void CopyFromFrame_EMAC(void *Dest, unsigned short Size) +void CopyFromFrame_EMAC( void *Dest, unsigned short Size ) { - unsigned short * piDest; // Keil: Pointer added to correct expression - - piDest = Dest; // Keil: Line added - while (Size > 1) { - *piDest++ = ReadFrame_EMAC(); - Size -= 2; - } - - if (Size) { // check for leftover byte... - *(unsigned char *)piDest = (char)ReadFrame_EMAC();// the LAN-Controller will return 0 - } // for the highbyte + unsigned short *piDest; // Keil: Pointer added to correct expression + piDest = Dest; // Keil: Line added + while( Size > 1 ) + { + *piDest++ = ReadFrame_EMAC(); + Size -= 2; + } + + if( Size ) + { // check for leftover byte... + *( unsigned char * ) piDest = ( char ) ReadFrame_EMAC(); // the LAN-Controller will return 0 + } // for the highbyte } // does a dummy read on frame-I/O-port // NOTE: only an even number of bytes is read! - -void DummyReadFrame_EMAC(unsigned short Size) // discards an EVEN number of bytes -{ // from RX-fifo - while (Size > 1) { - ReadFrame_EMAC(); - Size -= 2; - } +void DummyReadFrame_EMAC( unsigned short Size ) // discards an EVEN number of bytes +{ // from RX-fifo + while( Size > 1 ) + { + ReadFrame_EMAC(); + Size -= 2; + } } -// Reads the length of the received ethernet frame and checks if the +// Reads the length of the received ethernet frame and checks if the // destination address is a broadcast message or not // returns the frame length -unsigned short StartReadFrame(void) { - unsigned short RxLen; - unsigned int idx; - - idx = MAC_RXCONSUMEINDEX; - RxLen = (RX_STAT_INFO(idx) & RINFO_SIZE) - 3; - rptr = (unsigned short *)RX_DESC_PACKET(idx); - return(RxLen); +unsigned short StartReadFrame( void ) +{ + unsigned short RxLen; + unsigned int idx; + + idx = MAC_RXCONSUMEINDEX; + RxLen = ( RX_STAT_INFO(idx) & RINFO_SIZE ) - 3; + rptr = ( unsigned short * ) RX_DESC_PACKET( idx ); + return( RxLen ); } -void EndReadFrame(void) { - unsigned int idx; +void EndReadFrame( void ) +{ + unsigned int idx; - /* DMA free packet. */ - idx = MAC_RXCONSUMEINDEX; + /* DMA free packet. */ + idx = MAC_RXCONSUMEINDEX; - if (++idx == NUM_RX_FRAG) - idx = 0; + if( ++idx == NUM_RX_FRAG ) + { + idx = 0; + } - MAC_RXCONSUMEINDEX = idx; + MAC_RXCONSUMEINDEX = idx; } -unsigned int CheckFrameReceived(void) { // Packet received ? - - if (MAC_RXPRODUCEINDEX != MAC_RXCONSUMEINDEX) // more packets received ? - return(1); - else - return(0); +unsigned int CheckFrameReceived( void ) +{ + // Packet received ? + if( MAC_RXPRODUCEINDEX != MAC_RXCONSUMEINDEX ) + { // more packets received ? + return( 1 ); + } + else + { + return( 0 ); + } } unsigned int uiGetEMACRxData( unsigned char *ucBuffer ) { -unsigned int uiLen = 0; + unsigned int uiLen = 0; - if( MAC_RXPRODUCEINDEX != MAC_RXCONSUMEINDEX ) - { - uiLen = StartReadFrame(); - CopyFromFrame_EMAC( ucBuffer, uiLen ); - EndReadFrame(); - } + if( MAC_RXPRODUCEINDEX != MAC_RXCONSUMEINDEX ) + { + uiLen = StartReadFrame(); + CopyFromFrame_EMAC( ucBuffer, uiLen ); + EndReadFrame(); + } - return uiLen; + return uiLen; } // requests space in EMAC memory for storing an outgoing frame - -void RequestSend(void) +void RequestSend( void ) { - unsigned int idx; + unsigned int idx; - idx = MAC_TXPRODUCEINDEX; - tptr = (unsigned short *)TX_DESC_PACKET(idx); + idx = MAC_TXPRODUCEINDEX; + tptr = ( unsigned short * ) TX_DESC_PACKET( idx ); } // check if ethernet controller is ready to accept the // frame we want to send - -unsigned int Rdy4Tx(void) +unsigned int Rdy4Tx( void ) { - return (1); // the ethernet controller transmits much faster -} // than the CPU can load its buffers - + return( 1 ); // the ethernet controller transmits much faster +} // than the CPU can load its buffers // writes a word in little-endian byte order to TX_BUFFER -void WriteFrame_EMAC(unsigned short Data) +void WriteFrame_EMAC( unsigned short Data ) { - *tptr++ = Data; + *tptr++ = Data; } // copies bytes from MCU-memory to frame port // NOTES: * an odd number of byte may only be transfered // if the frame is written to the end! // * MCU-memory MUST start at word-boundary - -void CopyToFrame_EMAC(void *Source, unsigned int Size) +void CopyToFrame_EMAC( void *Source, unsigned int Size ) { - unsigned short * piSource; - - piSource = Source; - Size = (Size + 1) & 0xFFFE; // round Size up to next even number - while (Size > 0) { - WriteFrame_EMAC(*piSource++); - Size -= 2; - } + unsigned short *piSource; + + piSource = Source; + Size = ( Size + 1 ) & 0xFFFE; // round Size up to next even number + while( Size > 0 ) + { + WriteFrame_EMAC( *piSource++ ); + Size -= 2; + } } -void DoSend_EMAC(unsigned short FrameSize) +void DoSend_EMAC( unsigned short FrameSize ) { - unsigned int idx; + unsigned int idx; + + idx = MAC_TXPRODUCEINDEX; + TX_DESC_CTRL( idx ) = FrameSize | TCTRL_LAST; + if( ++idx == NUM_TX_FRAG ) + { + idx = 0; + } - idx = MAC_TXPRODUCEINDEX; - TX_DESC_CTRL(idx) = FrameSize | TCTRL_LAST; - if (++idx == NUM_TX_FRAG) idx = 0; - MAC_TXPRODUCEINDEX = idx; + MAC_TXPRODUCEINDEX = idx; } void vEMAC_ISR( void ) { -portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; + portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; - /* Clear the interrupt. */ - MAC_INTCLEAR = 0xffff; + /* Clear the interrupt. */ + MAC_INTCLEAR = 0xffff; - /* Ensure the uIP task is not blocked as data has arrived. */ - xSemaphoreGiveFromISR( xEMACSemaphore, &xHigherPriorityTaskWoken ); + /* Ensure the uIP task is not blocked as data has arrived. */ + xSemaphoreGiveFromISR( xEMACSemaphore, &xHigherPriorityTaskWoken ); - portEND_SWITCHING_ISR( xHigherPriorityTaskWoken ); + portEND_SWITCHING_ISR( xHigherPriorityTaskWoken ); } diff --git a/Demo/CORTEX_LPC1766_GCC_RedSuite/RTOSDemo/webserver/httpd-cgi.c b/Demo/CORTEX_LPC1766_GCC_RedSuite/RTOSDemo/webserver/httpd-cgi.c index 2eb3dfc84..827a8b4a7 100644 --- a/Demo/CORTEX_LPC1766_GCC_RedSuite/RTOSDemo/webserver/httpd-cgi.c +++ b/Demo/CORTEX_LPC1766_GCC_RedSuite/RTOSDemo/webserver/httpd-cgi.c @@ -54,6 +54,8 @@ #include #include +#include "LED.h" + HTTPD_CGI_CALL(file, "file-stats", file_stats); HTTPD_CGI_CALL(tcp, "tcp-connections", tcp_stats); HTTPD_CGI_CALL(net, "net-stats", net_stats); @@ -234,35 +236,27 @@ PT_THREAD(rtos_stats(struct httpd_state *s, char *ptr)) } /*---------------------------------------------------------------------------*/ -char *pcStatus[ 3 ]; +char *pcStatus; unsigned long ulString; -extern unsigned long uxParTextGetLED( unsigned long uxLED ); static unsigned short generate_io_state( void *arg ) { ( void ) arg; - -// for( ulString = 0; ulString < 3; ulString++ ) -// { -// if( uxParTextGetLED( ulString + 5 ) ) -// { -// pcStatus[ ulString ] = "checked"; -// } -// else -// { -// pcStatus[ ulString ] = ""; -// } -// } + + if( lGetLEDState( 1 << 7 ) == 0 ) + { + pcStatus = ""; + } + else + { + pcStatus = "checked"; + } sprintf( uip_appdata, - "LED 2.5,"\ - "LED 2.6,"\ - "LED 2.7"\ + "LED 7"\ "

"\ "", - pcStatus[ 0 ], - pcStatus[ 1 ], - pcStatus[ 2 ] ); + pcStatus ); return strlen( uip_appdata ); } diff --git a/Demo/CORTEX_LPC1766_GCC_RedSuite/RTOSDemo/webserver/httpd.c b/Demo/CORTEX_LPC1766_GCC_RedSuite/RTOSDemo/webserver/httpd.c index 644cf16b7..c416cc1c8 100644 --- a/Demo/CORTEX_LPC1766_GCC_RedSuite/RTOSDemo/webserver/httpd.c +++ b/Demo/CORTEX_LPC1766_GCC_RedSuite/RTOSDemo/webserver/httpd.c @@ -270,8 +270,8 @@ PT_THREAD(handle_input(struct httpd_state *s)) /* Process any form input being sent to the server. */ { - extern void vApplicationProcessFormInput( char *pcInputString, long xInputLength ); - vApplicationProcessFormInput( s->inputbuf, PSOCK_DATALEN(&s->sin) ); + extern void vApplicationProcessFormInput( char *pcInputString ); + vApplicationProcessFormInput( s->inputbuf ); } strncpy(s->filename, &s->inputbuf[0], sizeof(s->filename)); diff --git a/Demo/CORTEX_LPC1766_GCC_RedSuite/RTOSDemo/webserver/uIP_Task.c b/Demo/CORTEX_LPC1766_GCC_RedSuite/RTOSDemo/webserver/uIP_Task.c index a2b02d21f..b1cb319f6 100644 --- a/Demo/CORTEX_LPC1766_GCC_RedSuite/RTOSDemo/webserver/uIP_Task.c +++ b/Demo/CORTEX_LPC1766_GCC_RedSuite/RTOSDemo/webserver/uIP_Task.c @@ -48,6 +48,7 @@ http://www.OpenRTOS.com - Commercial support, development, porting, licensing and training services. */ + /* Standard includes. */ #include @@ -65,9 +66,8 @@ /* Demo includes. */ #include "emac.h" -//#include "partest.h" +#include "LED.h" -//#include "LPC17xx_defs.h" #include "LPC17xx.h" #include "core_cm3.h" /*-----------------------------------------------------------*/ @@ -82,7 +82,6 @@ #define uipTOTAL_FRAME_HEADER_SIZE 54 -#define MAC_INTENABLE (*(volatile unsigned long *)(EMAC_BASE + 0xFE4)) /* Interrupt enable reg */ /*-----------------------------------------------------------*/ /* @@ -275,12 +274,12 @@ struct uip_eth_addr xAddr; } /*-----------------------------------------------------------*/ -void vApplicationProcessFormInput( portCHAR *pcInputString, portBASE_TYPE xInputLength ) +void vApplicationProcessFormInput( portCHAR *pcInputString ) { char *c, *pcText; static portCHAR cMessageForDisplay[ 32 ]; extern xQueueHandle xLCDQueue; -//xLCDMessage xLCDMessage; +xLCDMessage xLCDMessage; /* Process the form input sent by the IO page of the served HTML. */ @@ -290,31 +289,15 @@ extern xQueueHandle xLCDQueue; /* Turn LED's on or off in accordance with the check box status. */ if( strstr( c, "LED0=1" ) != NULL ) { -// vParTestSetLED( 5, 0 ); + /* Set LED7. */ + vSetLEDState( 1 << 7, 1 ); } else { -// vParTestSetLED( 5, 1 ); + /* Clear LED7. */ + vSetLEDState( 1 << 7, 0 ); } - if( strstr( c, "LED1=1" ) != NULL ) - { -// vParTestSetLED( 6, 0 ); - } - else - { -// vParTestSetLED( 6, 1 ); - } - - if( strstr( c, "LED2=1" ) != NULL ) - { -// vParTestSetLED( 7, 0 ); - } - else - { -// vParTestSetLED( 7, 1 ); - } - /* Find the start of the text to be displayed on the LCD. */ pcText = strstr( c, "LCD=" ); pcText += strlen( "LCD=" ); @@ -336,10 +319,9 @@ extern xQueueHandle xLCDQueue; } /* Write the message to the LCD. */ -// strcpy( cMessageForDisplay, pcText ); -// xLCDMessage.xColumn = 0; -// xLCDMessage.pcMessage = cMessageForDisplay; -// xQueueSend( xLCDQueue, &xLCDMessage, portMAX_DELAY ); + strcpy( cMessageForDisplay, pcText ); + xLCDMessage.pcMessage = cMessageForDisplay; + xQueueSend( xLCDQueue, &xLCDMessage, portMAX_DELAY ); } } -- 2.39.5