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.

TMS570LC4357: SCI reception with DMA

Part Number: TMS570LC4357

Hello. 

I'm trying to receive data from a SCI device and copy the data to the RAM using the DMA. I receive burst of data (length is unknown) from others equipements, and poll the copied data using a periodic thread. 

I set up a DMA transfer of 1byte as element size, 1 element per frame, the number of frame as the size (in byte) of the receiving buffer and activate the autoinitiation.

I understood from the documentation at "20.2.4 DMA Channel Control Packets" that the working control packet won't be up-to-date unless an arbitration occured. To do so, I run 2 'dummy' DMA transfert of 8bytes from RAM to RAM in parallel,  to force an arbitration of both FIFO. I don't use informations from FIFO A or B because it's not possible to make an atomic read of all the fifo's registers. 

I observe that forcing the arbitration works all the time but in one specific case : when the transfer completely fill the reception buffer and no more transfer occurs. 

Let's take an example, I use a 32byte reception buffer ( It's start at 0x80700100 and ends at 0x8070011f), the buffer is filled with 0xFF at startup. 

  1.  The reception buffer is : >ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff <

  2. A transfer of 18 bytes start (with values from 0x00 to 0x11)

  3. During the transfer, a read operation occurred :
      The reception  buffer is >00 01 02 03 04 05 06 07 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff <
      The CDADDR of the Working Control Packet is 0x80700108, which is OK.

  4. An another read operation occured after the end of the transmission:
      The reception  buffer is  >00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 ff ff ff ff ff ff ff ff ff ff ff ff ff ff <
      The CDADDR of the Working Control Packet is 0x80700112, which is OK and up to date.

  5. An another transfer of 14 bytes start ( with values from 0x11 to 0x1e)

  6. During the 2nd transfer, a read operation occurred :
      The reception  buffer is >00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 11 12 13 14 15 16 17 18 19 1a 1b ff ff ff <
      The CDADDR of the Working Control Packet is 0x8070011d, which is OK.

  7. An another read operation occured after the end of the transmission: 
      The reception  buffer is >00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 11 11 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e <. Completely filled.
      The CDADDR of the Working Control Packet is 0x8070011e, which is not up to date. (Even though the arbitration of both FIFOs were made multiple times)
      The Block Transfert Complete interruption was received. 
      The registers in the Working Control packet won't change until a another transfer occured.

Is that behaviour normal and expected from the DMA as I don't see any information about this specific case in the documentation ?

Meaning that when a block transfer is complete the Working control packet won't be updated in any case. 

