Coded basic unit test to test RM infrastructure
authorJustin Sobota <jsobota@ti.com>
Thu, 15 Nov 2012 23:19:25 +0000 (18:19 -0500)
committerJustin Sobota <jsobota@ti.com>
Thu, 15 Nov 2012 23:19:25 +0000 (18:19 -0500)
include/rm_transportloc.h
rm_osal.h
rm_transport.h
src/rm.c
src/rm_services.c
src/rm_transport.c
test/rm_osal.c [new file with mode: 0644]
test/rm_osal.h [new file with mode: 0644]
test/rm_test.c [new file with mode: 0644]
test/rm_test.cfg [new file with mode: 0644]

index 8b5f655e55b282339c47db5de17c9312fcc7ee67..b3a7209fbb231c6180378636e9d12f770f559f58 100644 (file)
@@ -56,6 +56,8 @@ extern "C" {
  *        as a Rm_TransportHandle
  */
 typedef struct {
+    /** The RM instance that this node belongs to */
+    Rm_Handle rmHandle;
     /** The remote RM instance type */
     Rm_InstType remoteInstType;
     /** The remote RM instance name */
index 63e0f7e615b6c58a9ffd69e1d1f09ec4a8f85dc3..92ddc1b7e78318a6d0cfa58cb22daae8846bd646 100644 (file)
--- a/rm_osal.h
+++ b/rm_osal.h
@@ -82,8 +82,6 @@
 
 extern void* Osal_rmMalloc (uint32_t num_bytes, bool shared);
 extern void Osal_rmFree (void *ptr, uint32_t size, bool shared);
-extern void* Osal_rmLocalCsEnter (void);
-extern void Osal_rmLocalCsExit (void *CsHandle);
 extern void* Osal_rmCsEnter (void);
 extern void Osal_rmCsExit (void *CsHandle);
 extern void* Osal_rmMtCsEnter (void);
@@ -136,45 +134,6 @@ extern void Osal_rmEndMemAccess (void *ptr, uint32_t size);
 
 #define Rm_osalFree               Osal_rmFree
 
-/**
- * @brief   The macro is used by the RM LLD to provide critical sections to 
- *    protect shared variables from access from multiple RM instances
- *    on a single core
- *
- * <b> Prototype: </b>
- *  The following is the C prototype for the expected OSAL API.
- *
- *  @verbatim
-       void* Osal_rmLocalCsEnter (void)
-    @endverbatim
- *      
- *  <b> Parameter </b>
- *  @n  None.
- *
- *  <b> Return Value </b>
- *  @n  Handle used to lock critical section.
- */
-#define Rm_osalLocalCsEnter            Osal_rmLocalCsEnter
-
-/**
- * @brief   The macro is used by the RM LLD to exit a critical section 
- *      protected using Osal_rmLocalCsEnter() API.
- *
- * <b> Prototype: </b>
- *  The following is the C prototype for the expected OSAL API.
- *
- *  @verbatim
-       void Osal_rmLocalCsExit (void *CsHandle)
-    @endverbatim
- *      
- *  <b> Parameter </b>
- *  @n  Handle for unlocking critical section.
- *
- *  <b> Return Value </b>
- *  @n  Not applicable.
- */
-#define Rm_osalLocalCsExit             Osal_rmLocalCsExit
-
 /**
  * @brief   The macro is used by the RM LLD to provide critical sections to 
  * protect global and shared variables from
index 8b736d4a63ba1a81292d810fb3551f740dad339c..d2906c6e9501d5b14ee22332fbfdd8fd588b2f4e 100644 (file)
@@ -283,10 +283,9 @@ Rm_TransportHandle Rm_transportRegister (Rm_Handle rmHandle,
 Rm_TransportResult Rm_transportUnregister (Rm_Handle rmHandle, 
                                            Rm_TransportHandle transportHandle);
 
-int32_t Rm_receivePktIsr(Rm_Handle rmHandle, Rm_TransportHandle transportHandle, 
-                         Rm_Packet *pkt);
+int32_t Rm_receivePktIsr(Rm_TransportHandle transportHandle, Rm_Packet *pkt);
 
-int32_t Rm_receivePktPolling(Rm_Handle rmHandle, Rm_TransportHandle transportHandle);
+int32_t Rm_receivePktPolling(Rm_TransportHandle transportHandle);
 
 
 /** 
index 5472ec790958fbf95c763cd3819e6f2d1461098d..28e58fcb1349c6b32a95f2c18fa2e44e5f98ac6a 100644 (file)
--- a/src/rm.c
+++ b/src/rm.c
@@ -82,7 +82,7 @@ Rm_Transaction *Rm_transactionQueueAdd(Rm_Inst *rmInst, uint32_t transactionId)
     void *key;\r
 \r
     /* Lock access to the RM instance's transaction queue */\r
-    key = Rm_osalLocalCsEnter();\r
+    key = Rm_osalCsEnter();\r
 \r
     /* Get memory for a new transaction from local memory */\r
     newTransaction = Rm_osalMalloc(sizeof(Rm_Transaction), false);\r
@@ -90,7 +90,7 @@ Rm_Transaction *Rm_transactionQueueAdd(Rm_Inst *rmInst, uint32_t transactionId)
     /* Return if the memory allocated for the transaction entry is NULL */\r
     if (newTransaction == NULL)\r
     {\r
-        Rm_osalLocalCsExit(key);\r
+        Rm_osalCsExit(key);\r
         return(newTransaction);\r
     }\r
 \r
@@ -123,7 +123,7 @@ Rm_Transaction *Rm_transactionQueueAdd(Rm_Inst *rmInst, uint32_t transactionId)
         rmInst->transactionQueue = newTransaction;\r
     }\r
 \r
-    Rm_osalLocalCsExit(key);\r
+    Rm_osalCsExit(key);\r
     return (newTransaction);\r
 }\r
 \r
@@ -158,12 +158,12 @@ int32_t Rm_transactionQueueDelete(Rm_Inst *rmInst, uint32_t transactionId)
     void *key;\r
 \r
     /* Lock access to the RM instance's transaction queue */\r
-    key = Rm_osalLocalCsEnter();\r
+    key = Rm_osalCsEnter();\r
 \r
     /* Make sure there is at least one entry in the transaction queue */\r
     if (transaction == NULL)\r
     {\r
-        Rm_osalLocalCsExit(key);\r
+        Rm_osalCsExit(key);\r
         return (RM_SERVICE_ERROR_NO_TRANSACTIONS_IN_QUEUE);\r
     }\r
 \r
@@ -183,7 +183,7 @@ int32_t Rm_transactionQueueDelete(Rm_Inst *rmInst, uint32_t transactionId)
     /* Traversed entire queue but did not find transaction */\r
     if (transaction == NULL)\r
     {\r
-        Rm_osalLocalCsExit(key);\r
+        Rm_osalCsExit(key);\r
         return (RM_SERVICE_ERROR_SERVICE_TRANSACTION_DOES_NOT_EXIST);\r
     }\r
     else\r
@@ -208,7 +208,7 @@ int32_t Rm_transactionQueueDelete(Rm_Inst *rmInst, uint32_t transactionId)
         Rm_osalFree((void *)transaction, sizeof(Rm_Transaction), false);\r
     }\r
 \r
-    Rm_osalLocalCsExit(key);\r
+    Rm_osalCsExit(key);\r
     return (RM_SERVICE_ACTION_OKAY);\r
 }\r
 \r
@@ -218,13 +218,13 @@ uint32_t Rm_transactionGetSequenceNum(Rm_Inst *rmInst)
     void *key;\r
 \r
     /* Lock access to the RM instance */\r
