This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMS320F28027 - memcpy() ADC registers to a specific data ram location

Is there a way to memcpy the AdcRegs to a specific RAM location? (aka backup the entire AdcRegs block to RAM) I'm currently attempting to use the code below to copy the AdcRegs which are at address 0x007100 (size 128 bytes) to address 0x008800 which is allocated to the Data Page (1) via my linker file.

void * DRAM_L1 = (void *)0x008800;
void * ADC_Reg = (void *)0x007100;
EALLOW;
memcpy(DRAM_L1,ADC_Reg,128);
EDIS;

If I choose a different address like say 0x008000 then the contents of 0x008000 are copied just fine. Are their additional protections on the ADC Registers that would keep a memcpy from reading them?

Thanks,

  • Drew,

    Unfortunately the memcpy() won't work with registers.  This is because the memcpy() makes use of the PREAD assembly instruction in a repeat loop to get the fastest execution time.  In the disassembly window you'll see something like this:

          MOVL XAR4, @0x2c
          MOVL XAR7, @0x2a
          RPT #127
    ||    PREAD *XAR4++, *XAR7

    On C28x, the memory is unified, meaning it can be addressed in both program and data space, but the registers are not - they can only be reached from data space, so mempy is just reading zero from each location.

    What you can do is to use a for() loop to do the transfer.  Something like this should work:

          int i;

          EALLOW;

          for (i=0;i<128;)
          {
                *(int *)DRAM_L6++ = *(int *)ADC_Reg++;
          }
          EDIS;

    Regards;

    Richard

  • Richard,

    Thanks for the clarification on how to copy from register space to RAM. I was pretty sure that memcpy was the problem and other posts were saying things along the same lines about the PREAD function, I just didn't know a workaround. Your code suggestion is working out nicely. I actually created a small little function that handles the memory copy and I've listed it below if anyone else is interested.

    //! Peripheral Register Locations & Sizes
    #define  PRAM_L1_START			0x008800
    #define  ADC_START			    0x007100
    #define  ADC_LEN			    0x000080
    
    IEC_regcpy((int *)PRAM_L1_START, (int *)ADC_START, ADC_LEN);
    
    void IEC_regcpy(int * dest, int * src, uint16_t size) {
    	volatile uint16_t i;
    	EALLOW;
    	for (i=0;i<size;i++) {
    		*(int *)(dest++) = *(int *)(src++);
    	}
    	EDIS;
    }

    I have just one final question. *(int *) works just fine for RAM locations like 0x8800 but if I had an address like 0x3F6000 I would need to use a *(long *) or similar. When I convert the function above to do this, it does not copy correctly because it jumps memory locations 2 a time but is only copying in 1 byte segments. Any suggestions on how to make the function above support 32-bit addresses?

    Thanks,

  • Drew,

    You shouldn't have to make any changes to your code to access memory beyond 16-bits - it should work just fine with *(int *).  The pointer size is 32-bits regardless of the data size being addressed.  

    I'm running your code snippet above and it seems to work just fine for higher addresses.  Are you seeing any errors?

    Regards,

    Richard

  • Richard,

    Thanks for this clarification. I figured (incorrectly) that the pointer size would be 16-bits since the standard int size of C2000 is 16 bits. I just tested at higher memory, and I'm not seeing issues. Thanks again for your help on this. The code I pasted above is working nicely.

    Regards,