]> git.sur5r.net Git - freertos/commitdiff
Add run-time stats to the Kintex7 Microblaze demo.
authorrtel <rtel@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Mon, 19 Jan 2015 13:34:26 +0000 (13:34 +0000)
committerrtel <rtel@1d2547de-c912-0410-9cb9-b8ca96c0e9e2>
Mon, 19 Jan 2015 13:34:26 +0000 (13:34 +0000)
git-svn-id: https://svn.code.sf.net/p/freertos/code/trunk@2327 1d2547de-c912-0410-9cb9-b8ca96c0e9e2

FreeRTOS/Demo/MicroBlaze_Kintex7_EthernetLite/RTOSDemo/src/FreeRTOSConfig.h
FreeRTOS/Demo/MicroBlaze_Kintex7_EthernetLite/RTOSDemo/src/Full_Demo/main_full.c
FreeRTOS/Demo/MicroBlaze_Kintex7_EthernetLite/RTOSDemo/src/main.c
FreeRTOS/Demo/MicroBlaze_Kintex7_EthernetLite/RTOSDemo/src/printf-stdarg.c [new file with mode: 0644]
FreeRTOS/Demo/MicroBlaze_Kintex7_EthernetLite/RTOSDemo/src/serial.c

index e1ee403d59a4f19c603e3338f0cf1ecef5b0abe7..ae22e5c227d1cfe784e338a04c9d646911d29a84 100644 (file)
@@ -106,9 +106,9 @@ this demo on the FreeRTOS.org web site for more information. */
 \r
 /* Constants that describe the hardware and memory usage. */\r
 #define configCPU_CLOCK_HZ                                             ( Not used in this demo as it is determined by the hardware )\r
-#define configMINIMAL_STACK_SIZE                               ( ( uint16_t ) 220 )\r
-#define configTOTAL_HEAP_SIZE                                  ( ( size_t ) ( 50 * 1024 ) ) /* No effect if heap_3.c is used. */\r
-#define configMAX_TASK_NAME_LEN                                        ( 12 )\r
+#define configMINIMAL_STACK_SIZE                               ( ( uint16_t ) 170 )\r
+#define configTOTAL_HEAP_SIZE                                  ( ( size_t ) ( 80 * 1024 ) ) /* No effect if heap_3.c is used. */\r
+#define configMAX_TASK_NAME_LEN                                        ( 10 )\r
 \r
 /* Constants that build features in or out. */\r
 #define configUSE_MUTEXES                                              1\r
@@ -133,8 +133,8 @@ this demo on the FreeRTOS.org web site for more information. */
 \r
 /* Constants related to the generation of run time stats. */\r
 #define configGENERATE_RUN_TIME_STATS                  1\r
-#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() vMainConfigTimerForRunTimeStats(); /* Only used when configGENERATE_RUN_TIME_STATS is 1. */\r
-#define portGET_RUN_TIME_COUNTER_VALUE()               ulMainGetRunTimeCounterValue();         /* Only used when configGENERATE_RUN_TIME_STATS is 1. */\r
+#define portCONFIGURE_TIMER_FOR_RUN_TIME_STATS() /* Only used when configGENERATE_RUN_TIME_STATS is 1.  In this case the timer is setup when the tick timer is set up. */\r
+#define portGET_RUN_TIME_COUNTER_VALUE() ulMainGetRunTimeCounterValue()         /* Only used when configGENERATE_RUN_TIME_STATS is 1. */\r
 \r
 /* Software timer definitions. */\r
 #define configUSE_TIMERS                                               1\r
@@ -175,11 +175,10 @@ are multiple command interpreters running at once (for example, one on a UART
 and one on TCP/IP).  This is done to prevent an output buffer being defined by\r
 each implementation - which would waste RAM.  In this case, there is only one\r
 command interpreter running. */\r
-#define configCOMMAND_INT_MAX_OUTPUT_SIZE 1024\r
+#define configCOMMAND_INT_MAX_OUTPUT_SIZE 2048\r
 \r
 /* Prevent the function prototypes being included from asm files. */\r
 #ifndef __ASSEMBLER__\r
-       void vMainConfigTimerForRunTimeStats( void );\r
        uint32_t ulMainGetRunTimeCounterValue( void );\r
        void vAssertCalled( const char * pcFile, unsigned long ulLine );\r
 #endif\r