-    key = Rm_osalLocalCsEnter();\r
+    key = Rm_osalCsEnter();\r
 \r
     /* Get the next sequence number and then incement.  Overflow is okay since\r
      * it just restarts the sequence number count. */\r
     sequenceNum = rmInst->transactionSeqNum++;\r
 \r
-    Rm_osalLocalCsExit(key);\r
+    Rm_osalCsExit(key);\r
     return (sequenceNum);\r
 }\r
 \r
@@ -270,9 +270,9 @@ void Rm_transactionResponder (Rm_Inst *rmInst, Rm_Transaction *transaction,
     }\r
 \r
     /* Send the RM packet to the application transport */\r
-    if (rmInst->transport.rmSend((Rm_TransportHandle) dstTransportNode, rmPkt))\r
+    if (rmInst->transport.rmSend((Rm_TransportHandle) dstTransportNode, rmPkt) < RM_TRANSPORT_SUCCESSFUL)\r
     {\r
-        /* Non-NULL value returned by transport send.  An error occurred\r
+        /* Negative value returned by transport send.  An error occurred\r
          * in the transport while attempting to send the packet.*/\r
         receipt->serviceResult = RM_SERVICE_ERROR_TRANPSPORT_SEND_ERROR;\r
         /* Clean up the packet */\r
@@ -516,9 +516,9 @@ void Rm_transactionForwarder (Rm_Inst *rmInst, Rm_Transaction *transaction,
     transaction->state = Rm_transactionState_AWAITING_RESPONSE;\r
 \r
     /* Send the RM packet to the application transport */\r
-    if (rmInst->transport.rmSend((Rm_TransportHandle) dstTransportNode, rmPkt))\r
+    if (rmInst->transport.rmSend((Rm_TransportHandle) dstTransportNode, rmPkt) < RM_TRANSPORT_SUCCESSFUL)\r
     {\r
-        /* Non-NULL value returned by transport send.  An error occurred\r
+        /* Negative value returned by transport send.  An error occurred\r
          * in the transport while attempting to send the packet.*/\r
         receipt->serviceResult = RM_SERVICE_ERROR_TRANPSPORT_SEND_ERROR;\r
         /* Clean up the packet */\r
index 7e42870d817879d72127040048d652f93c5ae497..117d52ec340cf20f14e12b3cb03a5c6aedc261b3 100644 (file)
@@ -66,14 +66,14 @@ void Rm_serviceHandler (void *rmHandle, Rm_ServiceReqInfo *serviceRequest,
 
     /* Prevent another component using the same instance from wiping out the current
      * service request */
-    key = Rm_osalLocalCsEnter();
+    key = Rm_osalCsEnter();
 
     /* Make sure serviceType is valid and that a callback function has been provided */
     if ((serviceRequest->type < Rm_service_FIRST) || 
         (serviceRequest->type > Rm_service_LAST))
     {
         serviceResponse->serviceResult = RM_SERVICE_ERROR_INVALID_SERVICE_TYPE;
-        Rm_osalLocalCsExit(key);
+        Rm_osalCsExit(key);
         return;
     }
     else if (serviceRequest->callback.serviceCallback == NULL)
@@ -84,7 +84,7 @@ void Rm_serviceHandler (void *rmHandle, Rm_ServiceReqInfo *serviceRequest,
          * through the callback function provided by the component.  Return an error 
          * if the component does not provide a callback function. */
         serviceResponse->serviceResult = RM_SERVICE_ERROR_CALLBACK_NOT_PROVIDED;
-        Rm_osalLocalCsExit(key);
+        Rm_osalCsExit(key);
         return;
     }
 
@@ -153,7 +153,7 @@ void Rm_serviceHandler (void *rmHandle, Rm_ServiceReqInfo *serviceRequest,
         }
     }
 
-    Rm_osalLocalCsExit(key); 
+    Rm_osalCsExit(key); 
     return;
 }
 
index e0b09f7b14d03453af46d4cc31a4a99aaad0dcdb..0d3908a59af32dfdf0019feb0b363031a097b39e 100644 (file)
@@ -64,7 +64,7 @@ Rm_TransportNode *Rm_transportNodeAdd(Rm_Inst *rmInst, Rm_TransportCfg *transpor
     void *key;\r
 \r
     /* Lock access to the RM instance's route map */\r
-    key = Rm_osalLocalCsEnter();\r
+    key = Rm_osalCsEnter();\r
 \r
     /* Get memory for a new transport node from local memory */\r
     newTransportNode = Rm_osalMalloc (sizeof(Rm_TransportNode), false);\r
@@ -72,7 +72,8 @@ Rm_TransportNode *Rm_transportNodeAdd(Rm_Inst *rmInst, Rm_TransportCfg *transpor
     /* Return if the memory allocated for the transport node is NULL */\r
     if (newTransportNode != NULL)\r
     {\r
-        /* Populate the new entry. */\r
+        /* Populate the new entry */\r
+        newTransportNode->rmHandle = (Rm_Handle) rmInst;\r
         newTransportNode->remoteInstType = transportCfg->remoteInstType;\r
         strcpy(&(newTransportNode->remoteInstName)[0], transportCfg->remoteInstName);\r
         newTransportNode->nextNode = NULL;  /* New node will always be NULL */\r
@@ -98,7 +99,7 @@ Rm_TransportNode *Rm_transportNodeAdd(Rm_Inst *rmInst, Rm_TransportCfg *transpor
         }\r
     }\r
    \r
-    Rm_osalLocalCsExit(key);\r
+    Rm_osalCsExit(key);\r
 \r
     return (newTransportNode);\r
 }\r
@@ -186,12 +187,12 @@ Rm_TransportResult Rm_transportNodeDelete(Rm_Inst *rmInst, Rm_TransportHandle tr
     void *key;\r
 \r
     /* Lock access to the RM instance's route map */\r
-    key = Rm_osalLocalCsEnter();\r
+    key = Rm_osalCsEnter();\r
 \r
     /* Make sure there is at least one entry in the transaction queue */\r
     if (transportNode == NULL)\r
     {\r
-        Rm_osalLocalCsExit(key);\r
+        Rm_osalCsExit(key);\r
         return (RM_TRANSPORT_ERROR_NO_TRANSPORTS_REGISTERED);\r
     }\r
 \r
@@ -211,7 +212,7 @@ Rm_TransportResult Rm_transportNodeDelete(Rm_Inst *rmInst, Rm_TransportHandle tr
     /* Traversed entire queue but did not find transaction */\r
     if (transportNode == NULL)\r
     {\r
-        Rm_osalLocalCsExit(key);\r
+        Rm_osalCsExit(key);\r
         return (RM_TRANSPORT_ERROR_HANDLE_HAS_NOT_BEEN_REGISTERED);\r
     }\r
     else\r
@@ -236,7 +237,7 @@ Rm_TransportResult Rm_transportNodeDelete(Rm_Inst *rmInst, Rm_TransportHandle tr
         Rm_osalFree((void *) transportNode, sizeof(Rm_TransportNode), false);\r
     }\r
 \r
-    Rm_osalLocalCsExit(key);\r
+    Rm_osalCsExit(key);\r
     return (RM_TRANSPORT_SUCCESSFUL);\r
 }\r
 \r
@@ -428,7 +429,7 @@ Rm_TransportHandle Rm_transportRegister (Rm_Handle rmHandle, Rm_TransportCfg *tr
     void *key;\r
 \r
     /* Lock access to the RM instance */\r
-    key = Rm_osalLocalCsEnter();\r
+    key = Rm_osalCsEnter();\r
 \r
     /* RM Servers cannot connect to other Servers.  RM Client Delegates cannot\r
      * connect to other Client Delegates. */\r
@@ -437,7 +438,7 @@ Rm_TransportHandle Rm_transportRegister (Rm_Handle rmHandle, Rm_TransportCfg *tr
         ((rmInst->instType == Rm_instType_CLIENT_DELEGATE) &&\r
          (transportCfg->remoteInstType == Rm_instType_CLIENT_DELEGATE)))\r
     {\r
-        Rm_osalLocalCsExit(key);\r
+        Rm_osalCsExit(key);\r
         return (NULL); /* Error - return null */\r
     }\r
 \r
@@ -450,7 +451,7 @@ Rm_TransportHandle Rm_transportRegister (Rm_Handle rmHandle, Rm_TransportCfg *tr
          (transportCfg->remoteInstType == Rm_instType_SERVER)) &&\r
         rmInst->registeredWithDelegateOrServer)\r
     {\r
-        Rm_osalLocalCsExit(key);\r
+        Rm_osalCsExit(key);\r
         return (NULL); /* Error - return null */\r
     }         \r
 \r
@@ -465,7 +466,7 @@ Rm_TransportHandle Rm_transportRegister (Rm_Handle rmHandle, Rm_TransportCfg *tr
             (transportCfg->transportCallouts.rmReceive == NULL) ||\r
             (transportCfg->transportCallouts.rmNumPktsReceived == NULL))\r
         {\r
-            Rm_osalLocalCsExit(key);\r
+            Rm_osalCsExit(key);\r
             return (NULL); /* Error - return null */\r
         }\r
             \r
@@ -488,7 +489,7 @@ Rm_TransportHandle Rm_transportRegister (Rm_Handle rmHandle, Rm_TransportCfg *tr
         rmInst->registeredWithDelegateOrServer = true;\r
     }\r
 \r
-    Rm_osalLocalCsExit(key);\r
+    Rm_osalCsExit(key);\r
     return ((Rm_TransportHandle) transportNode);\r
 }\r
 \r
@@ -500,7 +501,7 @@ Rm_TransportResult Rm_transportUnregister (Rm_Handle rmHandle, Rm_TransportHandl
     void *key;\r
 \r
     /* Lock access to the RM instance */\r
-    key = Rm_osalLocalCsEnter();    \r
+    key = Rm_osalCsEnter();    \r
 \r
     /* Check if the transportHandle exists in the RM instance's route map */\r
     transportNode = Rm_transportNodeFindTransportHandle(rmInst, transportHandle);\r
@@ -508,7 +509,7 @@ Rm_TransportResult Rm_transportUnregister (Rm_Handle rmHandle, Rm_TransportHandl
     if (transportNode == NULL)\r
     {\r
         /* Error - transport node does not exist in RM instance route map */\r
-        Rm_osalLocalCsExit(key);\r
+        Rm_osalCsExit(key);\r
         return (RM_TRANSPORT_ERROR_HANDLE_HAS_NOT_BEEN_REGISTERED);\r
     }\r
 \r
@@ -523,7 +524,7 @@ Rm_TransportResult Rm_transportUnregister (Rm_Handle rmHandle, Rm_TransportHandl
     /* Delete the transport node */\r
     retVal = Rm_transportNodeDelete(rmInst, transportHandle);\r
 \r
-    Rm_osalLocalCsExit(key);\r
+    Rm_osalCsExit(key);\r
 \r
     return (retVal);\r
 }\r
@@ -531,9 +532,9 @@ Rm_TransportResult Rm_transportUnregister (Rm_Handle rmHandle, Rm_TransportHandl
 /* Used by the application to pass RM packets received from a transport to RM.\r
  * CODE THE FUNCTION SUCH THAT IT CAN BE CALLED DIRECTLY BY APP OR BE PLUGGED\r
  * AS PART OF AN ISR HANDLER FOR THE TRANSACTION RECEIVE */\r
-int32_t Rm_receivePktIsr(Rm_Handle rmHandle, Rm_TransportHandle transportHandle, Rm_Packet *pkt)\r
+int32_t Rm_receivePktIsr(Rm_TransportHandle transportHandle, Rm_Packet *pkt)\r
 {\r\r\r
-    Rm_Inst *rmInst = (Rm_Inst *)rmHandle;\r
+    Rm_Inst *rmInst = (Rm_Inst *)((Rm_TransportNode *)transportHandle)->rmHandle;\r
     Rm_Transaction *transaction;\r
     Rm_TransactionReceipt receipt;\r
 \r
@@ -716,9 +717,9 @@ int32_t Rm_receivePktIsr(Rm_Handle rmHandle, Rm_TransportHandle transportHandle,
 \r
 /* Application can call this API so that RM handles reception of packets based on\r
  * the RM handle and transport handle provided */\r
-int32_t Rm_receivePktPolling(Rm_Handle rmHandle, Rm_TransportHandle transportHandle)\r
+int32_t Rm_receivePktPolling(Rm_TransportHandle transportHandle)\r
 {\r
-    Rm_Inst *rmInst = (Rm_Inst *)rmHandle;\r
+    Rm_Inst *rmInst = (Rm_Inst *)((Rm_TransportNode *)transportHandle)->rmHandle;\r
     Rm_Packet *pkt = NULL;\r
     int32_t retVal = RM_SERVICE_ACTION_BASE;\r
 \r
@@ -731,7 +732,7 @@ int32_t Rm_receivePktPolling(Rm_Handle rmHandle, Rm_TransportHandle transportHan
     }\r
 \r
     /* Check to see if any RM packets are available.  Process any available packets. */\r
-    while (rmInst->transport.rmNumPktsReceived(transportHandle))\r
+    while (rmInst->transport.rmNumPktsReceived(transportHandle) > 0)\r
     {\r
         pkt = rmInst->transport.rmReceive(transportHandle);\r
 \r
@@ -741,7 +742,7 @@ int32_t Rm_receivePktPolling(Rm_Handle rmHandle, Rm_TransportHandle transportHan
         }\r
 \r
         /* Pass the packet to RM.  The packet will be freed within the PktIsr API */\r
-        if (retVal = Rm_receivePktIsr(rmHandle, transportHandle, pkt) <= RM_SERVICE_ERROR_BASE)\r
+        if (retVal = Rm_receivePktIsr(transportHandle, pkt) <= RM_SERVICE_ERROR_BASE)\r
         {\r
             /* Return if an error is encountered */\r
             return (retVal);\r
diff --git a/test/rm_osal.c b/test/rm_osal.c
new file mode 100644 (file)
index 0000000..0563140
--- /dev/null
@@ -0,0 +1,287 @@
+/**
+ *   @file  rm_osal.c
+ *
+ *   @brief
+ *      This is the OS abstraction layer and is used by the the RM LLD.
+ *
+ *  \par
+ *  ============================================================================
+ *  @n   (C) Copyright 2012, Texas Instruments, Inc.
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions
+ *  are met:
+ *
+ *    Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ *    Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the
+ *    distribution.
+ *
+ *    Neither the name of Texas Instruments Incorporated nor the names of
+ *    its contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  \par
+*/
+#include <xdc/std.h>
+#include <xdc/runtime/Memory.h>
+#include <xdc/runtime/Error.h>
+
+#include <ti/sysbios/family/c64p/Hwi.h>
+
+ /* CSL modules */
+#include <ti/csl/csl_semAux.h>
+/* CSL Cache module includes */
+#include <ti/csl/csl_cacheAux.h>
+/* CSL XMC module includes */
+#include <ti/csl/csl_xmcAux.h>
+
+/**********************************************************************
+ ****************************** Defines *******************************
+ **********************************************************************/
+
+#define RM_HW_SEM     2
+
+/**********************************************************************
+ ************************** Global Variables **************************
+ **********************************************************************/
+uint32_t rmMallocCounter = 0;
+uint32_t rmFreeCounter   = 0;
+
+/**********************************************************************
+ *************************** OSAL Functions **************************
+ **********************************************************************/
+
+/**
+ *  @b Description
+ *  @n
+ *      The function is used to allocate a memory block of the specified size.
+ *
+ *  @param[in]  num_bytes
+ *      Number of bytes to be allocated.
+ *
+ *  @retval
+ *      Allocated block address
+ */
+void* Osal_biosMalloc (uint32_t num_bytes)
+{
+       Error_Block     errorBlock;
+
+    /* Increment the allocation counter. */
+    rmMallocCounter++;
+
+       /* Allocate memory. */
+       return Memory_alloc(NULL, num_bytes, 0, &errorBlock);
+}
+
+/**
+ *  @b Description
+ *  @n
+ *      The function is used to free a memory block of the specified size.
+ *
+ *  @param[in]  ptr
+ *      Pointer to the memory block to be cleaned up.
+ *
+ *  @param[in]  size
+ *      Size of the memory block to be cleaned up.
+ *
+ *  @retval
+ *      Not Applicable
+ */
+void Osal_biosFree (void *ptr, uint32_t size)
+{
+    /* Increment the free counter. */
+    rmFreeCounter++;
+       Memory_free(NULL, ptr, size);
+}
+
+/**
+ *  @b Description
+ *  @n
+ *      The function is used to enter a critical section.
+ *      Function protects against
+ *
+ *      access from multiple cores
+ *      and
+ *      access from multiple threads on single core
+ *
+ *  @retval
+ *      Handle used to lock critical section
+ */
+void* Osal_rmCsEnter (void)
+{
+    /* Get the hardware semaphore */
+    while ((CSL_semAcquireDirect (RM_HW_SEM)) == 0);
+
+    /* Create Semaphore for protection against access from multiple threads
+     * Not created here becasue application is not multithreaded
+     * */
+    return NULL;
+}
+
+/**
+ *  @b Description
+ *  @n
+ *      The function is used to exit a critical section
+ *      protected using Osal_rmCsEnter() API.
+ *
+ *  @param[in]  CsHandle
+ *      Handle for unlocking critical section.
+ *
+ *  @retval
+ *      Not Applicable
+ */
+void Osal_rmCsExit (void *CsHandle)
+{
+    /* Release Semaphore using handle */
+
+    /* Release the hardware semaphore */
+    CSL_semReleaseSemaphore (RM_HW_SEM);
+
+    return;
+}
+/**
+ *  @b Description
+ *  @n
+ *      The function is used to enter a critical section.
+ *      Function protects against
+ *      access from multiple threads on single core
+ *
+ *  @retval
+ *      Handle used to lock critical section
+ */
+void* Osal_rmMtCsEnter (void)
+{
+    /* Create Semaphore for protection against access from multiple threads
+     * Not created here becasue application is not multithreaded
+     * */
+    return NULL;
+}
+
+/**
+ *  @b Description
+ *  @n
+ *      The function is used to exit a critical section
+ *      protected using Osal_rmCsEnter() API.
+ *
+ *  @param[in]  CsHandle
+ *      Handle for unlocking critical section.
+ *
+ *  @retval
+ *      Not Applicable
+ */
+void Osal_rmMtCsExit (void *CsHandle)
+{
+    /* Release Semaphore using handle */
+
+    return;
+}
+
+/**
+ *  @b Description
+ *  @n
+ *      The function is used to indicate that a block of memory is
+ *      about to be accessed. If the memory block is cached then this
+ *      indicates that the application would need to ensure that the
+ *      cache is updated with the data from the actual memory.
+ *
+ *  @param[in]  ptr
+ *       Address of memory block
+ *
+ *  @param[in]  size
+ *       Size of memory block
+ *
+ *  @retval
+ *      Not Applicable
+ */
+void Osal_rmBeginMemAccess (void *ptr, uint32_t size)
+{
+    uint32_t    key;
+
+    /* Disable Interrupts */
+    key = Hwi_disable();
+
+    /* Cleanup the prefetch buffer also. */
+    CSL_XMC_invalidatePrefetchBuffer();
+
+#ifdef L2_CACHE
+    /* Invalidate L2 cache. This should invalidate L1D as well.
+     * Wait until operation is complete. */
+    CACHE_invL2 (ptr, size, CACHE_FENCE_WAIT);
+#else
+    /* Invalidate L1D cache and wait until operation is complete.
+     * Use this approach if L2 cache is not enabled */
+    CACHE_invL1d (ptr, size, CACHE_FENCE_WAIT);
+#endif
+
+    asm   (" nop      4");
+    asm   (" nop      4");
+    asm   (" nop      4");
+    asm   (" nop      4");
+
+    /* Reenable Interrupts. */
+    Hwi_restore(key);
+
+    return;
+}
+
+/**
+ *  @b Description
+ *  @n
+ *      The function is used to indicate that the block of memory has
+ *      finished being accessed. If the memory block is cached then the
+ *      application would need to ensure that the contents of the cache
+ *      are updated immediately to the actual memory.
+ *
+ *  @param[in]  ptr
+ *       Address of memory block
+ *
+ *  @param[in]  size
+ *       Size of memory block
+ *
+ *  @retval
+ *      Not Applicable
+ */
+void Osal_rmEndMemAccess (void *ptr, uint32_t size)
+{
+    uint32_t    key;
+
+    /* Disable Interrupts */
+    key = Hwi_disable();
+
+#ifdef L2_CACHE
+    /* Writeback L2 cache. This should Writeback L1D as well.
+     * Wait until operation is complete. */
+    CACHE_wbL2 (ptr, size, CACHE_FENCE_WAIT);
+
+#else
+    /* Writeback L1D cache and wait until operation is complete.
+     * Use this approach if L2 cache is not enabled */
+    CACHE_wbL1d (ptr, size, CACHE_FENCE_WAIT);
+#endif
+
+    asm   (" nop      4");
+    asm   (" nop      4");
+    asm   (" nop      4");
+    asm   (" nop      4");
+
+    /* Reenable Interrupts. */
+    Hwi_restore(key);
+    return;
+}
+
diff --git a/test/rm_osal.h b/test/rm_osal.h
new file mode 100644 (file)
index 0000000..d818dd2
--- /dev/null
@@ -0,0 +1,71 @@
+/**
+ *   @file  rm_osal.h
+ *
+ *   @brief   
+ *      This is the OS adaptation layer for the Resource Manager. This file should
+ *      be modified by the system integrator to their system/OS implementation
+ *      The file is provided as an 'example' template ported for XDC/BIOS.
+ *
+ *  \par
+ *  NOTE:
+ *      (C) Copyright 2009 Texas Instruments, Inc.
+ * 
+ *  Redistribution and use in source and binary forms, with or without 
+ *  modification, are permitted provided that the following conditions 
+ *  are met:
+ *
+ *    Redistributions of source code must retain the above copyright 
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ *    Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the 
+ *    documentation and/or other materials provided with the   
+ *    distribution.
+ *
+ *    Neither the name of Texas Instruments Incorporated nor the names of
+ *    its contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
+ *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+ *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
+ *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  \par
+*/
+#ifndef __RM_OSAL_H__
+#define __RM_OSAL_H__
+
+extern void* Osal_biosMalloc (uint32_t num_bytes);
+extern void Osal_biosFree (void *ptr, uint32_t size);
+extern void* Osal_rmCsEnter (void);
+extern void Osal_rmCsExit (void *CsHandle);
+extern void* Osal_rmMtCsEnter (void);
+extern void Osal_rmMtCsExit (void *CsHandle);
+extern void Osal_rmBeginMemAccess (void *ptr, uint32_t size);
+extern void Osal_rmEndMemAccess (void *ptr, uint32_t size);
+
+/* RM LLD OSAL Memory Allocation API are redefined to TEST application API */
+#define Rm_osalMalloc             Osal_biosMalloc
+#define Rm_osalFree               Osal_biosFree
+
+/* RM LLD OSAL Critical section and cache coherency APIs are used without redefinition in TEST application API */
+#define Rm_osalCsEnter            Osal_rmCsEnter
+#define Rm_osalCsExit             Osal_rmCsExit
+#define Rm_osalMtCsEnter          Osal_rmMtCsEnter
+#define Rm_osalMtCsExit           Osal_rmMtCsExit
+#define Rm_osalBeginMemAccess     Osal_rmBeginMemAccess
+#define Rm_osalEndMemAccess       Osal_rmEndMemAccess
+
+/* RM LLD OSAL Logging API is mapped directly to an XDC Runtime API */
+#define Rm_osalLog                System_printf
+
+#endif /* __RM_OSAL_H__ */
+
diff --git a/test/rm_test.c b/test/rm_test.c
new file mode 100644 (file)
index 0000000..ec96813
--- /dev/null
@@ -0,0 +1,664 @@
+/* 
+ * Copyright (c) 2012, Texas Instruments Incorporated
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * *  Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * *  Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * *  Neither the name of Texas Instruments Incorporated nor the names of
+ *    its contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * */
+/*
+ *  ======== rm_test.c ========
+ *  RM multicore test example
+ *
+ *  This is an example program that uses MessageQ to pass a message
+ *  from one processor to another.
+ *
+ *  Each processor creates its own MessageQ first and then will try to open
+ *  a remote processor's MessageQ.  
+ *
+ *  See message_multicore.k file for expected output.
+ */
+
+#include <c6x.h>
+#include <xdc/std.h>
+#include <string.h>
+#include <stdbool.h>
+
+/*  -----------------------------------XDC.RUNTIME module Headers    */
+#include <xdc/runtime/System.h>
+#include <xdc/runtime/IHeap.h>
+
+/*  ----------------------------------- IPC module Headers           */
+#include <ti/ipc/Ipc.h>
+#include <ti/ipc/MessageQ.h>
+#include <ti/ipc/HeapBufMP.h>
+#include <ti/ipc/MultiProc.h>
+
+/*  ----------------------------------- BIOS6 module Headers         */
+#include <ti/sysbios/BIOS.h>
+#include <ti/sysbios/knl/Task.h>
+
+/*  ----------------------------------- Resource Manager Headers         */
+#include <ti/drv/rm/rm.h>
+#include <ti/drv/rm/rm_transport.h>
+#include <ti/drv/rm/rm_services.h>
+
+/* ======== Task Handles ======== */
+Task_Handle startupRmTskHandle;
+
+/* ======== Application Heaps ======== */
+#define RM_PKT_HEAP_NAME   "rmHeapBuf"
+HeapBufMP_Handle rmPktHeapHandle = NULL;
+
+#define MSGQ_HEAP_NAME   "msgQHeapBuf"
+#define MSGQ_HEAP_ID      0
+
+/* ======== RM Instance Names ======== */
+Char rmServerName[RM_INSTANCE_NAME_MAX_CHARS] = "RM_Server";
+Char rmClientDelegateName[RM_INSTANCE_NAME_MAX_CHARS] = "RM_Client_Delegate";
+Char rmClientName[RM_INSTANCE_NAME_MAX_CHARS] = "RM_Client";
+
+/* ======== RM IPC MessageQ Names ======== */
+Char serverCdQueueName[30] = "RM_Server_CD_Queue";
+Char cdServerQueueName[30] = "RM_CD_Server_Queue";
+Char cdClientQueueName[30] = "RM_CD_Client_Queue";
+Char clientCdQueueName[30] = "RM_Client_CD_Queue";
+
+/* ======== RM Instance Handles ======== */
+Rm_Handle rmServerHandle = NULL;
+Rm_Handle rmClientDelegateHandle = NULL;
+Rm_Handle rmClientHandle = NULL;
+
+/* ======== RM Transport Packet Definition ======== */
+typedef struct {
+  MessageQ_MsgHeader msgQHeader;
+  /* Pointer to packet provided by RM */
+  Rm_Packet *rmPkt;
+} MsgQ_RmPacket;
+
+/* ======== RM Transport Mapping Tables for Application ======== */
+/* Core 0 Map Entry Indices */
+#define SERVER_TO_CD_MAP_ENTRY 0
+/* Core 1 Map Entry Indicies */
+#define CD_TO_SERVER_MAP_ENTRY 0
+#define CD_TO_CLIENT_MAP_ENTRY 1
+#define CLIENT_TO_CD_MAP_ENTRY 2
+
+/* Max map entries across all cores */
+#define MAX_MAPPING_ENTRIES 3
+
+typedef struct {
+    Rm_TransportHandle transportHandle;
+    MessageQ_Handle receiveMsgQ;
+    MessageQ_QueueId remoteMsgQId;
+} Transport_MapEntry;
+
+/* Core 1 will have three mapping entries
+ * Two map entries for the Client Delegate
+ * One map entry for the Client */
+Transport_MapEntry rmTransportMap[MAX_MAPPING_ENTRIES];
+
+/* ======== RM Application Transport APIs ======== */
+
+Rm_Packet *TransportAlloc (Rm_TransportHandle transportHandle, uint32_t pktSize)
+{
+    Rm_Packet *pkt = NULL;
+
+    /* All transports will allocate from the same heap */
+    
+    HeapBufMP_alloc(rmPktHeapHandle, pktSize, 0);
+
+    if (pkt != NULL)
+    {
+       pkt->pktLenBytes = pktSize;
+    }
+
+    return (pkt);
+}
+
+int32_t TransportFree (Rm_TransportHandle transportHandle, Rm_Packet *pkt)
+{
+    uint32_t pktSize = pkt->pktLenBytes;
+
+    /* All transports will free to the same heap */
+    
+    HeapBufMP_free(rmPktHeapHandle, pkt, pktSize);
+
+    return (0);    
+}
+
+int32_t TransportSend (Rm_TransportHandle transportHandle, Rm_Packet *pkt)
+{
+    MsgQ_RmPacket *rmMsg = NULL;
+    MessageQ_QueueId remoteQueueId;
+    bool handleValid = false;
+    int32_t status, i;    
+
+    /* Get the remoteQueueId based on the transportHandle */
+    for (i = 0; i < MAX_MAPPING_ENTRIES; i++)
+    {
+        /* transportHandle found in mapping table.  Get the remoteQueueId associated
+         * with it */
+        if (rmTransportMap[i].transportHandle == transportHandle)
+        {
+            remoteQueueId = rmTransportMap[i].remoteMsgQId;
+            /* Break out of the search loop */
+            handleValid = true;
+            break;
+        }
+    }
+
+    if (handleValid)
+    {
+        /* Allocate a messageQ message for containing the RM packet */
+        rmMsg = (MsgQ_RmPacket *)MessageQ_alloc(MSGQ_HEAP_ID, sizeof(MsgQ_RmPacket));
+        if (rmMsg == NULL) 
+        {
+            System_printf("Core %d: MessageQ_alloc failed in TransportSend\n", MultiProc_self());
+        }
+
+        /* Attach the RM packet to the MessageQ message */
+        rmMsg->rmPkt = pkt;
+        /* Send the message to the remote side */
+        status = MessageQ_put(remoteQueueId, rmMsg);
+        if (status < 0) 
+        { 
+            System_printf("Core %d: MessageQ_put had a failure/error in TransportSend\n", MultiProc_self());
+        }
+    }
+    else
+    {   
+        /* Could not find a registered transport handle that matched the handle provided by RM.
+         * Return an error to RM. */
+        System_printf("Core %d: TransportSend couldn't find transportHandle in transport map\n", MultiProc_self());
+        status = -1;
+    }
+    
+    return (status);
+}
+
+void * TransportReceive (Rm_TransportHandle transportHandle)
+{
+    MessageQ_Handle receiveQ;
+    MessageQ_Msg rmMsg = NULL;
+    Rm_Packet *rmPkt = NULL;
+    bool queueValid = false;
+    int32_t status, i;    
+
+    /* Get the receiveQ based on the transportHandle */
+    for (i = 0; i < MAX_MAPPING_ENTRIES; i++)
+    {
+        /* transportHandle found in mapping table.  Get the receiveQ associated
+         * with it */
+        if (rmTransportMap[i].transportHandle == transportHandle)
+        {
+            receiveQ = rmTransportMap[i].receiveMsgQ;
+            /* Break out of the search loop */
+            queueValid = true;
+            break;
+        }
+    }
+
+    if (queueValid)
+    {
+        /* Get the next message from the receiveQ */
+        status = (int32_t) MessageQ_get(receiveQ, &rmMsg, MessageQ_FOREVER);
+        if (status < 0) 
+        {
+            System_abort("This should not happen since timeout is forever\n");
+        }
+        if (rmMsg == NULL) 
+        {
+            System_printf("Core %d: MessageQ_get failed returning a null packet in TransportReceive\n", MultiProc_self());
+        }
+
+        /* Extract the Rm_Packet from the RM msg */
+        rmPkt = ((MsgQ_RmPacket)rmMsg).rmPkt;
+
+        /* Free the messageQ message now that RM packet pointer has been extracted */
+        status = MessageQ_free(rmMsg);
+        if (status < 0) 
+        { 
+            System_printf("Core %d: MessageQ_free had a failure/error in TransportReceive\n", MultiProc_self());
+        }
+    }
+    else
+    {   
+        /* Could not find a registered transport handle that matched the handle provided by RM.
+         * Return an error to RM. */
+        System_printf("Core %d: TransportReceive couldn't find transportHandle in transport map\n", MultiProc_self());
+    }
+
+    /* Pass the RM packet back to RM */
+    return ((void *)rmPkt);
+}
+
+int32_t TransportNumPktsReceived (Rm_TransportHandle transportHandle)
+{
+    MessageQ_Handle receiveQ;
+    bool queueValid = false;
+    int32_t numPkts, i;    
+
+    /* Get the receiveQ based on the transportHandle */
+    for (i = 0; i < MAX_MAPPING_ENTRIES; i++)
+    {
+        /* transportHandle found in mapping table.  Get the receiveQ associated
+         * with it */
+        if (rmTransportMap[i].transportHandle == transportHandle)
+        {
+            receiveQ = rmTransportMap[i].receiveMsgQ;
+            /* Break out of the search loop */
+            queueValid = true;
+            break;
+        }
+    }
+
+    if (queueValid)
+    {
+        /* Get the number of messages in the receiveQ */
+        numPkts = (int32_t) MessageQ_count(receiveQ);
+    }
+    else
+    {   
+        /* Could not find a registered transport handle that matched the handle provided by RM.
+         * Return an error to RM. */
+        System_printf("Core %d: TransportNumPktsReceived couldn't find transportHandle in transport map\n", MultiProc_self());
+        numPkts = -1;
+    }
+    
+    return (numPkts);
+}
+
+/*
+ *  ======== testRmTsk ========
+ *  RM test task
+ */
+Void testRmTsk(UArg arg0, UArg arg1)
+{
+    /* Delete the RM startup task */
+    System_printf("Core %d: Deleting RM startup task...\n", MultiProc_self());
+    if (startupRmTskHandle)
+    {
+        Task_delete(startupRmTskHandle);
+        /* Set the task handle to be NULL so that the delete only occurs once */
+        startupRmTskHandle = NULL;
+    }
+
+    /* Start running Tests */
+
+    System_printf("The test is complete\n");
+    BIOS_exit(0);
+}
+
+/*
+ *  ======== startupRmTsk ========
+ *  Configures application transports and registers them with RM
+ */
+Void startupRmTsk(UArg arg0, UArg arg1)
+{
+    MessageQ_Msg     msg;    
+    MessageQ_Handle  serverCdMsgQ, cdServerMsgQ, cdClientMsgQ, clientCdMsgQ;
+    MessageQ_QueueId serverCdQId, cdServerQId, cdClientQId, clientCdQId;    
+    Int              status, i;
+    HeapBufMP_Handle msgQHeapHandle;
+    HeapBufMP_Params heapBufParams;
+    Rm_TransportCfg rmTransportCfg;
+    Rm_TransportHandle serverCdHandle, cdServerHandle, cdClientHandle, clientCdHandle;
+    Task_Params taskParams;
+       Task_Handle taskHandle;
+
+    /* Initialize the transport map */
+    for (i = 0; i < MAX_MAPPING_ENTRIES; i++)
+    {
+        rmTransportMap[i].transportHandle = NULL;
+    }
+
+    if (MultiProc_self() == 0)
+    {
+        /* Create the heap that will be used to allocate RM messages. This
+         * heap is a multi-processor heap.  It will be shared amongst
+         * all RM instances. */     
+        HeapBufMP_Params_init(&heapBufParams);
+        heapBufParams.regionId       = 0;
+        heapBufParams.name           = RM_PKT_HEAP_NAME;
+        heapBufParams.numBlocks      = 64;
+        heapBufParams.blockSize      = sizeof(Rm_Packet);
+        rmPktHeapHandle = HeapBufMP_create(&heapBufParams);
+        if (rmPktHeapHandle == NULL) 
+        {
+            System_abort("HeapBufMP_create failed for RM packet heap\n" );
+        }
+        System_printf("Core %d: RM packet heap created\n", MultiProc_self());
+
+        /* Create the heap that will be used to allocate messageQ messages. */     
+        HeapBufMP_Params_init(&heapBufParams);
+        heapBufParams.regionId       = 0;
+        heapBufParams.name           = MSGQ_HEAP_NAME;
+        heapBufParams.numBlocks      = 64;
+        heapBufParams.blockSize      = sizeof(MsgQ_RmPacket);
+        msgQHeapHandle = HeapBufMP_create(&heapBufParams);
+        if (msgQHeapHandle == NULL) 
+        {
+            System_abort("HeapBufMP_create failed MessageQ message heap\n" );
+        } 
+        System_printf("Core %d: IPC MessageQ message heap created\n", MultiProc_self());
+    }
+    else 
+    {
+        /* Open the heaps created by the other processor. Loop until opened. */
+        do 
+        {
+            status = HeapBufMP_open(RM_PKT_HEAP_NAME, &rmPktHeapHandle);
+            /* 
+             *  Sleep for 1 clock tick to avoid inundating remote processor
+             *  with interrupts if open failed
+             */
+            if (status < 0)
+            { 
+                Task_sleep(1);
+            }
+        } while (status < 0);
+        System_printf("Core %d: RM packet heap opened\n", MultiProc_self());
+        
+        do 
+        {
+            status = HeapBufMP_open(MSGQ_HEAP_NAME, &msgQHeapHandle);
+            /* 
+             *  Sleep for 1 clock tick to avoid inundating remote processor
+             *  with interrupts if open failed
+             */
+            if (status < 0)
+            { 
+                Task_sleep(1);
+            }
+        } while (status < 0);
+        System_printf("Core %d: IPC MessageQ message heap opened\n", MultiProc_self());
+    }
+    
+    /* Register the MessageQ heap with MessageQ */
+    MessageQ_registerHeap((IHeap_Handle)msgQHeapHandle, MSGQ_HEAP_ID);
+
+    /* Create the messageQ's for each RM instance connection
+     * Need four queues.  Topology will be:
+     * RM Server <---> RM Client Delegate <---> RM Client 
+     * 1 queue on RM Server
+     * 2 queues on RM Client Delegate
+     * 1 queue on RM Client */
+    if (MultiProc_self() == 0)
+    {
+        /* Create the RM Server messageQ used by the RM Client Delegate */
+        serverCdMsgQ = MessageQ_create(serverCdQueueName, NULL);
+        if (serverCdMsgQ == NULL) 
+        {
+            System_abort("MessageQ_create failed for RM Server - Client Delegate queue\n" );
+        }
+        System_printf("Core %d: RM Server MessageQ created for receiving packets from RM CD\n", MultiProc_self());
+    }
+    else if (MultiProc_self() == 1)
+    {
+        /* Create the RM Client Delegate messageQ used by the RM Server */
+        cdServerMsgQ = MessageQ_create(cdServerQueueName, NULL);
+        if (cdServerMsgQ == NULL) 
+        {
+            System_abort("MessageQ_create failed for RM Client Delegate - Server queue\n" );
+        }
+        System_printf("Core %d: RM CD MessageQ created for receiving packets from RM Server\n", MultiProc_self());
+        /* Create the RM Client Delegate messageQ used by the RM Client */
+        cdClientMsgQ = MessageQ_create(cdClientQueueName, NULL);
+        if (cdClientMsgQ == NULL) 
+        {
+            System_abort("MessageQ_create failed for RM Client Delegate - Client queue\n" );
+        } 
+        System_printf("Core %d: RM CD MessageQ created for receiving packets from RM Client\n", MultiProc_self());
+        /* Create the RM Client messageQ used by the RM Client Delegate */
+        clientCdMsgQ = MessageQ_create(clientCdQueueName, NULL;
+        if (clientCdMsgQ == NULL) 
+        {
+            System_abort("MessageQ_create failed for RM Client - Client Delegate queue\n" );
+        }
+        System_printf("Core %d: RM Client MessageQ created for receiving packets from RM CD\n", MultiProc_self());
+    }
+    
+    /* Open the remote message queues. Also register the RM transports with each RM instance */
+    if (MultiProc_self() == 0)
+    {
+        /* Open the Client Delegate messageQ from the Server */
+        do 
+        {
+            status = MessageQ_open(cdServerQueueName, &serverCdQId); 
+            /* 
+             *  Sleep for 1 clock tick to avoid inundating remote processor
+             *  with interrupts if open failed
+             */
+            if (status < 0)
+            { 
+                Task_sleep(1);
+            }
+        } while (status < 0);
+        System_printf("Core %d: RM CD MessageQ opened from RM Server\n", MultiProc_self());
+
+        /* Register the Client Delegate with the RM Server Instance */
+        rmTransportCfg.remoteInstType = Rm_instType_CLIENT_DELEGATE;
+        rmTransportCfg.remoteInstName = &rmClientDelegateName[0];
+        rmTransportCfg.transportCalloutsValid = true;
+        rmTransportCfg.transportCallouts.rmAllocPkt = TransportAlloc;
+        rmTransportCfg.transportCallouts.rmFreePkt = TransportFree;
+        rmTransportCfg.transportCallouts.rmSend = TransportSend;
+        rmTransportCfg.transportCallouts.rmReceive = TransportReceive;        
+        rmTransportCfg.transportCallouts.rmNumPktsReceived = TransportNumPktsReceived; 
+
+        serverCdHandle = Rm_transportRegister(rmServerHandle, rmTransportCfg);
+
+        /* Store the mapping information in the transport map */
+        rmTransportMap[SERVER_TO_CD_MAP_ENTRY].transportHandle = serverCdHandle;
+        rmTransportMap[SERVER_TO_CD_MAP_ENTRY].receiveMsgQ = serverCdMsgQ;
+        rmTransportMap[SERVER_TO_CD_MAP_ENTRY].remoteMsgQId = serverCdQId;
+        System_printf("Core %d: Registered RM Server <=> RM CD transport with RM Server instance\n", MultiProc_self());
+        
+    }
+    else if (MultiProc_self() == 1)
+    {
+        /* Open the Server messageQ from the Client Delegate */
+        do 
+        {
+            status = MessageQ_open(serverCdQueueName, &cdServerQId); 
+            /* 
+             *  Sleep for 1 clock tick to avoid inundating remote processor
+             *  with interrupts if open failed
+             */
+            if (status < 0) 
+            { 
+                Task_sleep(1);
+            }
+        } while (status < 0);
+        System_printf("Core %d: RM Server MessageQ opened from RM CD\n", MultiProc_self());
+
+        /* Register the Server with the RM Client Delegate Instance */
+        rmTransportCfg.remoteInstType = Rm_instType_SERVER;
+        rmTransportCfg.remoteInstName = &rmServerName[0];
+        /* Set the callouts as valid for the first transport configuration on this core */
+        rmTransportCfg.transportCalloutsValid = true;
+        rmTransportCfg.transportCallouts.rmAllocPkt = TransportAlloc;
+        rmTransportCfg.transportCallouts.rmFreePkt = TransportFree;
+        rmTransportCfg.transportCallouts.rmSend = TransportSend;
+        rmTransportCfg.transportCallouts.rmReceive = TransportReceive;        
+        rmTransportCfg.transportCallouts.rmNumPktsReceived = TransportNumPktsReceived; 
+
+        cdServerHandle = Rm_transportRegister(rmClientDelegateHandle, rmTransportCfg);
+
+        /* Store the mapping information in the transport map */
+        rmTransportMap[CD_TO_SERVER_MAP_ENTRY].transportHandle = cdServerHandle;
+        rmTransportMap[CD_TO_SERVER_MAP_ENTRY].receiveMsgQ = cdServerMsgQ;
+        rmTransportMap[CD_TO_SERVER_MAP_ENTRY].remoteMsgQId = cdServerQId;
+        System_printf("Core %d: Registered RM CD <=> RM Server transport with RM CD instance\n", MultiProc_self());
+        
+        /* Open the Client messageQ from the Client Delegate */
+        do 
+        {
+            status = MessageQ_open(clientCdQueueName, &cdClientQId); 
+            /* 
+             *  Sleep for 1 clock tick to avoid inundating remote processor
+             *  with interrupts if open failed
+             */
+            if (status < 0) 
+            { 
+                Task_sleep(1);
+            }
+        } while (status < 0);
+        System_printf("Core %d: RM Client MessageQ opened from RM CD\n", MultiProc_self());
+
+        /* Register the Client with the RM Client Delegate Instance */
+        rmTransportCfg.remoteInstType = Rm_instType_CLIENT;
+        rmTransportCfg.remoteInstName = &rmClientName[0];
+        /* Callouts already set so set them as invalid */
+        rmTransportCfg.transportCalloutsValid = false;
+
+        cdClientHandle = Rm_transportRegister(rmClientDelegateHandle, rmTransportCfg);
+
+        /* Store the mapping information in the transport map */
+        rmTransportMap[CD_TO_CLIENT_MAP_ENTRY].transportHandle = cdClientHandle;
+        rmTransportMap[CD_TO_CLIENT_MAP_ENTRY].receiveMsgQ = cdClientMsgQ;
+        rmTransportMap[CD_TO_CLIENT_MAP_ENTRY].remoteMsgQId = cdClientQId;
+        System_printf("Core %d: Registered RM CD <=> RM Client transport with RM CD instance\n", MultiProc_self());
+        
+        /* Open the Client Delegate messageQ from the Client */        
+        do 
+        {
+            status = MessageQ_open(cdClientQueueName, &clientCdQId); 
+            /* 
+             *  Sleep for 1 clock tick to avoid inundating remote processor
+             *  with interrupts if open failed
+             */
+            if (status < 0) 
+            { 
+                Task_sleep(1);
+            }
+        } while (status < 0);
+        System_printf("Core %d: RM CD MessageQ opened from RM Client\n", MultiProc_self());
+
+        /* Register the Client Delegate with the RM Client Instance */
+        rmTransportCfg.remoteInstType = Rm_instType_CLIENT_DELEGATE;
+        rmTransportCfg.remoteInstName = &rmClientDelegateName[0];
+        /* Callouts already set so set them as invalid */
+        rmTransportCfg.transportCalloutsValid = false;
+
+        clientCdHandle = Rm_transportRegister(rmClientHandle, rmTransportCfg);
+
+        /* Store the mapping information in the transport map */
+        rmTransportMap[CLIENT_TO_CD_MAP_ENTRY].transportHandle = clientCdHandle;
+        rmTransportMap[CLIENT_TO_CD_MAP_ENTRY].receiveMsgQ = clientCdMsgQ;
+        rmTransportMap[CLIENT_TO_CD_MAP_ENTRY].remoteMsgQId = clientCdQId; 
+        System_printf("Core %d: Registered RM Client <=> RM CD transport with RM Client instance\n", MultiProc_self());
+    }
+    
+    /* Create the RM test task. */
+    System_printf("Core %d: Creating RM test task...\n", MultiProc_self());
+    Task_Params_init (&taskParams);
+    Task_create (testRmTsk, &taskParams, NULL);
+}
+
+/*
+ *  ======== main ========
+ *  Synchronizes all processors (in Ipc_start) and calls BIOS_start
+ */
+Int main(Int argc, Char* argv[])
+{
+    Rm_InitCfg rmInitCfg;
+    Rm_Handle rmHandle = NULL;
+    Task_Params taskParams;
+    Int status;
+
+    System_printf ("*********************************************************\n");
+    System_printf ("********************** RM Testing ***********************\n");
+    System_printf ("*********************************************************\n");
+
+    System_printf ("RM Version : 0x%08x\nVersion String: %s\n", Rm_getVersion(), Rm_getVersionStr());
+
+    /* Initialize the RM instances - RM must be initialized before anything else in the system
+     * Core 0: 1 RM Instance - RM Server
+     * Core 1: 2 RM Instances - RM Client Delegate
+     *                          RM Client
+     */
+    if (MultiProc_self()== 0)
+    {
+        /* Create the RM Server instance */
+        rmInitCfg.instName = &rmServerName[0];
+        rmInitCfg.instType = Rm_instType_SERVER;
+        /* SET TO NULL - FEATURES NOT ADDED YET */
+        rmInitCfg.globalResourceList = NULL;
+        rmInitCfg.startupPolicy = NULL;
+
+        /* Get the RM Server handle */
+        rmServerHandle = Rm_init(&rmInitCfg);
+        System_printf("Core %d: RM Server instance created\n", MultiProc_self());
+    }
+    else if (MultiProc_self()== 1)
+    {
+        /* Create the RM Client Delegate instance */
+        rmInitCfg.instName = &rmClientDelegateName[0];
+        rmInitCfg.instType = Rm_instType_CLIENT_DELEGATE;
+        /* SET TO NULL - FEATURES NOT ADDED YET */
+        rmInitCfg.globalResourceList = NULL;
+        rmInitCfg.startupPolicy = NULL;
+
+        /* Get the RM Client Delegate handle */
+        rmClientDelegateHandle = Rm_init(&rmInitCfg);
+        System_printf("Core %d: RM Client Delegate instance created\n", MultiProc_self());
+
+        /* Create the RM Client instance */
+        rmInitCfg.instName = &rmClientName[0];
+        rmInitCfg.instType = Rm_instType_CLIENT;
+        /* SET TO NULL - FEATURES NOT ADDED YET */
+        rmInitCfg.globalResourceList = NULL;
+        rmInitCfg.startupPolicy = NULL;
+
+        /* Get the RM Client handle */
+        rmClientHandle = Rm_init(&rmInitCfg);
+        System_printf("Core %d: RM Client instance created\n", MultiProc_self());
+    }
+
+    /*  
+     *  Ipc_start() calls Ipc_attach() to synchronize all remote processors
+     *  because 'Ipc.procSync' is set to 'Ipc.ProcSync_ALL' in *.cfg
+     */
+    System_printf("Core %d: Starting IPC...\n", MultiProc_self());
+    status = Ipc_start();
+    if (status < 0) 
+    {
+        System_abort("Ipc_start failed\n");
+    }
+
+    /* Create the RM startup task */
+    System_printf("Core %d: Creating RM startup task...\n", MultiProc_self());
+    Task_Params_init (&taskParams);
+    startupRmTskHandle = Task_create (startupRmTsk, &taskParams, NULL);
+
+    System_printf("Core %d: Starting BIOS...\n", MultiProc_self());
+    BIOS_start();
+
+    return (0);    
+}
+
diff --git a/test/rm_test.cfg b/test/rm_test.cfg
new file mode 100644 (file)
index 0000000..13ad0bb
--- /dev/null
@@ -0,0 +1,94 @@
+/* 
+ * Copyright (c) 2012, Texas Instruments Incorporated
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * *  Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * *  Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * *  Neither the name of Texas Instruments Incorporated nor the names of
+ *    its contributors may be used to endorse or promote products derived
+ *    from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
+ * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
+ * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ * */
+
+var MultiProc = xdc.useModule('ti.sdo.utils.MultiProc');
+
+/*
+ *  Get the list of names that the build device supports.
+ *  I.e. ["CORE0", "CORE1", "CORE2" ... ]
+ */
+var nameList = MultiProc.getDeviceProcNames();
+
+/* 
+ *  Since this is a single-image example, we don't (at build-time) which 
+ *  processor we're building for.  We therefore supply 'null' 
+ *  as the local procName and allow IPC to set the local procId at runtime.
+ */
+MultiProc.setConfig(null, nameList);
+                           
+/* 
+ *  The SysStd System provider is a good one to use for debugging 
+ *  but does not have the best performance. Use xdc.runtime.SysMin
+ *  for better performance.
+ */
+var System   = xdc.useModule('xdc.runtime.System');
+var SysStd   = xdc.useModule('xdc.runtime.SysStd');
+System.SupportProxy = SysStd;
+
+/* Modules explicitly used in the application */
+var MessageQ    = xdc.useModule('ti.sdo.ipc.MessageQ');
+var Ipc         = xdc.useModule('ti.sdo.ipc.Ipc');
+var HeapBufMP   = xdc.useModule('ti.sdo.ipc.heaps.HeapBufMP');
+var MultiProc   = xdc.useModule('ti.sdo.utils.MultiProc');
+
+/* BIOS/XDC modules */
+var BIOS        = xdc.useModule('ti.sysbios.BIOS');
+BIOS.heapSize   = 0x8000;
+var Task        = xdc.useModule('ti.sysbios.knl.Task');
+
+/* Synchronize all processors (this will be done in Ipc_start) */
+Ipc.procSync = Ipc.ProcSync_ALL;
+
+/* Shared Memory base address and length */
+var SHAREDMEM           = 0x0C000000;
+var SHAREDMEMSIZE       = 0x00200000;
+
+/* 
+ *  Need to define the shared region. The IPC modules use this
+ *  to make portable pointers. All processors need to add this
+ *  call with their base address of the shared memory region.
+ *  If the processor cannot access the memory, do not add it.
+ */ 
+var SharedRegion = xdc.useModule('ti.sdo.ipc.SharedRegion');
+SharedRegion.setEntryMeta(0,
+    { base: SHAREDMEM, 
+      len:  SHAREDMEMSIZE,
+      ownerProcId: 0,
+      isValid: true,
+      name: "DDR2 RAM",
+    });
+
+/* PDK packages */
+var Csl = xdc.loadPackage('ti.csl');
+var Rm = xdc.loadPackage('ti.drv.rm'); 
+    
+