Regards

  • Hi Jeff,

    First of all, i am suggesting you refer my explanation regarding CDADDR register behavior:

    (13) TMS570LC4357: What is the correct mechanism to use when receiving a data stream of unknown size bursts on an SCI link? - Arm-based microcontrollers - INTERNAL forum - Arm-based microcontrollers - INTERNAL - TI E2E support forums

    Now come to your issue, I don't understand how you are able to create the arbitration whenever you required.

    Can you please send your complete project for my debugging. And also, please provide the screenshot of the CDADDR register that you are verifying.

    --
    Thanks & regards,
    Jagadish.

  • Hello. Your link doesn't work, the page no longer exists. 

    I can't share you my whole project easily, but here the arbitration forcing part : 

    #define TRANSFERT_SIZE 8
    char buffer_src[TRANSFERT_SIZE];
    char buffer_dst[TRANSFERT_SIZE];
    char buffer_src2[TRANSFERT_SIZE];
    char buffer_dst2[TRANSFERT_SIZE];
    dma_ctrl_t ctrl_packet_dummy;
    dma_ctrl_t ctrl_packet_dummy2;
    
    void dummyTransfertInit()
    {
    
      /* - Pre configure the constant part of the transfert control packet  */
      ctrl_packet_dummy.CHCTRL    = 0;                              
      ctrl_packet_dummy.ELCNT     = 1;                              
      ctrl_packet_dummy.FRCNT  = TRANSFERT_SIZE;                    
      ctrl_packet_dummy.ELDOFFSET = 0;                              
      ctrl_packet_dummy.ELSOFFSET = 0;                              
      ctrl_packet_dummy.FRDOFFSET = 0;                              
      ctrl_packet_dummy.FRSOFFSET = 0;                              
      ctrl_packet_dummy.RDSIZE    = ACCESS_8_BIT;                   
      ctrl_packet_dummy.WRSIZE    = ACCESS_8_BIT;                   
      ctrl_packet_dummy.TTYPE     = BLOCK_TRANSFER ;                
      ctrl_packet_dummy.ADDMODERD = ADDR_INC1;                      
      ctrl_packet_dummy.ADDMODEWR = ADDR_INC1;                      
      ctrl_packet_dummy.AUTOINIT  = AUTOINIT_OFF;                   
      ctrl_packet_dummy.PORTASGN  = 0x2;
      ctrl_packet_dummy.SADD   = (uint32_t)buffer_src; 
      ctrl_packet_dummy.DADD   = (uint32_t)buffer_dst; 
    
      /* - Pre configure the constant part of the transfert control packet  */
      ctrl_packet_dummy2.CHCTRL    = 0;                 
      ctrl_packet_dummy2.ELCNT     = 1;                 
      ctrl_packet_dummy2.FRCNT  = sizeof(buffer_src2);  
      ctrl_packet_dummy2.ELDOFFSET = 0;                 
      ctrl_packet_dummy2.ELSOFFSET = 0;                 
      ctrl_packet_dummy2.FRDOFFSET = 0;                 
      ctrl_packet_dummy2.FRSOFFSET = 0;                 
      ctrl_packet_dummy2.RDSIZE    = ACCESS_8_BIT;      
      ctrl_packet_dummy2.WRSIZE    = ACCESS_8_BIT;      
      ctrl_packet_dummy2.TTYPE     = BLOCK_TRANSFER ;   
      ctrl_packet_dummy2.ADDMODERD = ADDR_INC1;         
      ctrl_packet_dummy2.ADDMODEWR = ADDR_INC1;         
      ctrl_packet_dummy2.AUTOINIT  = AUTOINIT_OFF;      
      ctrl_packet_dummy2.PORTASGN  = 0x2;
      ctrl_packet_dummy2.SADD   = (uint32_t)buffer_src2;
      ctrl_packet_dummy2.DADD   = (uint32_t)buffer_dst2;
    }
    
    void dummyTransfert()
    {
      dmaSetCtrlPacket(DMA_CH0,  &ctrl_packet_dummy);
      dmaSetCtrlPacket(DMA_CH1,  &ctrl_packet_dummy2);
    
      // Enable 2 DMA transfer with the higher priority  ...
      dmaSetChEnable(DMA_CH0, DMA_SW);
      dmaSetChEnable(DMA_CH1, DMA_SW);
    
      uint32_t swChanEnable;
      uint32_t bit_chan_0_1 = ( 1 << DMA_CH0) | ( 1 << DMA_CH1);
    
      // ... and wait for the transfer to be done.
      do
      {
         swChanEnable = dmaREG->SWCHENAS;
      } while ((swChanEnable & bit_chan_0_1) != 0x0);
    }
    

    The function dummyTransfertInit is called once at initialization, then I call  dummyTransfert when I want to force an arbitration. This function trigger 2 DMA transfert from ram to ram with channels 0 & 1 (which are the 2 most priority). The others DMA transfer use channel with higher number (ie: less priority).

    I retrieve the CDADDR value from the working control packet using the structure provided by a TI's example :

    dmaRAMREG->WCP[MY_CHANNEL].CDADDR

  • Hello. Your link doesn't work, the page no longer exists. 

    I converted the page in the link into pdf. Please refer it once.

    E2E_Thread.pdf

  • Hi Jeff,

    Apologies for the delay in my response.

    Today i got chance to test it. 

    My observation was this:
    once the entire DMA transfer was completed, i mean all the frame transfers were completed and that means no more pending transfers on the corresponding channel, in this case if this channel was interrupted by high priority channel, then there won't be any data copy into the working directory. This is what we should also expect that right, i mean working directory is only required if there were some pending transfers and it is not required if there were no more pending transfers.

    Here is my testing:

    I created one project with SCI DMA with 4 frames and 1 element. One frame will be transferred on each byte transfer into the RX register of SCI.

    And i am creating arbitration with memory-to-memory transfer as you given, and this arbitration will get triggered whenever i pressed user switch on my Launchpad.

    Scenario-1:

    On my first testing i am transferring 3 frames (3 bytes) to the SCI before triggering the arbitration.

    As you can see 3 bytes got moved and working control packets were with their previously tested values only. Now i am creating arbitration to see the updated values into the working control packets.

    As you can see CDADDR register is pointing 0x080015F3 because of we moved 3 bytes from the starting address of the 0x080015F0.

    And now i just sent the last frame also and then i triggered arbitration again and here is the result:

    As you can see there is no updating into the CDADDR register from their last values.

    Scenario-2:

     i am transferring 2 frames (2 bytes) to the SCI and then i am triggering arbitration and here is the result:

    As you can see CDADDR register is pointing 0x080015F2 because of we moved 3 bytes from the starting address of the 0x080015F0.

    And now i just sent the last two frames and then i triggered arbitration again and here is the result:

    As you can see there is no updating into the CDADDR register from their last values.

    So, in this way CDADDR register is not updating once all the transfers on the corresponding pending channel were completed.

    Here is my tested code for your reference:
    5228.SCI_DMA_LC4357.zip

    --
    Thanks & regards,
    Jagadish.

  • Hello.
    I'm glad that you observe the same behaviour than me ! :)

    But, at the end, my question was :  "Is that behaviour normal and expected from the DMA as I don't see any information about this specific case in the documentation ?"

    Regards

  • Hi Jeff,

    I agree with you that this specific case not covered clearly in documentation

    But this is expected behavior only. The working control packets will only helpful until the block transfer completes, once the block transfer completed there won't be any copy of addresses into the working control packets even though arbitration comes.

    --
    Thanks & regards,
    Jagadish.

  • Hello.
    I get your point, but in my case I'm using Auto-Initiation mode, so working control packets will be helpful after the block transfer completes, because further block are expected. 

    To make a correct software implementation using the DMA, I need to know it's behaviour. As you said yourself, this specific case is not covered clearly in the documentation, so I need to know what is implemented in the DMA. ( ie: The DMA won't ever the working control packet when a blocks is completed, no matters the configuration  ?)

    Regards

  • Hi Jeff,

    I get your point, but in my case I'm using Auto-Initiation mode, so working control packets will be helpful after the block transfer completes, because further block are expected. 

    Even though Auto-Initiation mode ON, the DMA channel will not directly go into the pending state, right? The channel will go to the pending state only after again receiving a new character request from SCI until then the channel will do auto initiation and just wait for new request from SCI right?

    I also want you to understand that there won't be any arbitration at all if the channel is not in pending state. I mean the channel won't get arbitrated by other transfer until it was in pending state. So that means if there is no arbitration and no more transfers into the working control packets right.

    --
    Thanks & regards,
    Jagadish.

  • Hi Jeff,

    Carlo asked the below question to me:

    I could summarize my question by: Will the DMA never update the working control packet when a blocks is completed, no matters the configuration?

    Ans)

    Yes, DMA will never update the working control packet when the block transfer is completed.

    As mentioned in TRM the working control images are updated only when the arbitration takes place right. If a DMA channel completes the configured number of transfers, then there won’t be any chance of channel arbitration by another channel, then there is no point of updating the working images.

    And even I tested this behavior in practical and got he same behavior as the TRM mentioned. And I updated the same behavior with screenshots in the e2e thread.

    --
    Thanks & regards,
    Jagadish.