index 7c1532f0940390de877c0fc756c976af9250fb48..e1b15a5d021efb380c8575301c1d7113e5d77650 100644 (file)
 #define mainBLOCK_Q_PRIORITY                           ( tskIDLE_PRIORITY + 2UL )\r
 #define mainCREATOR_TASK_PRIORITY                      ( tskIDLE_PRIORITY + 3UL )\r
 #define mainFLOP_TASK_PRIORITY                         ( tskIDLE_PRIORITY )\r
-#define mainUART_COMMAND_CONSOLE_STACK_SIZE    ( configMINIMAL_STACK_SIZE * 3UL )\r
+#define mainUART_COMMAND_CONSOLE_STACK_SIZE    ( configMINIMAL_STACK_SIZE * 2UL )\r
 #define mainCOM_TEST_TASK_PRIORITY                     ( tskIDLE_PRIORITY + 2 )\r
 #define mainCHECK_TASK_PRIORITY                                ( configMAX_PRIORITIES - 1 )\r
 #define mainQUEUE_OVERWRITE_PRIORITY           ( tskIDLE_PRIORITY )\r
index cdbdcd44d6ccd7df57d847028509bc6d4e6a37ca..fcd21298ef8f7654b2c1dd6d40fa773c26824310 100644 (file)
@@ -84,8 +84,6 @@
  *\r
  */\r
 \r
-#warning Try reducing minimal stack size.\r
-\r
 /* Standard includes. */\r
 #include <stdio.h>\r
 #include <limits.h>\r
@@ -136,8 +134,9 @@ void vApplicationIdleHook( void );
 void vApplicationStackOverflowHook( TaskHandle_t pxTask, char *pcTaskName );\r
 void vApplicationTickHook( void );\r
 \r
-/* The dual timer is used to generate the RTOS tick interrupt. */\r
-static XTmrCtr xDualTimerInstance;\r
+/* The dual timer is used to generate the RTOS tick interrupt and as a time base\r
+for the run time stats. */\r
+static XTmrCtr xTickTimerInstance;\r
 \r
 /*-----------------------------------------------------------*/\r
 \r
