4 Replies Latest reply on Oct 29, 2020 10:29 PM by AikoO_51

    PSoC 4 DMA Interrupt?

    MoTa_728816

      Hi,

       

      I've been studying the usage of DMA.

      And today, I'm stuck with DMA interrupt (or callback).

      What I would like to do is set an ISR or callback to be called after transfer completion.

       

      Although I think I set up my_dma_isr to be called at the transfer completion, it's never called.

      I wonder if there is/are more to be done to make this work.

      I would appreciate it if someone can teach me how to correctly set up this.

       

          DMA_Start((void*)source, destination) ;

          DMA_SetInterruptCallback(my_dma_isr) ;

       

      I've been trying with CY8CKIT-044.

       

      schematic

      001-schematic.JPG

      pins

      002-pins.JPG

       

      DMA Config

      003-DMA_Config_1.JPG

      004-DMA_Config_2.JPG

      Tera Term log

      Note: DMA transfer seems to be done OK, except the callback is not being called.

      005-TeraTerm-log.JPG

      Oscilloscope waveform

      Red: int_out signal, which is supposed to be the interrupt monitoring signal

      Yellow: TRO (Tr_out) signal

      IMG_4516.JPG

       

      main.c

      ===================

      #include "project.h"

      #include "stdio.h"

       

      #define STR_BUF_LEN 54

      char str[STR_BUF_LEN+1] ;

      void print(char *str)

      {

          UART_UartPutString(str) ;

      }

       

      void cls(void)

      {

          print("\x1b[2J\x1b[;H") ;

          CyDelay(1) ;

      }

       

      void splash(void)

      {

          cls() ;

          snprintf(str, STR_BUF_LEN, "DMA Test (%s %s)\n\r", __DATE__, __TIME__) ;

          print(str) ;

      }

       

      volatile uint8_t source[32] = { 0u } ;

      uint8_t destination[32] ;

       

      CY_ISR(my_dma_isr)

      {

          int_out_Write(1) ;

      }

       

      void dump_memory(void)

      {

          int i ;

          print("Src: ") ;

          for (i = 0 ; i < 10 ; i++ ) {

              snprintf(str, STR_BUF_LEN, "%02X ", source[i]) ;

              print(str) ;

          }

          print("\n\r") ;

          print("Dst: ") ;

          for (i = 0 ; i < 10 ; i++ ) {

              snprintf(str, STR_BUF_LEN, "%02X ", destination[i]) ;

              print(str) ;

          }

          print("\n\r\n\r") ;

          CyDelay(10) ;

      }

       

      void prepare_source(int offset)

      {

          int i ;

          for (i = 0 ; i < 8 ; i++ ) {

              source[i] = i + offset ;

          }

      }

       

      int main(void)

      {

          int i = 0 ;

         

          CyGlobalIntEnable; /* Enable global interrupts. */

       

          DMA_Start((void*)source, destination) ;

          DMA_SetInterruptCallback(my_dma_isr) ;

       

          UART_Start() ;

       

          splash() ;

          dump_memory() ;

         

          for(;;)

          {

              prepare_source(i) ;

       

              DMA_Trigger() ;

       

              CyDelay(1) ;

              int_out_Write(0) ;

              dump_memory() ;

              i = (i + 1) % 0x100 ;

              CyDelay(1000) ;

          }

      }

      ===================

       

      moto

        • 1. Re: PSoC 4 DMA Interrupt?
          AikoO_51

          It’s necessary this API, CyIntEnable(CYDMA_INTR_NUMBER), to enable DMA interrupt other than CyGlobalIntEnable.

          I tried the API, and then the ISR was worked.

          Also you can make sure of it on code example, DMA_UART_PSoC401.

          Please refer to the code example.

          • 2. Re: PSoC 4 DMA Interrupt?
            MoTa_728816

            Dear AikoO_51-san,

             

            Thank you very much for your answer!

            I modified my program as below and now I can observe that the interrupt is being generated!

             

            Oscilloscope waveform

            Red: int_out (driven from FW)

            Yellow: TRO (Tr_out)

            IMG_4517.JPG

             

            main.c

            ===========

            #include "project.h"

            #include "stdio.h"

             

            #define STR_BUF_LEN 54

            char str[STR_BUF_LEN+1] ;

            void print(char *str)

            {

                UART_UartPutString(str) ;

            }

             

            void cls(void)

            {

                print("\x1b[2J\x1b[;H") ;

                CyDelay(1) ;

            }

             

            void splash(void)

            {

                cls() ;

                snprintf(str, STR_BUF_LEN, "DMA Test (%s %s)\n\r", __DATE__, __TIME__) ;

                print(str) ;

            }

             

            volatile uint8_t source[32] = { 0u } ;

            uint8_t destination[32] ;

             

            CY_ISR(my_dma_isr)

            {

                int_out_Write(0) ;

            }

             

            void dump_memory(void)

            {

                int i ;

                print("Src: ") ;

                for (i = 0 ; i < 10 ; i++ ) {

                    snprintf(str, STR_BUF_LEN, "%02X ", source[i]) ;

                    print(str) ;

                }

                print("\n\r") ;

                print("Dst: ") ;

                for (i = 0 ; i < 10 ; i++ ) {

                    snprintf(str, STR_BUF_LEN, "%02X ", destination[i]) ;

                    print(str) ;

                }

                print("\n\r\n\r") ;

                CyDelay(10) ;

            }

             

            void prepare_source(int offset)

            {

                int i ;

                for (i = 0 ; i < 8 ; i++ ) {

                    source[i] = i + offset ;

                }

            }

             

            int main(void)

            {

                int i = 0 ;

              

                CyGlobalIntEnable; /* Enable global interrupts. */

              

                CyIntEnable(CYDMA_INTR_NUMBER) ; // <--- NEW

             

                DMA_Start((void*)source, destination) ;

                DMA_SetInterruptCallback(my_dma_isr) ;

             

                UART_Start() ;

             

                splash() ;

                dump_memory() ;

              

                for(;;)

                {

                    prepare_source(i) ;

             

                    int_out_Write(1) ;

                    DMA_Trigger() ;

                  

                    dump_memory() ;

                    i = (i + 1) % 0x100 ;

                    CyDelay(1000) ;

                }

            }

            ===========

             

            Best Regards,

            30-Oct-2020

            Motoo Tanaka

            • 3. Re: PSoC 4 DMA Interrupt?
              MoTa_728816

              Hi,

               

              Actually, what I wanted to test was

              (1) When a descriptor has multiple element(s) (for example 8)

              (2) Transfer mode is element per trigger

              (3) If the interrupt will be generated at the end of descriptor or at each transfer.

               

              So I modified the program as below

               

              main.c

              =======================

              #include "project.h"

              #include "stdio.h"

               

              #define STR_BUF_LEN 54

              char str[STR_BUF_LEN+1] ;

              void print(char *str)

              {

                  UART_UartPutString(str) ;

              }

               

              void cls(void)

              {

                  print("\x1b[2J\x1b[;H") ;

                  CyDelay(1) ;

              }

               

              void splash(void)

              {

                  cls() ;

                  snprintf(str, STR_BUF_LEN, "DMA Test (%s %s)\n\r", __DATE__, __TIME__) ;

                  print(str) ;

              }

               

              volatile uint8_t source[32] = { 0u } ;

              uint8_t destination[32] ;

              volatile int dma_done_flag = 0 ;

               

              CY_ISR(my_dma_isr)

              {

                  dma_done_flag = 1 ;

              }

               

              void dump_memory(void)

              {

                  int i ;

                  print("Src: ") ;

                  for (i = 0 ; i < 10 ; i++ ) {

                      snprintf(str, STR_BUF_LEN, "%02X ", source[i]) ;

                      print(str) ;

                  }

                  print("\n\r") ;

                  print("Dst: ") ;

                  for (i = 0 ; i < 10 ; i++ ) {

                      snprintf(str, STR_BUF_LEN, "%02X ", destination[i]) ;

                      print(str) ;

                  }

                  print("\n\r\n\r") ;

                  CyDelay(10) ;

              }

               

              void prepare_source(int offset)

              {

                  int i ;

                  for (i = 0 ; i < 8 ; i++ ) {

                      source[i] = i + offset ;

                  }

              }

               

              int main(void)

              {

                  int i = 0 ;

                  int j = 0 ;

                 

                  CyGlobalIntEnable; /* Enable global interrupts. */

                 

                  CyIntEnable(CYDMA_INTR_NUMBER) ;

               

                  DMA_Start((void*)source, destination) ;

                  DMA_SetInterruptCallback(my_dma_isr) ;

               

                  UART_Start() ;

               

                  splash() ;

                  dump_memory() ;

                 

                  for(;;)

                  {

                      prepare_source(i) ;

               

               

                      while(dma_done_flag == 0) {

                          DMA_Trigger() ;

                          CyDelayUs(1) ;

                      }

               

               

                      int_out_Write(1) ;

                      CyDelayUs(1) ;

                      int_out_Write(0) ;

                      dma_done_flag = 0 ;

                     

                      dump_memory() ;

                      i = (i + 1) % 0x100 ;

                      CyDelay(1000) ;

                  }

              }

              =======================

               

              The result oscilloscope wave form was

              IMG_4518.JPG

              So I could confirm that the interrupt was generated at the end of the descriptor not at the end of each tranfer.

               

              moto

              1 of 1 people found this helpful
              • 4. Re: PSoC 4 DMA Interrupt?
                AikoO_51

                That's good to hear.

                Thank you for sharing your escalation.