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.

Float points arithmetic on RAM MSP430F5438a

Other Parts Discussed in Thread: MSP430F5438A

I need to get some float results analyzing sensor data, I read that it is suggested to move those data into RAM memory, I modified my device linker comand file, and at the moment the function seems working..  I get my var back from the function and reading address it seems to be on RAM memory.
(I checked the block address, converting in decimal and compared var address with address in RAM memory).

My problem is that I need to send this var Through Uart and I would like to use the DMA module, but it seems that it doesn´t work.
I´m getting no one var on my serial monitor.
I attached how I modified the device linker comand file:

MEMORY
{
    SFR                     : origin = 0x0000, length = 0x0010
    PERIPHERALS_8BIT        : origin = 0x0010, length = 0x00F0
    PERIPHERALS_16BIT       : origin = 0x0100, length = 0x0100
    RAM_MEM                 : origin = 0x1C00, length = 0x0200
    RAM                     : origin = 0x1E00, length = 0x3E00
    INFOA                   : origin = 0x1980, length = 0x0080
    INFOB                   : origin = 0x1900, length = 0x0080
    INFOC                   : origin = 0x1880, length = 0x0080
    INFOD                   : origin = 0x1800, length = 0x0080
    FLASH_MEM               : origin = 0x5C00, length = 0x0200
    FLASH                   : origin = 0x5E00, length = 0xA180
    FLASH2                  : origin = 0x10000,length = 0x35C00
    INT00                   : origin = 0xFF80, length = 0x0002
    INT01                   : origin = 0xFF82, length = 0x0002
    INT02                   : origin = 0xFF84, length = 0x0002
    INT03                   : origin = 0xFF86, length = 0x0002
    INT04                   : origin = 0xFF88, length = 0x0002
    INT05                   : origin = 0xFF8A, length = 0x0002
    INT06                   : origin = 0xFF8C, length = 0x0002
    INT07                   : origin = 0xFF8E, length = 0x0002
    INT08                   : origin = 0xFF90, length = 0x0002
    INT09                   : origin = 0xFF92, length = 0x0002
    INT10                   : origin = 0xFF94, length = 0x0002
    INT11                   : origin = 0xFF96, length = 0x0002
    INT12                   : origin = 0xFF98, length = 0x0002
    INT13                   : origin = 0xFF9A, length = 0x0002
    INT14                   : origin = 0xFF9C, length = 0x0002
    INT15                   : origin = 0xFF9E, length = 0x0002
    INT16                   : origin = 0xFFA0, length = 0x0002
    INT17                   : origin = 0xFFA2, length = 0x0002
    INT18                   : origin = 0xFFA4, length = 0x0002
    INT19                   : origin = 0xFFA6, length = 0x0002
    INT20                   : origin = 0xFFA8, length = 0x0002
    INT21                   : origin = 0xFFAA, length = 0x0002
    INT22                   : origin = 0xFFAC, length = 0x0002
    INT23                   : origin = 0xFFAE, length = 0x0002
    INT24                   : origin = 0xFFB0, length = 0x0002
    INT25                   : origin = 0xFFB2, length = 0x0002
    INT26                   : origin = 0xFFB4, length = 0x0002
    INT27                   : origin = 0xFFB6, length = 0x0002
    INT28                   : origin = 0xFFB8, length = 0x0002
    INT29                   : origin = 0xFFBA, length = 0x0002
    INT30                   : origin = 0xFFBC, length = 0x0002
    INT31                   : origin = 0xFFBE, length = 0x0002
    INT32                   : origin = 0xFFC0, length = 0x0002
    INT33                   : origin = 0xFFC2, length = 0x0002
    INT34                   : origin = 0xFFC4, length = 0x0002
    INT35                   : origin = 0xFFC6, length = 0x0002
    INT36                   : origin = 0xFFC8, length = 0x0002
    INT37                   : origin = 0xFFCA, length = 0x0002
    INT38                   : origin = 0xFFCC, length = 0x0002
    INT39                   : origin = 0xFFCE, length = 0x0002
    INT40                   : origin = 0xFFD0, length = 0x0002
    INT41                   : origin = 0xFFD2, length = 0x0002
    INT42                   : origin = 0xFFD4, length = 0x0002
    INT43                   : origin = 0xFFD6, length = 0x0002
    INT44                   : origin = 0xFFD8, length = 0x0002
    INT45                   : origin = 0xFFDA, length = 0x0002
    INT46                   : origin = 0xFFDC, length = 0x0002
    INT47                   : origin = 0xFFDE, length = 0x0002
    INT48                   : origin = 0xFFE0, length = 0x0002
    INT49                   : origin = 0xFFE2, length = 0x0002
    INT50                   : origin = 0xFFE4, length = 0x0002
    INT51                   : origin = 0xFFE6, length = 0x0002
    INT52                   : origin = 0xFFE8, length = 0x0002
    INT53                   : origin = 0xFFEA, length = 0x0002
    INT54                   : origin = 0xFFEC, length = 0x0002
    INT55                   : origin = 0xFFEE, length = 0x0002
    INT56                   : origin = 0xFFF0, length = 0x0002
    INT57                   : origin = 0xFFF2, length = 0x0002
    INT58                   : origin = 0xFFF4, length = 0x0002
    INT59                   : origin = 0xFFF6, length = 0x0002
    INT60                   : origin = 0xFFF8, length = 0x0002
    INT61                   : origin = 0xFFFA, length = 0x0002
    INT62                   : origin = 0xFFFC, length = 0x0002
    RESET                   : origin = 0xFFFE, length = 0x0002
}