@@ -165,10 +164,6 @@ int main( void )
 \r
 static void prvSetupHardware( void )\r
 {\r
-#warning Stacks are in BRAM.\r
-#warning Caches are disabled.\r
-//     init_platform();\r
-\r
        microblaze_disable_interrupts();\r
 \r
        #if defined( XPAR_MICROBLAZE_USE_ICACHE ) && ( XPAR_MICROBLAZE_USE_ICACHE != 0 )\r
@@ -275,12 +270,13 @@ below declares as an extern. */
 void vApplicationSetupTimerInterrupt( void )\r
 {\r
 portBASE_TYPE xStatus;\r
-const unsigned char ucTimerCounterNumber = ( unsigned char ) 0U;\r
+const unsigned char ucTickTimerCounterNumber = ( unsigned char ) 0U;\r
+const unsigned char ucRunTimeStatsCounterNumber = ( unsigned char ) 1U;\r
 const unsigned long ulCounterValue = ( ( XPAR_TMRCTR_0_CLOCK_FREQ_HZ / configTICK_RATE_HZ ) - 1UL );\r
 extern void vPortTickISR( void *pvUnused );\r
 \r
        /* Initialise the timer/counter. */\r
-       xStatus = XTmrCtr_Initialize( &xDualTimerInstance, XPAR_TMRCTR_0_DEVICE_ID );\r
+       xStatus = XTmrCtr_Initialize( &xTickTimerInstance, XPAR_TMRCTR_0_DEVICE_ID );\r
 \r
        if( xStatus == XST_SUCCESS )\r
        {\r
@@ -298,19 +294,29 @@ extern void vPortTickISR( void *pvUnused );
                vPortEnableInterrupt( XPAR_INTC_0_TMRCTR_0_VEC_ID );\r
 \r
                /* Configure the timer interrupt handler. */\r
-               XTmrCtr_SetHandler( &xDualTimerInstance, ( void * ) vPortTickISR, NULL );\r
+               XTmrCtr_SetHandler( &xTickTimerInstance, ( void * ) vPortTickISR, NULL );\r
 \r
                /* Set the correct period for the timer. */\r
-               XTmrCtr_SetResetValue( &xDualTimerInstance, ucTimerCounterNumber, ulCounterValue );\r
+               XTmrCtr_SetResetValue( &xTickTimerInstance, ucTickTimerCounterNumber, ulCounterValue );\r
 \r
                /* Enable the interrupts.  Auto-reload mode is used to generate a\r
                periodic tick.  Note that interrupts are disabled when this function is\r
                called, so interrupts will not start to be processed until the first\r
                task has started to run. */\r
-               XTmrCtr_SetOptions( &xDualTimerInstance, ucTimerCounterNumber, ( XTC_INT_MODE_OPTION | XTC_AUTO_RELOAD_OPTION | XTC_DOWN_COUNT_OPTION ) );\r
+               XTmrCtr_SetOptions( &xTickTimerInstance, ucTickTimerCounterNumber, ( XTC_INT_MODE_OPTION | XTC_AUTO_RELOAD_OPTION | XTC_DOWN_COUNT_OPTION ) );\r
+\r
+               /* Start the timer. */\r
+               XTmrCtr_Start( &xTickTimerInstance, ucTickTimerCounterNumber );\r
+\r
+\r
+\r
+\r
+               /* The second timer is used as the time base for the run time stats.\r
+               Auto-reload mode is used to ensure the timer does not stop. */\r
+               XTmrCtr_SetOptions( &xTickTimerInstance, ucRunTimeStatsCounterNumber, XTC_AUTO_RELOAD_OPTION );\r
 \r
                /* Start the timer. */\r
-               XTmrCtr_Start( &xDualTimerInstance, ucTimerCounterNumber );\r
+               XTmrCtr_Start( &xTickTimerInstance, ucRunTimeStatsCounterNumber );\r
        }\r
 \r
        /* Sanity check that the function executed as expected. */\r
@@ -344,12 +350,20 @@ void *malloc( size_t x )
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-void vMainConfigTimerForRunTimeStats( void )\r
-{\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
 uint32_t ulMainGetRunTimeCounterValue( void )\r
 {\r
-       return 0;\r
+static uint32_t ulOverflows = 0, ulLastTime = 0;\r
+uint32_t ulTimeNow, ulReturn;\r
+const uint32_t ulPrescale = 10, ulTCR2Offset = 24UL;\r
+\r
+       ulTimeNow = * ( ( uint32_t * ) ( XPAR_TMRCTR_0_BASEADDR + ulTCR2Offset ) );\r
+\r
+       if( ulTimeNow < ulLastTime )\r
+       {\r
+               ulOverflows += ( 1UL << ulPrescale );\r
+       }\r
+\r
+       ulReturn = ( ulTimeNow >> ulPrescale ) + ulOverflows;\r
+\r
+       return ulReturn;\r
 }\r
diff --git a/FreeRTOS/Demo/MicroBlaze_Kintex7_EthernetLite/RTOSDemo/src/printf-stdarg.c b/FreeRTOS/Demo/MicroBlaze_Kintex7_EthernetLite/RTOSDemo/src/printf-stdarg.c
new file mode 100644 (file)
index 0000000..1175198
--- /dev/null
@@ -0,0 +1,285 @@
+/*\r
+       Copyright 2001, 2002 Georges Menie (www.menie.org)\r
+       stdarg version contributed by Christian Ettinger\r
+\r
+    This program is free software; you can redistribute it and/or modify\r
+    it under the terms of the GNU Lesser General Public License as published by\r
+    the Free Software Foundation; either version 2 of the License, or\r
+    (at your option) any later version.\r
+\r
+    This program is distributed in the hope that it will be useful,\r
+    but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+    GNU Lesser General Public License for more details.\r
+\r
+    You should have received a copy of the GNU Lesser General Public License\r
+    along with this program; if not, write to the Free Software\r
+    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\r
+*/\r
+\r
+/*\r
+       putchar is the only external dependency for this file,\r
+       if you have a working putchar, leave it commented out.\r
+       If not, uncomment the define below and\r
+       replace outbyte(c) by your own function call.\r
+\r
+*/\r
+\r
+#define putchar(c) c\r
+\r
+#include <stdarg.h>\r
+\r
+static void printchar(char **str, int c)\r
+{\r
+       //extern int putchar(int c);\r
+       \r
+       if (str) {\r
+               **str = (char)c;\r
+               ++(*str);\r
+       }\r
+       else\r
+       { \r
+               (void)putchar(c);\r
+       }\r
+}\r
+\r
+#define PAD_RIGHT 1\r
+#define PAD_ZERO 2\r
+\r
+static int prints(char **out, const char *string, int width, int pad)\r
+{\r
+       register int pc = 0, padchar = ' ';\r
+\r
+       if (width > 0) {\r
+               register int len = 0;\r
+               register const char *ptr;\r
+               for (ptr = string; *ptr; ++ptr) ++len;\r
+               if (len >= width) width = 0;\r
+               else width -= len;\r
+               if (pad & PAD_ZERO) padchar = '0';\r
+       }\r
+       if (!(pad & PAD_RIGHT)) {\r
+               for ( ; width > 0; --width) {\r
+                       printchar (out, padchar);\r
+                       ++pc;\r
+               }\r
+       }\r
+       for ( ; *string ; ++string) {\r
+               printchar (out, *string);\r
+               ++pc;\r
+       }\r
+       for ( ; width > 0; --width) {\r
+               printchar (out, padchar);\r
+               ++pc;\r
+       }\r
+\r
+       return pc;\r
+}\r
+\r
+/* the following should be enough for 32 bit int */\r
+#define PRINT_BUF_LEN 12\r
+\r
+static int printi(char **out, int i, int b, int sg, int width, int pad, int letbase)\r
+{\r
+       char print_buf[PRINT_BUF_LEN];\r
+       register char *s;\r
+       register int t, neg = 0, pc = 0;\r
+       register unsigned int u = (unsigned int)i;\r
+\r
+       if (i == 0) {\r
+               print_buf[0] = '0';\r
+               print_buf[1] = '\0';\r
+               return prints (out, print_buf, width, pad);\r
+       }\r
+\r
+       if (sg && b == 10 && i < 0) {\r
+               neg = 1;\r
+               u = (unsigned int)-i;\r
+       }\r
+\r
+       s = print_buf + PRINT_BUF_LEN-1;\r
+       *s = '\0';\r
+\r
+       while (u) {\r
+               t = (unsigned int)u % b;\r
+               if( t >= 10 )\r
+                       t += letbase - '0' - 10;\r
+               *--s = (char)(t + '0');\r
+               u /= b;\r
+       }\r
+\r
+       if (neg) {\r
+               if( width && (pad & PAD_ZERO) ) {\r
+                       printchar (out, '-');\r
+                       ++pc;\r
+                       --width;\r
+               }\r
+               else {\r
+                       *--s = '-';\r
+               }\r
+       }\r
+\r
+       return pc + prints (out, s, width, pad);\r
+}\r
+\r
+static int print( char **out, const char *format, va_list args )\r
+{\r
+       register int width, pad;\r
+       register int pc = 0;\r
+       char scr[2];\r
+\r
+       for (; *format != 0; ++format) {\r
+               if (*format == '%') {\r
+                       ++format;\r
+                       width = pad = 0;\r
+                       if (*format == '\0') break;\r
+                       if (*format == '%') goto out;\r
+                       if (*format == '-') {\r
+                               ++format;\r
+                               pad = PAD_RIGHT;\r
+                       }\r
+                       while (*format == '0') {\r
+                               ++format;\r
+                               pad |= PAD_ZERO;\r
+                       }\r
+                       for ( ; *format >= '0' && *format <= '9'; ++format) {\r
+                               width *= 10;\r
+                               width += *format - '0';\r
+                       }\r
+                       if( *format == 's' ) {\r
+                               register char *s = (char *)va_arg( args, int );\r
+                               pc += prints (out, s?s:"(null)", width, pad);\r
+                               continue;\r
+                       }\r
+                       if( *format == 'd' ) {\r
+                               pc += printi (out, va_arg( args, int ), 10, 1, width, pad, 'a');\r
+                               continue;\r
+                       }\r
+                       if( *format == 'x' ) {\r
+                               pc += printi (out, va_arg( args, int ), 16, 0, width, pad, 'a');\r
+                               continue;\r
+                       }\r
+                       if( *format == 'X' ) {\r
+                               pc += printi (out, va_arg( args, int ), 16, 0, width, pad, 'A');\r
+                               continue;\r
+                       }\r
+                       if( *format == 'u' ) {\r
+                               pc += printi (out, va_arg( args, int ), 10, 0, width, pad, 'a');\r
+                               continue;\r
+                       }\r
+                       if( *format == 'c' ) {\r
+                               /* char are converted to int then pushed on the stack */\r
+                               scr[0] = (char)va_arg( args, int );\r
+                               scr[1] = '\0';\r
+                               pc += prints (out, scr, width, pad);\r
+                               continue;\r
+                       }\r
+               }\r
+               else {\r
+               out:\r
+                       printchar (out, *format);\r
+                       ++pc;\r
+               }\r
+       }\r
+       if (out) **out = '\0';\r
+       va_end( args );\r
+       return pc;\r
+}\r
+\r
+int printf(const char *format, ...)\r
+{\r
+        va_list args;\r
+        \r
+        va_start( args, format );\r
+        return print( 0, format, args );\r
+}\r
+\r
+int sprintf(char *out, const char *format, ...)\r
+{\r
+        va_list args;\r
+        \r
+        va_start( args, format );\r
+        return print( &out, format, args );\r
+}\r
+\r
+\r
+int snprintf( char *buf, unsigned int count, const char *format, ... )\r
+{\r
+        va_list args;\r
+        \r
+        ( void ) count;\r
+        \r
+        va_start( args, format );\r
+        return print( &buf, format, args );\r
+}\r
+\r
+\r
+#ifdef TEST_PRINTF\r
+int main(void)\r
+{\r
+       char *ptr = "Hello world!";\r
+       char *np = 0;\r
+       int i = 5;\r
+       unsigned int bs = sizeof(int)*8;\r
+       int mi;\r
+       char buf[80];\r
+\r
+       mi = (1 << (bs-1)) + 1;\r
+       printf("%s\n", ptr);\r
+       printf("printf test\n");\r
+       printf("%s is null pointer\n", np);\r
+       printf("%d = 5\n", i);\r
+       printf("%d = - max int\n", mi);\r
+       printf("char %c = 'a'\n", 'a');\r
+       printf("hex %x = ff\n", 0xff);\r
+       printf("hex %02x = 00\n", 0);\r
+       printf("signed %d = unsigned %u = hex %x\n", -3, -3, -3);\r
+       printf("%d %s(s)%", 0, "message");\r
+       printf("\n");\r
+       printf("%d %s(s) with %%\n", 0, "message");\r
+       sprintf(buf, "justif: \"%-10s\"\n", "left"); printf("%s", buf);\r
+       sprintf(buf, "justif: \"%10s\"\n", "right"); printf("%s", buf);\r
+       sprintf(buf, " 3: %04d zero padded\n", 3); printf("%s", buf);\r
+       sprintf(buf, " 3: %-4d left justif.\n", 3); printf("%s", buf);\r
+       sprintf(buf, " 3: %4d right justif.\n", 3); printf("%s", buf);\r
+       sprintf(buf, "-3: %04d zero padded\n", -3); printf("%s", buf);\r
+       sprintf(buf, "-3: %-4d left justif.\n", -3); printf("%s", buf);\r
+       sprintf(buf, "-3: %4d right justif.\n", -3); printf("%s", buf);\r
+\r
+       return 0;\r
+}\r
+\r
+/*\r
+ * if you compile this file with\r
+ *   gcc -Wall $(YOUR_C_OPTIONS) -DTEST_PRINTF -c printf.c\r
+ * you will get a normal warning:\r
+ *   printf.c:214: warning: spurious trailing `%' in format\r
+ * this line is testing an invalid % at the end of the format string.\r
+ *\r
+ * this should display (on 32bit int machine) :\r
+ *\r
+ * Hello world!\r
+ * printf test\r
+ * (null) is null pointer\r
+ * 5 = 5\r
+ * -2147483647 = - max int\r
+ * char a = 'a'\r
+ * hex ff = ff\r
+ * hex 00 = 00\r
+ * signed -3 = unsigned 4294967293 = hex fffffffd\r
+ * 0 message(s)\r
+ * 0 message(s) with %\r
+ * justif: "left      "\r
+ * justif: "     right"\r
+ *  3: 0003 zero padded\r
+ *  3: 3    left justif.\r
+ *  3:    3 right justif.\r
+ * -3: -003 zero padded\r
+ * -3: -3   left justif.\r
+ * -3:   -3 right justif.\r
+ */\r
+\r
+#endif\r
+\r
+\r
+\r
index c2694c613361e2f513e9eafea8a06698137bb083..0c9cbce02d695cbb9102c64661f0e7e8a69848a3 100644 (file)
@@ -79,6 +79,7 @@
 \r
 /* Scheduler includes. */\r
 #include "FreeRTOS.h"\r
+#include "task.h"\r
 #include "queue.h"\r
 #include "comtest_strings.h"\r
 \r
@@ -103,6 +104,10 @@ static XUartLite xUartLiteInstance;
 /* The queue used to hold received characters. */\r
 static QueueHandle_t xRxedChars;\r
 \r
+/* Holds the handle of a task performing a Tx so it can be notified of when\r
+the Tx has completed. */\r
+static TaskHandle_t xUARTSendingTask = NULL;\r
+\r
 /*-----------------------------------------------------------*/\r
 \r
 xComPortHandle xSerialPortInitMinimal( unsigned long ulWantedBaud, unsigned portBASE_TYPE uxQueueLength )\r
@@ -182,20 +187,40 @@ portBASE_TYPE xReturn;
 \r
 signed portBASE_TYPE xSerialPutChar( xComPortHandle pxPort, signed char cOutChar, TickType_t xBlockTime )\r
 {\r
+const TickType_t xMaxBlockTime = pdMS_TO_TICKS( 150UL );\r
+portBASE_TYPE xReturn;\r
+\r
        ( void ) pxPort;\r
        ( void ) xBlockTime;\r
 \r
+       /* Note this is the currently sending task. */\r
+       xUARTSendingTask = xTaskGetCurrentTaskHandle();\r
+\r
        XUartLite_Send( &xUartLiteInstance, ( unsigned char * ) &cOutChar, sizeof( cOutChar ) );\r
-       return pdPASS;\r
+\r
+       /* Wait in the Blocked state (so not using any CPU time) for the Tx to\r
+       complete. */\r
+       xReturn = ulTaskNotifyTake( pdTRUE, xMaxBlockTime );\r
+\r
+       return xReturn;\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
 void vSerialPutString( xComPortHandle pxPort, const signed char * const pcString, unsigned short usStringLength )\r
 {\r
+const TickType_t xMaxBlockTime = pdMS_TO_TICKS( 150UL );\r
+\r
        ( void ) pxPort;\r
 \r
+       /* Note this is the currently sending task. */\r
+       xUARTSendingTask = xTaskGetCurrentTaskHandle();\r
+\r
        /* Output uxStringLength bytes starting from pcString. */\r
        XUartLite_Send( &xUartLiteInstance, ( unsigned char * ) pcString, usStringLength );\r
+\r
+       /* Wait in the Blocked state (so not using any CPU time) for the Tx to\r
+       complete. */\r
+       ulTaskNotifyTake( pdTRUE, xMaxBlockTime );\r
 }\r
 /*-----------------------------------------------------------*/\r
 \r
@@ -225,14 +250,21 @@ portBASE_TYPE xHigherPriorityTaskWoken = pdFALSE;
 }\r
 /*-----------------------------------------------------------*/\r
 \r
-static void prvTxHandler( void *pvUnused, unsigned portBASE_TYPE uxByteCount )\r
+static void prvTxHandler( void *pvUnused, unsigned portBASE_TYPE uxUnused )\r
 {\r
+BaseType_t xHigherPriorityTaskWoken = NULL;\r
+\r
        ( void ) pvUnused;\r
-       ( void ) uxByteCount;\r
+       ( void ) uxUnused;\r
 \r
-       /* Nothing to do here.  The Xilinx library function takes care of the\r
-       transmission. */\r
-       portNOP();\r
+       /* Notify the sending that that the Tx has completed. */\r
+       if( xUARTSendingTask != NULL )\r
+       {\r
+               vTaskNotifyGiveFromISR( xUARTSendingTask, &xHigherPriorityTaskWoken );\r
+               xUARTSendingTask = NULL;\r
+       }\r
+\r
+       portYIELD_FROM_ISR( xHigherPriorityTaskWoken );\r
 }\r
 \r
 \r