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.

MSP430FR5994: writing 20bit Address into DMA register fails + deviation asm to compiler guide

Part Number: MSP430FR5994

Dear all,

i have a problem im sure you can help me and is answered before - but i cant find this solution, so i hope you can give help me out.

My problem in short (as i understand it): i cant seem to write a 20bit address into a 32bit register even if using __data20_write_long . Also the assembler code generated deviates from the code shown in the compiler guide on p.137. I tried the suggested assembler code but it didnt work either.

More details to my problem: I would like to compute a crc32 over the whole programcode beginning at some address on an MSP430FR5994 (256kB). Therefore i would like to use the DMA to handle the CRC32 register, so i would like to write a fitting starting address to the DMAxSA register - which fails.


__data20_write_long((unsigned long) &DMA3SA, (unsigned long) 0x23fff);

//or this version taken from the compiler guide
__asm("	MOVA #DMA3SA+0, R15\n"
	"	MOVX.W #3FFFh, 0(R15)\n"
	"	MOVX.W #2, 2(R15)\n");

Both code snippets write into the DMA3SA register but only fill it with 0x3fff -> so only the 16bit part is written. The family data sheet says that it can take a 20bit address (how else would one use the DMA on the whole program space). I tried it with the TI-Compiler 20.2.7 and 21.6.0 and 21.6.1 - in all versions only the low 16bits are written into the source register. I dont know if the debugger can read 32bit from a register correctly but the executed code (which doesnt work as expected - starting at 0x4500 and not at 0x3fff) suggest that indeed there is no high byte in the register.

On an other hand, the created code for the __data20_write_long function deviates from the code written in the compiler guide as it only generates "MOV.W" commands. Since my assembler knowledge is nonexistent i dont know if this is relevant.

Hopefully you can help me find a solution.

Best wishes

Tobias

P.S.: In debug mode I can't write the correct value to the register either - is this behavior to be expected?

  • All word writes to the DMASA or DMADA registers will clear the upper 16 bits. I don't know why the compiler intrinsic function failed for you but it is obvious why the assembly did. It did two 16 bit writes. You have to get the 32 bit value into a register and then use MOVA or MOVX.A to perform the write to DMASA. For a constant value you can use: movx.a #23fffh,&DMASA.

  • Just by accident i stumbled over this post, where OP has the exact same problem... loading the SA and DA register of the DMA with values bigger than 16bit doesnt work even when using the __data20_write_long function (https://e2e.ti.com/support/tools/code-composer-studio-group/ccs/f/code-composer-studio-forum/917157/ccs-msp430fr5994-load-the-20-bit-dms-register-with-right-not-wrong-value).


    Dear David Schultz,

    thank you very much for the reply! The point about clearing the upper bits was something i was aware of as it is described in the family data sheet - but they are a bit tight lipped about what to do instead. With your hint i suspect, that the _data16_write_addr() function does it. First tests support it. Since my assembler is abysmal im not sure if it really does the job or just pretends:

    //this is approx my code inside a loop:
    start_address = old_address+256; //block of words i want to calculate the crc over for each run
    __data16_write_addr((unsigned short) &DMA3SA, (unsigned long) start_address);
    old_address = start_address;
    
    //this is the compiler version of the __data16_write_addr() part:
    //with DMA3SA = 0x0542
    //with start_adress = 0x4004f which is somehow in SP?
    asm("   MOV.W #0x0542,R15");
    asm("   MOVA 0x0000(SP),R14");
    asm("   MOVA R14,0x0000(R15)");

    I have no idea how i get my start_address into the register R15 but i guess i than could swap the __data16... line with asm(" movx.a R15,&DMA3SA");

    Thanks for your help! I would really appreciate it, if you could take a look if the assembler code done by the compiler is valid or if its just a fluke that it works. Sadly i still get a warning about converting from pointer to small integer (unsigned short = unsigned int = 16bit), even when using DMA3SAL which is 16bit. Also the name data16bit write address makes me uncomfortable to use it…

    Best wishes

    Tobias

  • GCC generates the following:

      __data16_write_addr(&DMA3SA, 0x23fff);
        4178:       b1 40 ff 3f     mov     #16383, 0(r1)   ;#0x3fff
        417c:       00 00 
        417e:       a1 43 02 00     mov     #2,     2(r1)   ;r3 As==10
    
    00004182 <.Loc.38.1>:
        4182:       3c 40 42 05     mov     #1346,  r12     ;#0x0542
        4186:       00 18 ec 41     movx.a  @r1,    0(r12)  ;
        418a:       00 00 
    

    The trick with a function call is getting a 20 bit argument where you can use it. The compiler prefers to pass arguments in registers, with a 32 bit arg in two registers. The only way to do that is to get it into memory. Hence the push to the stack.

    The appendix in slau646 just lists the intrinsic functions with no description of what they do or how they work. It appears that the data20 functions are badly named as they treat the 32 bit argument in the usual two 16 bit ints sort of way. The data16 function on the other hand does what you need.

    Grafting extra bits onto a 16 bit machine always has warts. Which is probably why I always preferred the 68000 to the 8086.

  • Dear David Schultz,

    thanks again for your time and reply! So to conclude, ill use the _data16_write_addr() function, which is named a bit misleading, and ill probably be fine with it. (Sorry, i dont understand what you want to show me with the assembler code above.)

    Best wishes

    Tobias

**Attention** This is a public forum