/****************************************************************************/
/* Specify the sections allocation into memory                              */
/****************************************************************************/

SECTIONS
{
    .bss        : {} > RAM                  /* Global & static vars              */
    .data       : {} > RAM                  /* Global & static vars              */
    .TI.noinit  : {} > RAM                  /* For #pragma noinit                */
    .sysmem     : {} > RAM                  /* Dynamic memory allocation area    */
    .stack      : {} > RAM (HIGH)           /* Software system stack             */

    .run_from_ram : load = FLASH_MEM, run = RAM_MEM /* CODE IN FLASH AND WILL BE COPIED
                                            TO RAM AT EXECUTION HANDLED BY
                                            USER */
//#ifndef __LARGE_DATA_MODEL__
    .text       : {}>> FLASH                /* Code                              */
//#else
    .text       : {}>> FLASH2 | FLASH       /* Code                              */
//#endif
    .text:_isr  : {} > FLASH                /* ISR Code space                    */
    .cinit      : {} > FLASH                /* Initialization tables             */
//#ifndef __LARGE_DATA_MODEL__
//    .const      : {} > FLASH                /* Constant data                     */
//#else
    .const      : {} > FLASH | FLASH2       /* Constant data                     */
//#endif
    .cio        : {} > RAM                  /* C I/O Buffer                      */

....... I didn´t modified the rest

In my .c fyle defined the function on ram as:

#pragma CODE_SECTION(Calculateacc,".run_from_ram")
void Calculateacc(volatile signed char *a,volatile signed char *b,volatile signed char *c)

I call that fuction as

 Calculateacc(&a,&b,&c);

where

volatile signed char a,b,c;

  • here is the DMA function:

    unsigned char DMA_transfer(buffer *pointer_buffer) //DATA WRITE/PUSH
    {
       int next = pointer_buffer->head + 1;
       if (next >= pointer_buffer->Num_Samples)
        next = 0;
       //buffer is full
        DMA0SZ =pointer_buffer->Num_Samples;
    //    __data20_write_long((unsigned long) &DMA0SA,(unsigned long) &d1);
        __data20_write_long((unsigned long) &DMA0SA,(unsigned long) & a);
        __data20_write_long((unsigned long) &DMA0DA,(unsigned long) &pointer_buffer->buffer[pointer_buffer->head]);
    	DMA0CTL |= DMAEN +DMAIE;                         // Enable DMA0
        DMA0CTL |= DMAREQ;                      // Trigger block transfer
        pointer_buffer->head = next;
        return 0;
    }
    void Uart_transfer(buffer *pointer_buffer)//DATA READ/POP
    {
    // if the head isn't ahead of the tail, we don't have any characters
     if (pointer_buffer->head == pointer_buffer->tail)
    // return -1;  // quit with an error (buffer empty)
      DMA1SZ =pointer_buffer->Num_Samples;
      __data20_write_long((unsigned long) &DMA1SA,(unsigned long) &pointer_buffer->buffer[pointer_buffer->tail]);
      __data20_write_long((unsigned long) &DMA1DA,(unsigned long) &UCA3TXBUF);
      DMA1CTL |= DMAEN; // // Enable DMA1
      DMA1CTL |= DMAREQ; // Trigger block transfer
      //pointer_buffer->buffer[pointer_buffer->tail]=0; //data remove from array location
      int next = pointer_buffer->tail + 1;
      if(next >= pointer_buffer->Num_Samples)
      next = 0;
      pointer_buffer->tail = next;
    
    }

    Suggestions are really apprecieted!!

  • Hi Dodz,

    It's pretty hard to tell what you are trying to accomplish with the information given and the complexity of the DMA setup. Can you use the IDE debugger to confirm that the DMA registers are being written with the expected values? You could also try to see what the UART buffer is outputting to the serial monitor as compared to what it should be doing. I don't know what size transfers you are trying to accomplish but I notice that you never increment the source or destination inside of the DMAxCTL registers, which could be part of your issue. I would recommend reviewing the MSP430F5438A DMA code examples to get a better grasp of how to complete this task.

    Regards,
    Ryan
  •       void DMA_init()
          {  	  // Setup DMA0 double buffer
          	 DMACTL0 = DMA0TSEL_0;                    // Timer B triggered
                                                     // Read-modify-write disable
          	 DMA0CTL &= ~DMAIFG;
          	 DMA0CTL =  DMADT_5 +//a complete block transfer requires a trigger from Timer B
          			    DMASRCINCR_3 +//Source address unchanged
    				    DMASRCBYTE +
    					DMAIE +
    					DMAEN +
          			    DMASBDB;//
          	 //DMA1 to UART
          	 DMACTL0 = DMA1TSEL_30; // DMA0 Trigger
          	 DMA1CTL = DMADT_5 +
          			  DMASRCINCR_3 +
          			  DMAEN +
          			  DMASBDB; //burst block transfer, inc src, enable

    unsigned char DMA_transfer(buffer *pointer_buffer) //DATA WRITE/PUSH
    {
    	int next = pointer_buffer->head + 1;
       if (next >= pointer_buffer->Num_Samples+1)
        next = 0;
       //buffer is full
        DMA0SZ =pointer_buffer->Num_Samples;
    //    __data20_write_long((unsigned short) &DMA0SA,(unsigned long) &d1);
    //   __data20_write_long((unsigned long) &DMA0SA,(unsigned long) &axg);
       __data20_write_long((unsigned long) &DMA0SA,(unsigned long) 0x001C26);
        __data20_write_long((unsigned long) &DMA0DA,(unsigned long) &pointer_buffer->buffer[pointer_buffer->head]);
    	DMA0CTL |= DMAEN;                         // Enable DMA0
    //    DMA0CTL |= DMAREQ;                      // Trigger block transfer
        pointer_buffer->head = next;
        return 0;
    }
    unsigned char Uart_transfer(buffer *pointer_buffer)//DATA READ/POP
    {
    // if the head isn't ahead of the tail, we don't have any characters
     if (pointer_buffer->head == pointer_buffer->tail)
     return -1;  // quit with an error (buffer empty)
      DMA1SZ =pointer_buffer->Num_Samples;
      __data20_write_long((unsigned long) &DMA1SA,(unsigned long) &pointer_buffer->buffer[pointer_buffer->tail]);
      __data20_write_long((unsigned long) &DMA1DA,(unsigned long) &UCA3TXBUF);
      DMA1CTL |= DMAEN; // // Enable DMA1
    //  DMA1CTL |= DMAREQ; // Trigger block transfer
      //pointer_buffer->buffer[pointer_buffer->tail]=0; //data remove from array location
      int next = pointer_buffer->tail + 1;
      if(next >= pointer_buffer->Num_Samples+1)
      next = 0;
      pointer_buffer->tail = next;
      return 0;
    }
    
    #pragma vector=TIMER0_B0_VECTOR
    __interrupt void TIMER0B0ISR(void)
    {
    //	DMA0CTL |= DMAEN;                         // Enable DMA0
        DMA0CTL |= DMAREQ;                      // Trigger block transfer
    	overflow=1;
     __bic_SR_register_on_exit(CPUOFF);
    }
    #pragma vector = DMA_VECTOR
    __interrupt void DMA_ISR(void)
    {
    DMA0CTL &= ~DMAIFG;
    //DMA1CTL |= DMAEN; // // Enable DMA1
    DMA1CTL |= DMAREQ; // Trigger block transfer
    counter++;
    	__bic_SR_register_on_exit(CPUOFF);
    }

    Hi Ryan, I decided to avoid float arithmetic, I switched to signed char to reduce complexity, the address of the var to print are

    axg=0x001C25

    ayg=0x001C26

    azg=0x001C27

    and I would like to get them printed in this order but when I read the buffer filled by the DMA I´m able to read

    [ayg azg ayg] if start address is ayg

    [0 axg 0] if the start address is axg

    this is my dma setup(observing texas examples):

  • Hello Dodz,

    Some notes on your DMA initialization:

    1) There are TB0 DMA trigger assignments (DMAxTSEL_5 or DMAxTSEL_6) so that you don't have to enter a TB0 ISR. However you overwrite your original DMACTL0 assignment by using = instead of |= so the current setup works out in your favor...just an FYI in case you ever wanted to use the TB0 DMA trigger as it was intended.
    2) The DMA ISR shouldn't be necessary since you set the DMA1 trigger select to DMA0IFG. I'm surprised that DMA1 is even being serviced.
    3) Both DMASRCBYTE and DMASBDB are unnecessary for DMA0CTL and is most likely causing the register's result to be incorrect. Make sure that the DMAxCTL registers are as expected in your debugger.
    4) What is DMAxSZ? It should be 3 since you are intending to send 3 bytes.
    5) What are the values of axg, ayg, and azg in your example?

    You're close to finding a solution but you will need to read the DMA chapter of the User's Guide and keep messing with your DMA settings until you find the correct match that sends the bytes correctly.

    Regards,
    Ryan
  • Thank you Rayan,
    I checked the register and I tryed to solved the setup configurations as you suggested to me, I read the chapter on the user guide to check the setup
    I wrote to differents setup I would like to follows yours because it seems to be more accurate but I wrote my working version that seems to be working. I will post both to know what do you think about that.
    my message will be : 255 4 axg ayg azg 255 2 (where axg ayg azg are 8 bit values  0-255) Using the first version I´m still not getting the right message.

          void DMA_init()
          {  	  // Setup DMA0 double buffer
          	 DMACTL0 |= DMA0TSEL_6;                    // Timer B triggered
                                                     // Read-modify-write disable
          	 DMA0CTL &= ~DMAIFG;
          	 DMA0CTL |=  DMADT_5 +//a complete block transfer requires a trigger from Timer B
    					DMAIE +
    					DMAEN;//
          	 //DMA1 to UART
          	 DMACTL0 |= DMA1TSEL_30; // DMA0 Trigger
          	 DMA1CTL |= DMADT_5 +
          			  DMAEN;// +
          	 }
    unsigned char DMA_transfer(volatile signed char *varadd, buffer *pointer_buffer) //DATA WRITE/PUSH
    {
    	int next = pointer_buffer->head + 1;
       if (next >= pointer_buffer->Num_Samples)
        next = 0;
       //buffer is full
        DMA0SZ =pointer_buffer->Num_Samples;
    //   __data20_write_long((unsigned long) &DMA0SA,(unsigned long) &ayg);
    //   __data20_write_long((unsigned long) &DMA0SA,(unsigned long) varadd);
        if (pointer_buffer->head==0)
        	  __data20_write_long((unsigned long) &DMA0SA,(unsigned long) &start[0]);
        if (pointer_buffer->head==1)
        	  __data20_write_long((unsigned long) &DMA0SA,(unsigned long) &start[1]);
       if (pointer_buffer->head==2)
       	  __data20_write_long((unsigned long) &DMA0SA,(unsigned long) &axg);
       if (pointer_buffer->head==3)
       	  __data20_write_long((unsigned long) &DMA0SA,(unsigned long) &ayg);
       if (pointer_buffer->head==4)
       	  __data20_write_long((unsigned long) &DMA0SA,(unsigned long) &azg);
       if (pointer_buffer->head==5)
       	  __data20_write_long((unsigned long) &DMA0SA,(unsigned long) &stop[0]);
       if (pointer_buffer->head==6)
       	  __data20_write_long((unsigned long) &DMA0SA,(unsigned long) &stop[1]);
        __data20_write_long((unsigned long) &DMA0DA,(unsigned long) &pointer_buffer->buffer[pointer_buffer->head]);
        DMA0CTL |= DMAREQ;                      // Trigger block transfer
        pointer_buffer->head = next;
        return 0;
    }
    
    unsigned char Uart_transfer(buffer *pointer_buffer)//DATA READ/POP
    {
    // if the head isn't ahead of the tail, we don't have any characters
     if (pointer_buffer->head == pointer_buffer->tail)
     return -1;  // quit with an error (buffer empty)
      DMA1SZ =pointer_buffer->Num_Samples;
      __data20_write_long((unsigned long) &DMA1SA,(unsigned long) &pointer_buffer->buffer[pointer_buffer->tail]);
      __data20_write_long((unsigned long) &DMA1DA,(unsigned long) &UCA3TXBUF);
      DMA1CTL |= DMAREQ; // Trigger block transfer
      //pointer_buffer->buffer[pointer_buffer->tail]=0; //data remove from array location
      int next = pointer_buffer->tail + 1;
      if(next >= pointer_buffer->Num_Samples)
      next = 0;
      pointer_buffer->tail = next;
      return 0;
    }
    
    #pragma vector=TIMER0_B0_VECTOR
    __interrupt void TIMER0B0ISR(void)
    {
    	overflow=1;
     __bic_SR_register_on_exit(CPUOFF);
    }
    #pragma vector = DMA_VECTOR
    __interrupt void DMA_ISR(void)
    {
    DMA0CTL &= ~DMAIFG;
    counter++;
    	__bic_SR_register_on_exit(CPUOFF);
    }

     

  • while this is my working version:

    unsigned char DMA_transfer(volatile signed char *varadd, buffer *pointer_buffer) //DATA WRITE/PUSH
    {
    int next = pointer_buffer->head + 1;
    if (next >= pointer_buffer->Num_Samples)
    next = 0;
    //buffer is full
    DMA0SZ =pointer_buffer->Num_Samples;
    // __data20_write_long((unsigned long) &DMA0SA,(unsigned long) &ayg);
    // __data20_write_long((unsigned long) &DMA0SA,(unsigned long) varadd);
    if (pointer_buffer->head==0)
    __data20_write_long((unsigned long) &DMA0SA,(unsigned long) &start[0]);
    if (pointer_buffer->head==1)
    __data20_write_long((unsigned long) &DMA0SA,(unsigned long) &start[1]);
    if (pointer_buffer->head==2)
    __data20_write_long((unsigned long) &DMA0SA,(unsigned long) &axg);
    if (pointer_buffer->head==3)
    __data20_write_long((unsigned long) &DMA0SA,(unsigned long) &ayg);
    if (pointer_buffer->head==4)
    __data20_write_long((unsigned long) &DMA0SA,(unsigned long) &azg);
    if (pointer_buffer->head==5)
    __data20_write_long((unsigned long) &DMA0SA,(unsigned long) &stop[0]);
    if (pointer_buffer->head==6)
    __data20_write_long((unsigned long) &DMA0SA,(unsigned long) &stop[1]);
    __data20_write_long((unsigned long) &DMA0DA,(unsigned long) &pointer_buffer->buffer[pointer_buffer->head]);
    DMA0CTL |= DMAEN; // Enable DMA0
    pointer_buffer->head = next;
    return 0;
    }
    unsigned char Uart_transfer(buffer *pointer_buffer)//DATA READ/POP
    {
    // if the head isn't ahead of the tail, we don't have any characters
    if (pointer_buffer->head == pointer_buffer->tail)
    return -1; // quit with an error (buffer empty)
    DMA1SZ =pointer_buffer->Num_Samples;
    __data20_write_long((unsigned long) &DMA1SA,(unsigned long) &pointer_buffer->buffer[pointer_buffer->tail]);
    __data20_write_long((unsigned long) &DMA1DA,(unsigned long) &UCA3TXBUF);
    DMA1CTL |= DMAEN; // // Enable DMA1
    //pointer_buffer->buffer[pointer_buffer->tail]=0; //data remove from array location
    int next = pointer_buffer->tail + 1;
    if(next >= pointer_buffer->Num_Samples)
    next = 0;
    pointer_buffer->tail = next;
    return 0;
    }

    #pragma vector=TIMER0_B0_VECTOR
    __interrupt void TIMER0B0ISR(void)
    {
    // DMA0CTL |= DMAEN; // Enable DMA0
    DMA0CTL |= DMAREQ; // Trigger block transfer
    overflow=1;
    __bic_SR_register_on_exit(CPUOFF);
    }
    #pragma vector = DMA_VECTOR
    __interrupt void DMA_ISR(void)
    {
    DMA0CTL &= ~DMAIFG;
    //DMA1CTL |= DMAEN; // // Enable DMA1
    DMA1CTL |= DMAREQ; // Trigger block transfer
    counter++;
    __bic_SR_register_on_exit(CPUOFF);
    }

    void DMA_init()
    { // Setup DMA0 double buffer
    DMACTL0 = DMA0TSEL_0; // Timer B triggered
    // Read-modify-write disable
    DMA0CTL &= ~DMAIFG;
    DMA0CTL = DMADT_5 +//a complete block transfer requires a trigger from Timer B
    // DMASRCINCR_3 +//Source address unchanged
    // DMASRCBYTE +
    // DMADSTBYTE +
    DMAIE +
    DMAEN +
    DMASBDB;//+
    //DMA1 to UART
    DMACTL0 = DMA1TSEL_30; // DMA0 Trigger
    DMA1CTL = DMADT_5 +
    DMAEN +
    DMASBDB; //burst block transfer, inc src, enable
    }

  • adding DMASBDB to DMA1CTL and DMA0CTL it works properly... thank you!

**Attention** This is a public forum