Update XMOS xcore.ai port to be compatible with v11.x (#1096)

* Fix kexcept function

* Create dummy pxCurrentTCBs for xcore.ai port

* Additional commentary

* Add a layer of indirection to cope with singlecore

* Clarify use of _DoException
diff --git a/portable/ThirdParty/xClang/XCOREAI/port.c b/portable/ThirdParty/xClang/XCOREAI/port.c
index ba4598b..ac12aa3 100644
--- a/portable/ThirdParty/xClang/XCOREAI/port.c
+++ b/portable/ThirdParty/xClang/XCOREAI/port.c
@@ -12,6 +12,15 @@
 
 uint32_t ulPortYieldRequired[ portMAX_CORE_COUNT ] = { pdFALSE };
 
+/* When this port was designed, it was assumed that pxCurrentTCBs would always
+   exist and that it would always be an array containing pointers to the current
+   TCBs for each core. In v11, this is not the case; if we are only running one
+   core, the symbol is pxCurrentTCB instead. Therefore, this port adds a layer
+   of indirection - we populate this pointer-to-pointer in the RTOS kernel entry
+   function below. This makes this port agnostic to whether it is running on SMP
+   or singlecore RTOS. */
+void ** xcorePvtTCBContainer;
+
 /*-----------------------------------------------------------*/
 
 void vIntercoreInterruptISR( void )
@@ -140,6 +149,28 @@
     }
     #endif
 
+    /* Populate the TCBContainer depending on whether we're singlecore or SMP */
+    #if ( configNUMBER_OF_CORES == 1 )
+    {
+        asm volatile (
+            "ldaw %0, dp[pxCurrentTCB]\n\t"
+            : "=r"(xcorePvtTCBContainer)
+            : /* no inputs */
+            : /* no clobbers */
+            );
+    }
+    #else
+    {
+        asm volatile (
+            "ldaw %0, dp[pxCurrentTCBs]\n\t"
+            : "=r"(xcorePvtTCBContainer)
+            : /* no inputs */
+            : /* no clobbers */
+            );
+    }
+
+    #endif
+
     debug_printf( "FreeRTOS Core %d initialized\n", xCoreID );
 
     /*
@@ -147,8 +178,8 @@
      * to run and jump into it.
      */
     asm volatile (
-        "mov r6, %0\n\t"                 /* R6 must be the FreeRTOS core ID*/
-        "ldaw r5, dp[pxCurrentTCBs]\n\t" /* R5 must be the TCB list which is indexed by R6 */
+        "mov r6, %0\n\t"                       /* R6 must be the FreeRTOS core ID. In singlecore this is always 0. */
+        "ldw r5, dp[xcorePvtTCBContainer]\n\t" /* R5 must be the TCB list which is indexed by R6 */
         "bu _freertos_restore_ctx\n\t"
         :                                /* no outputs */
         : "r" ( xCoreID )
diff --git a/portable/ThirdParty/xClang/XCOREAI/portasm.S b/portable/ThirdParty/xClang/XCOREAI/portasm.S
index 7445672..64b7b9d 100644
--- a/portable/ThirdParty/xClang/XCOREAI/portasm.S
+++ b/portable/ThirdParty/xClang/XCOREAI/portasm.S
@@ -14,11 +14,8 @@
 .issue_mode dual
 .cc_top kexcept.function, kexcept
 kexcept:
-  ldc r11, 0x0008
-  shl r11, r11, 16
-  ldc r9, 0x0080
-  or  r11, r11, r9
-  bau r11 //_TrapHandler is at 0x00080080. TODO: Is it always? Why can't I access the symbol _TrapHandler?
+  bu _DoException       /* This symbol is generated by the toolchain and */
+                        /* provides graceful exception handling */
 
 _yield:
  {set    sp,     r4                  /* Restore the task's SP to save the rest of its context. */
@@ -123,7 +120,7 @@
   ldaw   r11,    sp[37]}
   vstc   r11[0]
 #endif
-  ldaw   r5,     dp[pxCurrentTCBs] /* Get the current TCB array into r5. */
+  ldw    r5,     dp[xcorePvtTCBContainer]
   ldw    r1,     r5[r0]            /* Get this core's current TCB pointer into r1. */
   stw    r4,     r1[0x0]           /* Save the current task's SP to the first */
                                    /* word (top of stack) in the current TCB. */