Index: /webserver/example/freeRTOSexample/Source/EnergyMeters/Meters.c =================================================================== --- /webserver/example/freeRTOSexample/Source/EnergyMeters/Meters.c (revision 19) +++ /webserver/example/freeRTOSexample/Source/EnergyMeters/Meters.c (revision 19) @@ -0,0 +1,107 @@ + +#include "FreeRTOS.h" +#include "semphr.h" +#include "task.h" + +#define metersSTACK_SIZE configMINIMAL_STACK_SIZE +/* masks for RTC */ +#define MASKSEC 0x3F // Second 00..59 00000000:00000000:00xxxxxx +#define MASKMIN 0x3F00 // Minute 00..59 00000000:00xxxxxx:00000000 +#define MASKHR 0x1F0000 // Hour 00..23 000xxxxx:00000000:00000000 + + +portBASE_TYPE Init_P2_0(void); +void basementGasCalculation(void); + +portLONG basementGasReading = 0; +portTickType basementGasLastTime = 0; + +/* The semaphore used to wake the Meters task when a pulse was received or the timer expired. */ +xSemaphoreHandle xMetersSemaphore = NULL; + +portTickType xLastMeterTaskRunTime; /* keeps the last time the meter calculation ran */ +portTickType xMeterIdleRate = 1000; /* the rate (in ticks = ms) at which the calculation runs when no pulses triggered a calculation */ + + + int rtcHOURS; + int rtcMINUTES; + int rtcSECONDS; +static portTASK_FUNCTION( vMeters_Task, pvParameters ) +{ + + + + vSemaphoreCreateBinary( xMetersSemaphore ); + + Init_P2_0(); /* init GPIO for meters */ + xLastMeterTaskRunTime = xTaskGetTickCount(); /* init last run time */ + + + for( ;; ) + { + + basementGasCalculation(); + + portENTER_CRITICAL(); + // example: do stuff + portEXIT_CRITICAL(); + + /* We did not receive a pulse, and there was no periodic + processing to perform. Block for a fixed period. If a pulse + is received during this period we will be woken by the ISR + giving us the Semaphore. */ + xLastMeterTaskRunTime = xTaskGetTickCount(); /* update last run time */ + + rtcHOURS = (RTC_CTIME0 & MASKHR)>>16; // Read Hour + rtcMINUTES = (RTC_CTIME0 & MASKMIN)>>8; // Read Minute + rtcSECONDS = RTC_CTIME0 & MASKSEC; // Read Second + + xSemaphoreTake( xMetersSemaphore, 1000 ); /* timeout 1 sec */ + + /* Yield in case cooperative scheduling is being used. */ + #if configUSE_PREEMPTION == 0 + { + taskYIELD(); + } + #endif + } +} + + + +void vStartMetersTask( unsigned portBASE_TYPE uxPriority ) +{ + + /* Spawn the task. */ + xTaskCreate( vMeters_Task, ( signed portCHAR * ) "Meters", metersSTACK_SIZE, NULL, uxPriority, ( xTaskHandle * ) NULL ); +} + +void vP2_0_ISR_Wrapper( void ); + +// configure port-pins for use with LAN-controller, +// reset it and send the configuration-sequence + +portBASE_TYPE Init_P2_0(void) +{ + // not needed yet : SCS |= 1; // Enable FAST GPIO + portBASE_TYPE xReturn = 1; // return value + + /* Enable Pins. */ + + PINSEL4 &= 0xfffff3ff; /* reset bit 20 and 21, P2.10 = GPIO Port 2.10 */ + PINMODE4 &= 0xfffff3ff; /* reset bit 20 and 21, enable on-chip pull-up resistor on Port 2.10 */ + IO2_INT_EN_R |= (1<<10); /* enable rising edge interrupt for P2:10 */ + IO2_INT_EN_F &= ~(1<<10); /* disable falling edge interrupt for P2:10 */ + + VICVectAddr17 = (portLONG) vP2_0_ISR_Wrapper; /* EINT-3 interrupt handler */ + + VICIntEnable |= (1<<17); /* Enable VIC index-17 (shared by EINT3 and GPIO) */ + + return xReturn; +} + + +void basementGasCalculation(void) +{ + +} Index: /webserver/example/freeRTOSexample/Source/EnergyMeters/Meters_ISRs.c =================================================================== --- /webserver/example/freeRTOSexample/Source/EnergyMeters/Meters_ISRs.c (revision 19) +++ /webserver/example/freeRTOSexample/Source/EnergyMeters/Meters_ISRs.c (revision 19) @@ -0,0 +1,60 @@ +#include "FreeRTOS.h" +#include "semphr.h" +#include "task.h" + +extern basementGasReading; +extern xMetersSemaphore; + +/* The interrupt entry point. */ +void vP2_0_ISR_Wrapper( void ) __attribute__((naked)); + +/* The function that actually performs the interrupt processing. This must be +separate to the wrapper to ensure the correct stack frame is set up. */ +void vP2_0_ISR_Handler( void ); + +void vP2_0_ISR_Handler( void ) +{ + portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE; + + if ((IO2_INT_STAT_R & (1 << 10)) != 0) /* P2.10 interrupt triggered */ + { + basementGasReading++; + } + // else if ((IO2_INT_STAT_R & (1 << n)) != 0) /* some other interrupt triggered */ + { + ; + } + + /* Clear the interrupt. */ + IO2_INT_CLR |= (1<<10); + VICVectAddr = 0; + + /* Unblock the Meters task as data has arrived. */ + xSemaphoreGiveFromISR( xMetersSemaphore, &xHigherPriorityTaskWoken ); + + if( xHigherPriorityTaskWoken ) + { + /* If the Meters task was unblocked then calling "Yield from ISR" here + will ensure the interrupt returns directly to the Meters task, if it + is the highest priority read task. */ + portYIELD_FROM_ISR(); + } +} +/*-----------------------------------------------------------*/ + +void vP2_0_ISR_Wrapper( void ) +{ + /* Save the context of the interrupted task. */ + portSAVE_CONTEXT(); + + /* Call the handler function. This must be separate from the wrapper + function to ensure the correct stack frame is set up. */ + vP2_0_ISR_Handler(); + + /* Restore the context of whichever task is going to run next. */ + portRESTORE_CONTEXT(); +} + + + + Index: /webserver/example/freeRTOSexample/Demo/ARM7_LPC2368_Rowley/RTOSDemo.hzs =================================================================== --- /webserver/example/freeRTOSexample/Demo/ARM7_LPC2368_Rowley/RTOSDemo.hzs (revision 17) +++ /webserver/example/freeRTOSexample/Demo/ARM7_LPC2368_Rowley/RTOSDemo.hzs (revision 19) @@ -20,10 +20,14 @@ + + + + - + - + @@ -41,23 +45,47 @@ - + + + + + - + - - + + + + + + + + + + - - + + - - + + + + + + + + + + + + + + - + Index: /webserver/example/freeRTOSexample/Demo/ARM7_LPC2368_Rowley/webserver/httpd-cgi.c =================================================================== --- /webserver/example/freeRTOSexample/Demo/ARM7_LPC2368_Rowley/webserver/httpd-cgi.c (revision 14) +++ /webserver/example/freeRTOSexample/Demo/ARM7_LPC2368_Rowley/webserver/httpd-cgi.c (revision 19) @@ -208,13 +208,19 @@ static char cCountBuf[ 32 ]; long lRefreshCount = 0; +extern basementGasReading; +extern rtcHOURS; +extern rtcMINUTES; +extern rtcSECONDS; static unsigned short generate_rtos_stats(void *arg) { - lRefreshCount++; - sprintf( cCountBuf, "


