This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

external memory write time

Hello,

I'm trying to move memory from the ADC result result (ADDAT) to external memory (on BUSCON3) ASAP. I'm using the C167HSE Phycore module. From the data sheet for the external RAM, it says that it can write within 10ns, although it didn't specify how many bytes within that 10ns time frame. The fastest result I can achieve for writing from ADDAT to external memory is 10us using xmemcpy, which was verified through the oscilloscope. I even tried to move the data w/o using xmemcpy but the result is still the same. I also tried to tweak the BUSCON3 settings in .a66 file but still no luck. Does anyone have any ideas? Thanks in advance.

Shane

Parents
  • Chris,

    One of my project requirement is to collect around 500KB worth of data from an ADC channel; therefore, only the external RAM has the capacity to do so. After thinking about what you said, maybe PEC isn't such a good idea since PEC buffer is of type sdata where external RAM is of type xhuge.

    Right now, my problem is trying to minimize the time it takes to move data from ADDAT into the external RAM. 10us to move data from ADDAT to external RAM is way too long. Is there any method to reduce it to 1us or less with a 40MHz processor speed?

    Just FYI, Aater collecting 500KB of data, it will send it to a PC program through Ethernet.

    With that being said, will mapping /CS3 to the first segment still be beneficial? If yes, could you please provide me some example? Thanks.

Reply
  • Chris,

    One of my project requirement is to collect around 500KB worth of data from an ADC channel; therefore, only the external RAM has the capacity to do so. After thinking about what you said, maybe PEC isn't such a good idea since PEC buffer is of type sdata where external RAM is of type xhuge.

    Right now, my problem is trying to minimize the time it takes to move data from ADDAT into the external RAM. 10us to move data from ADDAT to external RAM is way too long. Is there any method to reduce it to 1us or less with a 40MHz processor speed?

    Just FYI, Aater collecting 500KB of data, it will send it to a PC program through Ethernet.

    With that being said, will mapping /CS3 to the first segment still be beneficial? If yes, could you please provide me some example? Thanks.

Children
  • Transferring a word to xhuge memory shouldn't take much longer than 1 us. Try something like this:

    unsigned int xhuge adc_results[100000];
    unsigned int xhuge *adc_ptr = adc_results;
    
    /* ADC conversion done ISR */
    void adc_isr(void) interrupt ADC_INT
    {
        /* reload ADC control registers if you must */
    
        /* save conversion result: */
        *adc_ptr++ = ADDAT;
    }
    

    That should do it. I don't think this will generate a lot of slow code.

    - mike

  • First, here are the bus settings that Phytec has called out for /CS3 "BUSCON3 = 0x04AF".

    So you have the solution provided by Mike which is perfectly fine. But this requires your code to service the ADC interrupt on every conversion (every 10usec). If this is not a problem then no need to continue.

    The alternative that I was thinking of would be to give up a block (actually two) of internal RAM (or XRAM) as an intermediate step to hold the ADC results and service it as a block transfer. The PEC would be used to move the ADC result after every conversion to the internal RAM (as an injected MOV until the temporary block of data is filled). The final PEC move would post the interrupt that is serviced by software. So for example, to have 262,144 results (512K of data) you could choose the transfer count to be 64. This means you would only vector to the ADC interrupt once out of 64 conversions or every 640usecs. Then the data movement to external RAM from internal RAM would be outside of the interrupt and consist of 4096 transactions (64 word transfer each transaction).

    #define BUF_SIZE (64)
    #define LIMIT (4096)
    
    extern unsigned int xhuge adc_results[];
    extern unsigned int xhuge *adc_ptr;
    
    bit bufferSelect;
    bit taskADCMove;
    unsigned int sdata adc_temp1[BUF_SIZE];
    unsigned int sdata adc_temp2[BUF_SIZE];
    unsigned int sdata *adc_temp_ptr;
    unsigned int sdata *adc_unload_ptr;
    unsigned int sdata transactions;
    
    /* Initialize ADC */
    void InitADC(void)
    {
      ADCON    =  0xC290;
      ADCIC    =  0x007A;       /* Use PEC channel 2 for ADC Conv INT:  */
      PECC2    =  0x0200 | BUF_SIZE;     /* load PEC2 control register */
      SRCP2    =  (unsigned int) (&ADDAT);         /* set source pointer */
      DSTP2    =  (unsigned int) (adc_temp1);  /* set destination pointer */
      bufferSelect = 0;
      transactions = 0;
      ADCON    |= 0x0080;                 /* set start bit */
    }
    
    
    /* ADC conversion complete ISR */
    void ADC_conversion_complete_ISR (void) interrupt 0x28 {
    
      PECC2  =  0x0200 | BUF_SIZE;          /* load PEC2 control register */
      SRCP2  =  (unsigned int) (&ADDAT);   /* set source pointer */
    
      bufferSelect ^= 1;                   /* move to alternate buffer */
    
      if (bufferSelect == 1) {
        DSTP2 = (unsigned int) (adc_temp2);  /* set destination pointer */
        adc_unload_ptr = adc_temp1;
      }
      else {
        DSTP2 = (unsigned int) (adc_temp1);  /* set destination pointer */
        adc_unload_ptr = adc_temp2;
      }
    
      taskADCMove = 1;         /* inform kernel of ADC move task is ready */
    }
    
    /* routine to move data to external RAM */
    void ADCMoveTask(void)
    {
      short i;
    
      for (i = 0; i < BUF_SIZE; i++) {
         *adc_ptr++ = *adc_unload_ptr;
      }
    
      if (++transactions > LIMIT-1) {
        ADCON &= 0xFF7F;
        /* issue task to move data across Ethernet */
      }
    }
    
    
    void TaskLoop(void) {
    
       for(;;) {   /* run state machine forever */
    
        if (taskADCMove == 1) {
          taskADCMove = 0;
          ADCMoveTask();
        }
      }
    }
    

    -Chris