diff gsm-fw/L1/dsp/leadapi.c @ 558:565bf963c3a2

gsm-fw/L1/dsp/leadapi.[ch]: import from Leonardo semi-src
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Mon, 04 Aug 2014 17:58:49 +0000
parents
children 25a3095e8a98
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/gsm-fw/L1/dsp/leadapi.c	Mon Aug 04 17:58:49 2014 +0000
@@ -0,0 +1,503 @@
+/********************************************************************************
+            TEXAS INSTRUMENTS INCORPORATED PROPRIETARY INFORMATION           
+                                                                             
+  Property of Texas Instruments -- For  Unrestricted  Internal  Use  Only 
+   Unauthorized reproduction and/or distribution is strictly prohibited.  This 
+   product  is  protected  under  copyright  law  and  trade  secret law as an 
+   unpublished work.  Created 1987, (C) Copyright 1997 Texas Instruments.  All 
+   rights reserved.                                                            
+                 
+                                                           
+   Filename       	: leadapi.c
+
+   Description    	: Boot the LEAD through the API
+			  Target : Arm
+
+   Project        	: 
+
+   Author         	: A0917556
+
+   Version number	: 1.7
+
+   Date and time	: 01/30/01 10:22:25
+
+   Previous delta 	: 12/19/00 14:27:48
+
+   SCCS file      	: /db/gsm_asp/db_ht96/dsp_0/gsw/rel_0/mcu_l1/release_gprs/RELEASE_GPRS/drivers1/common/SCCS/s.leadapi.c
+
+   Sccs Id  (SID)       : '@(#) leadapi.c 1.7 01/30/01 10:22:25 '
+
+ 
+*****************************************************************************/
+
+
+#define LEADAPI_C  1
+
+#include "l1sw.cfg"
+#include "chipset.cfg"
+
+#if (OP_L1_STANDALONE == 0)
+  #include "main/sys_types.h"
+#else
+  #include "sys_types.h"
+#endif
+
+#include "memif/mem.h"
+#include "clkm/clkm.h"
+#include "leadapi.h"
+
+
+void LA_ResetLead(void) 
+{
+   (*(SYS_UWORD16 *) CLKM_CNTL_RST) |= CLKM_LEAD_RST; 
+}
+
+/*
+ * LA_StartLead 
+ *
+ * Parameter : pll is the value to set in the PLL register
+ */
+void LA_StartLead(SYS_UWORD16 pll)
+{
+   volatile int j;
+
+#if ((CHIPSET == 2) || (CHIPSET == 3) || (CHIPSET == 5) || (CHIPSET == 6) || (CHIPSET == 9))
+   // Set PLL    
+   (*(SYS_UWORD16 *) CLKM_LEAD_PLL_CNTL) = pll;
+
+   // Wait 100 microseconds for PLL to start
+   wait_ARM_cycles(convert_nanosec_to_cycles(100000));
+#endif
+
+   (*(SYS_UWORD16 *) CLKM_CNTL_RST) &= ~CLKM_LEAD_RST; 
+}
+
+
+/*
+ * LA_InitialLeadBoot16
+ *
+ * For RAM-based LEAD
+ * 
+ * Copy all sections to API 
+ * Dedicated with coff2c with 16-bit size and address (used with coff version 1 until DSP v1110)
+ */
+void LA_InitialLeadBoot16(const unsigned char bootCode[]) 
+{
+   int i;
+   SYS_UWORD16 *origin;
+   SYS_UWORD16 *destination;
+   SYS_UWORD16 *currentSection;
+
+   (*(SYS_UWORD16 *) CLKM_CNTL_RST) |= CLKM_LEAD_RST; // Reset Lead 
+
+   currentSection = (SYS_UWORD16*) bootCode;
+   
+   while (*currentSection != 0)     // *currentSection is "size"
+   {
+      origin = currentSection + 2;  // origin points on 1st word  of current section
+      destination = (SYS_UWORD16 *)
+         (BASE_API_ARM + ((*(currentSection+1) - BASE_API_LEAD) * 2));
+                                    // destination is "addr" in API 
+                                    // (*(currentSection+1) is "size" of current section
+
+      for (i=0 ; i< *currentSection ; i++) 
+      {
+          *destination = *origin++;
+          destination = destination + 1;  // destination is UNSIGNED16
+      }
+      currentSection = origin;
+   }
+}
+
+
+/*
+ * LA_InitialLeadBoot
+ *
+ * For RAM-based LEAD
+ * 
+ * Copy all sections to API 
+ * Dedicated with coff2c with 32-bit size and address (perl or v3 version used with coff version 2 from v1500)
+ * 
+ */
+void LA_InitialLeadBoot(const unsigned char bootCode[]) 
+{
+  int i;
+  short error = NULL;
+  SYS_UWORD16 size, size_ext;                // dsp_addr[0:15] and dsp_addr[16:31] of the current section as specified in bootCode[] array
+  SYS_UWORD16 dsp_address, dsp_ext_address;  // size[0:15] and size[16:31] of the current section as specified in bootCode[] array
+  SYS_UWORD16 *bootCodePtr, *destinationPtr; // pointer in bootCode[] array and pointer in the API (MCU addresses)
+  
+  (*(SYS_UWORD16 *) CLKM_CNTL_RST) |= CLKM_LEAD_RST;         // reset Lead 
+  
+  bootCodePtr = (SYS_UWORD16 *) bootCode;                    // initialisation of bootCodePtr on the first word of the C array
+  
+  if ( (NULL == *bootCodePtr++) && (NULL == *bootCodePtr++) ) { // NULL TAG detection
+    
+    if ( ( 3 == *bootCodePtr++) && (NULL == *bootCodePtr++) ) { // coff2c version number detection 
+      
+      // initialization for the first section
+      size            = *bootCodePtr++;
+      size_ext        = *bootCodePtr++;
+      dsp_address     = *bootCodePtr++;
+      dsp_ext_address = *bootCodePtr++;
+      
+      while (size != NULL) {                                    // loop until last section whose size is null
+	if ( (NULL == size_ext) && (NULL == dsp_ext_address) ) {// size and address must 16-bit values in LA_InitialLeadBoot() 
+	  destinationPtr = (SYS_UWORD16 *) (BASE_API_ARM + (dsp_address - BASE_API_LEAD) * 2); // destination in API from the MCU side
+	  
+	  for (i=0 ; i<size ; i++) {
+	    *destinationPtr++ = *bootCodePtr++;
+	  }
+	  
+	  // next section
+	  size            = *bootCodePtr++;
+	  size_ext        = *bootCodePtr++;
+	  dsp_address     = *bootCodePtr++;
+	  dsp_ext_address = *bootCodePtr++;
+	}
+	else {
+	  error   = LA_BAD_EXT_VALUE;
+	  size    = NULL;
+	}
+      }
+    }
+    else {
+      error = LA_BAD_VERSION;
+    }
+  }
+  else {
+    error = LA_BAD_TAG;
+  }
+  
+  if (error != NULL) {                                          // if an error was detected in the coff2c format,
+    LA_InitialLeadBoot16(bootCode);                             // try to download a coff-v1.0 coff2c output
+  }
+}
+
+
+/*
+ * LA_LoadPage
+ * 
+ * Final LEAD boot - needs to communicate with initial LEAD Boot program
+ *
+ * Copy all sections to API 
+ *
+ * Parameters : pointer to code, LEAD page, flag to start executing
+ * Return value : 0 for success, 1 for timeout
+ */
+short LA_LoadPage(const unsigned char code[], SYS_UWORD16 page, SYS_UWORD16 start) 
+{
+  int t;                                // time counter for synchronization
+  SYS_UWORD16 stat;                  // status parameter for synchronization
+  int i       = NULL;
+  short error = NULL;
+  SYS_UWORD16 current_block_size;    // size of the current block to be copied into API
+  int remaining_size32;                 // remaining size of the current section to be copied after the last block
+  int remaining_size_DSPpage32;         // size remaining in the current DSP page
+  int max_block_size;    //biggest block size used during the patch download
+  SYS_UWORD16 size, size_ext;                // size[0:15] and size[16:31] of the current section as specified in code[] array
+  SYS_UWORD16 dsp_address, dsp_ext_address;  // dsp_addr[0:15] and dsp_addr[16:31] of the current section as specified in code[] array
+  SYS_UWORD16 *codePtr, *destinationPtr;     // pointer in code[] array and pointer in the API (MCU addresses)
+    
+  codePtr = (SYS_UWORD16 *) code;                    // initialisation of codePtr on the first word of the C array
+  max_block_size = 0;
+  
+  if ( (NULL == *codePtr++) && (NULL == *codePtr++)) {  // NULL TAG detection
+    
+    if ( (3 == *codePtr++) && (NULL == *codePtr++)) {   // coff2c version number detection 
+      
+      // Set the data page 
+      //-------------------
+      // Wait until LEAD is ready
+      t = 0;
+      do
+	  {
+	    stat = *((volatile SYS_UWORD16 *) DOWNLOAD_STATUS);
+	    t++;
+	    if (t > LA_TIMEOUT)
+	      return(LA_ERR_TIMEOUT);
+	  }
+      while (stat != LEAD_READY);
+      
+      destinationPtr  = (SYS_UWORD16 *) BASE_API_ARM;
+      *destinationPtr = page;
+      *(volatile SYS_UWORD16 *) DOWNLOAD_STATUS = PAGE_SELECTION;
+   
+      // Code/Data download block by block
+      //-----------------------------------
+      do {                                                      // SECTION BY SECTION COPY
+	    size            = *codePtr++;
+        size_ext        = *codePtr++;
+        dsp_address     = *codePtr++;
+        dsp_ext_address = *codePtr++;
+      
+        remaining_size32 = (size_ext << 16) + size;             // reconstruction of the total 32-bit size of the section
+
+        while (remaining_size32) {                              // BLOCK BY BLOCK COPY
+
+          // Wait until LEAD is ready
+          t = 0;
+          do
+          {
+            stat = *((volatile SYS_UWORD16 *) DOWNLOAD_STATUS);
+            t++;
+            if (t > LA_TIMEOUT)
+              return(LA_ERR_TIMEOUT);    
+          }
+          while (stat != LEAD_READY);
+	  
+          // DSP address managment including the extended page
+          remaining_size_DSPpage32 = MAX_UINT - dsp_address +1; // calculate the max available size in the current DSP page (MAX_UINT=65535)
+          if (NULL == remaining_size_DSPpage32) {
+            dsp_address = 0;                                    // continue on the next DSP page
+            dsp_ext_address += 1;
+          }
+
+          // partitionning of the current section into blocks
+          if (remaining_size32 >= MAX_BLOCK_SIZE) { 
+            if (MAX_BLOCK_SIZE <= remaining_size_DSPpage32)
+              current_block_size = MAX_BLOCK_SIZE;              // block by block partitioning
+            else 
+              current_block_size = remaining_size_DSPpage32;
+          }
+          else { 
+            if(remaining_size32 <= remaining_size_DSPpage32)
+              current_block_size = remaining_size32;             // the end of the section fits and is copied
+            else
+              current_block_size = remaining_size_DSPpage32;
+          }
+	  
+          if ( current_block_size > max_block_size )
+          {
+            max_block_size = current_block_size;
+          }
+          
+          // set parameters in the share memory
+          *(volatile SYS_UWORD16 *) DOWNLOAD_SIZE     = current_block_size;
+          *(volatile SYS_UWORD16 *) DOWNLOAD_ADDR     = dsp_address;
+          *(volatile SYS_UWORD16 *) DOWNLOAD_EXT_PAGE = dsp_ext_address;
+
+          // perform the copy
+          destinationPtr  = (SYS_UWORD16 *) BASE_API_ARM;
+          for (i=0 ; i<current_block_size ; i++) {
+            *destinationPtr++ = *codePtr++;
+          }
+	  
+          // synchronize and prepare the next step
+          *(volatile SYS_UWORD16 *) DOWNLOAD_STATUS = BLOCK_READY;
+          dsp_address      += current_block_size;
+          remaining_size32 -= current_block_size;
+        }
+      } while ( (size != NULL) || (size_ext != NULL) );
+      
+      // Setting of the starting address if required
+      //---------------------------------------------
+      // Wait until LEAD is ready
+      t = 0;
+      do
+      {
+        stat = *((volatile SYS_UWORD16 *) DOWNLOAD_STATUS);
+        t++;
+        if (t > LA_TIMEOUT)
+          return(LA_ERR_TIMEOUT);    
+      }
+      while (stat != LEAD_READY);
+
+      /* the part of the API used for the download must be reseted at end of download */
+      /* in case some values are not initialized within API before DSP start:*/
+      /* DSP start after DOWNLOAD_SIZE is set to zero.*/
+      destinationPtr  = (SYS_UWORD16 *) BASE_API_ARM;
+      for (i=0 ; i<max_block_size ; i++) {
+        *destinationPtr++ = 0x0000;
+      }
+
+      if (start)
+      {
+        /* Set the last block, which is the starting address */   
+        *(volatile SYS_UWORD16 *) DOWNLOAD_SIZE     = 0;
+        *(volatile SYS_UWORD16 *) DOWNLOAD_ADDR     = dsp_address;
+        *(volatile SYS_UWORD16 *) DOWNLOAD_EXT_PAGE = dsp_ext_address;
+        *(volatile SYS_UWORD16 *) DOWNLOAD_STATUS   = BLOCK_READY;
+      }
+      
+      return(LA_SUCCESS);
+    }
+    else {
+      error = LA_BAD_VERSION;
+    }
+  }
+  else {
+    error = LA_BAD_TAG;
+  }
+  
+/*  if (error != NULL) { */                               // if an error was detected in the coff2c format,
+    error = LA_LoadPage16(code, page, start);         // try to download a coff-v1.0 coff2c output
+    return(error);                                    // and return its result
+/*  } */
+}
+
+
+/*
+ * LA_LoadPage16
+ * 
+ * Final LEAD boot - needs to communicate with initial LEAD Boot program
+ *
+ * Copy all sections to API 
+ *
+ * Parameters : pointer to code, LEAD page, flag to start executing
+ * Return value : 0 for success, 1 for timeout
+ */
+short LA_LoadPage16(const unsigned char code[], SYS_UWORD16 page, SYS_UWORD16 start) 
+{
+   int i = 0;
+   int remainingSize, currentBlockSize;
+   volatile int j;
+   int t;
+   int max_block_size;    //biggest block size used during the patch download
+
+   volatile SYS_UWORD16 *origin;
+   volatile SYS_UWORD16 *destination;
+   volatile SYS_UWORD16 *currentSection;
+   SYS_UWORD16 addr, size, stat;
+
+   currentSection = (SYS_UWORD16*) code;   /* Take GSM application s/w */
+   max_block_size = 0;
+
+   // Set the data page if needed
+   if (page == 1)
+   {
+      // Wait until LEAD is ready
+      t = 0;
+      do
+      {
+         stat = *((volatile SYS_UWORD16 *) DOWNLOAD_STATUS);
+         t++;
+         if (t > LA_TIMEOUT)
+            return(LA_ERR_TIMEOUT);
+            
+      }
+      while ( stat != LEAD_READY);
+
+      destination = (volatile SYS_UWORD16 *) BASE_API_ARM;
+      *destination = 1;
+      *(volatile SYS_UWORD16 *) DOWNLOAD_STATUS = PAGE_SELECTION;
+   }
+   
+
+   do
+   {                                   /* while there is a section to transfer */
+      origin = currentSection + 2;
+      size = *currentSection;
+      addr = *(currentSection+1);
+
+      remainingSize = size;
+      
+      while (remainingSize) 
+      {  
+         if (remainingSize > MAX_BLOCK_SIZE) 
+            currentBlockSize = MAX_BLOCK_SIZE;
+         else 
+            currentBlockSize = remainingSize;
+
+         /* Wait until LEAD is ready */
+         t = 0;
+         do
+         {
+            stat = *((volatile SYS_UWORD16 *) DOWNLOAD_STATUS);
+            t++;
+            if (t > LA_TIMEOUT)
+               return(LA_ERR_TIMEOUT);
+               
+         }
+         while (stat != LEAD_READY);
+
+         /* Set the block size and address in shared memory */   
+         *(volatile SYS_UWORD16 *) DOWNLOAD_SIZE = currentBlockSize;
+         *(volatile SYS_UWORD16 *) DOWNLOAD_ADDR = addr + size - remainingSize;
+
+         if ( currentBlockSize > max_block_size )
+         {
+             max_block_size = currentBlockSize;
+         }
+
+         /* Copy the block */
+         destination = (volatile SYS_UWORD16 *) BASE_API_ARM;
+         for (i=0 ; i< currentBlockSize ; i++) 
+         {
+            *destination = *origin++;     
+            destination += 1;  // API is really 16-bit wide for MCU now !
+         }
+
+         *(volatile SYS_UWORD16 *) DOWNLOAD_STATUS = BLOCK_READY;
+
+         remainingSize -= currentBlockSize;
+      }
+      currentSection = origin;
+   }
+   while (size != 0);
+
+   /* Wait until LEAD is ready */
+   t = 0;
+   do
+   {
+      stat = *((volatile SYS_UWORD16 *) DOWNLOAD_STATUS);
+      t++;
+      if (t > LA_TIMEOUT)
+         return(LA_ERR_TIMEOUT);
+         
+   }
+   while (stat != LEAD_READY);
+
+  
+   /* the part of the API used for the download must be reseted at end of download */
+   /* in case some values are not initialized within API before DSP start:*/
+   /* DSP start after DOWNLOAD_SIZE is set to zero.*/
+   destination  = (SYS_UWORD16 *) BASE_API_ARM;
+   for (i=0 ; i<max_block_size ; i++) {
+      *destination++ = 0x0000;
+   }
+
+   if (start)
+   {
+      /* Set the last block, which is the starting address */   
+      *(volatile SYS_UWORD16 *) DOWNLOAD_SIZE = 0;
+      *(volatile SYS_UWORD16 *) DOWNLOAD_ADDR = addr;
+      *(volatile SYS_UWORD16 *) DOWNLOAD_STATUS = BLOCK_READY;
+   }
+
+   return(LA_SUCCESS);
+}
+
+/*
+ * LeadBoot
+ *
+ * Start the LEAD without downloading any code
+ */
+short LeadBoot(SYS_UWORD16 entryPoint, SYS_UWORD16 pll)
+{
+   SYS_UWORD16 section[2];
+   short res;
+   
+   section[0] = 0;      // null size 
+   section[1] = entryPoint;
+   
+#if ((CHIPSET == 4) || (CHIPSET == 7) || (CHIPSET == 8) || (CHIPSET == 10) || (CHIPSET == 11) || (CHIPSET == 12))
+   CLKM_RELEASELEADRESET;
+#else
+   LA_StartLead(pll);
+#endif
+   
+   res = LA_LoadPage((const unsigned char *) section, 0, 1);
+   return(res);
+   
+}
+
+
+/*
+ * LA_ReleaseLead
+ *
+ */
+void LA_ReleaseLead(void)
+{
+  (*(unsigned short *) CLKM_CNTL_RST) &= ~CLKM_LEAD_RST;
+}