Refresh count = %d", lRefreshCount ); - vTaskList( uip_appdata ); - strcat( uip_appdata, cCountBuf ); - - return strlen( uip_appdata ); + lRefreshCount++; + + sprintf( cCountBuf, "


Refresh count = %d


Pulse Counter = %d at %02u:%02u:%02u", lRefreshCount, basementGasReading, rtcHOURS, rtcMINUTES, rtcSECONDS ); + strcat( uip_appdata, cCountBuf ); + vTaskList( uip_appdata ); + strcat( uip_appdata, cCountBuf ); + + return strlen( uip_appdata ); } /*---------------------------------------------------------------------------*/ Index: /webserver/example/freeRTOSexample/Demo/ARM7_LPC2368_Rowley/main.c =================================================================== --- /webserver/example/freeRTOSexample/Demo/ARM7_LPC2368_Rowley/main.c (revision 17) +++ /webserver/example/freeRTOSexample/Demo/ARM7_LPC2368_Rowley/main.c (revision 19) @@ -81,4 +81,7 @@ +void setRTC(void); +void startRTC(void); + /* * Checks the status of all the demo tasks then prints a message to the @@ -98,4 +101,9 @@ extern void vuIP_Task( void *pvParameters ); +/* + * The task that handles the electricity meter handling/calculations. + */ +extern void vMeters_Task( void *pvParameters ); + /* * The LCD is written two by more than one task so is controlled by a @@ -113,30 +121,35 @@ int main (void) { - /* Setup the led's on the MCB2300 board */ - vParTestInitialise(); - - /* 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 ) ); - - /* Create the lwIP task. This uses the lwIP RTOS abstraction layer.*/ - xTaskCreate( vuIP_Task, ( signed portCHAR * ) "uIP", mainBASIC_WEB_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY - 1, NULL ); - + startRTC(); /* start the RTC */ + + /* Setup the led's on the MCB2300 board */ + vParTestInitialise(); + + /* 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 ) ); + + /* Create the lwIP task. This uses the lwIP RTOS abstraction layer.*/ + xTaskCreate( vuIP_Task, ( signed portCHAR * ) "uIP", mainBASIC_WEB_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY - 1, NULL ); + +// vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY ); + vStartMetersTask( mainBLOCK_Q_PRIORITY ); /* Start the standard demo tasks. */ - vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY ); - vCreateBlockTimeTasks(); - vStartLEDFlashTasks( mainFLASH_PRIORITY ); - vStartSemaphoreTasks( mainSEM_TEST_PRIORITY ); - vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY ); - vStartIntegerMathTasks( mainINTEGER_TASK_PRIORITY ); +// vStartBlockingQueueTasks( mainBLOCK_Q_PRIORITY ); +// vCreateBlockTimeTasks(); + vStartLEDFlashTasks( mainFLASH_PRIORITY ); +// vStartSemaphoreTasks( mainSEM_TEST_PRIORITY ); +// vStartPolledQueueTasks( mainQUEUE_POLL_PRIORITY ); +// vStartIntegerMathTasks( mainINTEGER_TASK_PRIORITY ); /* Start the tasks defined within this file/specific to this demo. */ - xTaskCreate( vCheckTask, ( signed portCHAR * ) "Check", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY, NULL ); - xTaskCreate( vLCDTask, ( signed portCHAR * ) "LCD", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY - 1, NULL ); + // xTaskCreate( vCheckTask, ( signed portCHAR * ) "Check", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY, NULL ); + xTaskCreate( vLCDTask, ( signed portCHAR * ) "LCD", configMINIMAL_STACK_SIZE, NULL, mainCHECK_TASK_PRIORITY - 1, NULL ); /* The suicide tasks must be created last as they need to know how many tasks were running prior to their creation in order to ascertain whether or not the correct/expected number of tasks are running at any given time. */ - vCreateSuicidalTasks( mainCREATOR_TASK_PRIORITY ); + // vCreateSuicidalTasks( mainCREATOR_TASK_PRIORITY ); + /* Start the scheduler. */ @@ -245,6 +258,40 @@ } - - - - +void setRTC(void) +{ +/* + This function needs to be called when the RTC battery was replaces + + SEC 6 Seconds value in the range of 0 to 59 R/W 0xE002 4020 + MIN 6 Minutes value in the range of 0 to 59 R/W 0xE002 4024 + HOUR 5 Hours value in the range of 0 to 23 R/W 0xE002 4028 + DOM 5 Day of month value in the range of 1 to 28, 29, 30, + or 31 (depending on the month and whether it is a + leap year).[1] + R/W 0xE002 402C + DOW 3 Day of week value in the range of 0 to 6[1] R/W 0xE002 4030 + DOY 9 Day of year value in the range of 1 to 365 (366 for + leap years)[1] + R/W 0xE002 4034 + MONTH 4 Month value in the range of 1 to 12 R/W 0xE002 4038 + YEAR 12 Year value in the range of 0 to 4095 R/W 0xE002 403C +*/ + RTC_SEC = 00; + RTC_MIN = 22; + RTC_HOUR = 17; + RTC_DOM = 11; + RTC_DOW = 2-1; + RTC_DOY = 223; + RTC_MONTH = 8; + RTC_YEAR = 2009; +} + +void startRTC(void) +{ + // Initial RTC Function + RTC_CCR = 0; // Reset All Bit Control + RTC_CCR |= 0x00000010; // CLKSRC = 1 = Used EXT 32.768 KHz + RTC_CCR |= 0x00000002; // Reset Clock + RTC_CCR &= 0xFFFFFFFD; // Release Reset + RTC_CCR |= 0x00000001; // Start RTC Clock +} Index: /webserver/example/freeRTOSexample/Demo/ARM7_LPC2368_Rowley/RTOSDemo.hzp =================================================================== --- /webserver/example/freeRTOSexample/Demo/ARM7_LPC2368_Rowley/RTOSDemo.hzp (revision 17) +++ /webserver/example/freeRTOSexample/Demo/ARM7_LPC2368_Rowley/RTOSDemo.hzp (revision 19) @@ -2,5 +2,5 @@ - + @@ -45,5 +45,7 @@ - + + + @@ -58,5 +60,7 @@ - + + + @@ -98,4 +102,8 @@ + + + +