zoukankan      html  css  js  c++  java
  • Timer-triggered memory-to-memory DMA transfer demonstrator

    http://www.efton.sk/STM32/bt.c

    // Timer-triggered memory-to-memory DMA transfer demonstrator for STM32F4xx (probably good enough for STM32F2xx too)
    // Note, that we won't use the memory-to-memory mode here, as that would simply run not waiting for the triggers
    // To be run in debugger, watching the dst array to being gradually filled, one word each time the trigger reloads
    //   (and perhaps watching a cycle-counter to see how the timer's ARR setting influences the total time)
    
    // (C)2014 by wek at efton dot sk
    // Legalese: do whatever you want with this
    
    
    #include "stm32f4xx.h"
    #include <stdint.h>
    
    #define TIMER 1
    
    #if (TIMER == 1)
      #define _DMA_     2
      #define _Stream_  5
      #define _Channel_ 6
    #elif (TIMER == 2)  // this won't work, as DMA1 can't transfer
      #define _DMA_     1
      #define _Stream_  1
      #define _Channel_ 3
    #else
      #error "no such"
    #endif
    
    
    #define GLUE5_(a, b, c, d, e) a ## b ## c ## d ## e
    #define GLUE5(a, b, c, d, e) GLUE5_(a, b, c, d, e)
    #define GLUE4(a, b, c, d) GLUE5_(a, b, c, d, )
    
    #define DBGMCU_APBxFZ GLUE4(DBGMCU->APB, _DMA_, FZ, )
    #define DBGMCU_APB1_FZ_DBG_TIMy_STOP GLUE4(DBGMCU_APB1_FZ_DBG_TIM, TIMER, _STOP, )
    
    #define RCC_AHB1ENR_DMAxEN GLUE4(RCC_AHB1ENR_DMA, _DMA_, EN, )
    
    #define DMAx GLUE4(DMA, _DMA_, , )
    
    #define DMAStream GLUE4(DMA, _DMA_, _Stream, _Stream_)
    
    #if (_Stream_ < 4)
      #define yISR LISR
    #else
      #define yISR HISR
    #endif
    
    #define DMA_yISR_TCIFz GLUE4(DMA_, yISR, _TCIF, _Stream_)
    
    
    
    #define TIMz GLUE4(TIM, TIMER, , )
    
    #define APBxENR GLUE4(APB, _DMA_, ENR, )
    
    #define RCC_APBxENR_TIMzEN GLUE5(RCC_APB, _DMA_, ENR_TIM, TIMER, EN)
    
    
    #define BUFSIZE 10
    
    volatile uint32_t src[BUFSIZE] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
    volatile uint32_t dst[BUFSIZE];
    
    
    
    int main(void) {
    
    
    //  DBGMCU->APB2FZ |= DBGMCU_APB1_FZ_DBG_TIM1_STOP;
      DBGMCU_APBxFZ |= DBGMCU_APB1_FZ_DBG_TIMy_STOP;
    
    // TIM1_UP -> DMA2 Stream5 Channel6
        RCC->AHB1ENR |= RCC_AHB1ENR_DMAxEN;
        while (!(RCC->AHB1ENR & RCC_AHB1ENR_DMAxEN));
    
    
    
        DMAStream->NDTR = BUFSIZE;  // halfwords to transfer
        DMAStream->M0AR = (uint32_t)src;
        DMAStream->PAR = (uint32_t)dst;
        DMAStream->FCR = 0
          | ( 0                       * DMA_SxFCR_DMDIS )     // direct mode
          | (DMA_SxFCR_FTH__FULL      * DMA_SxFCR_FTH_0 )     // [irrelevant - keep it full]
          | ( 0                       * DMA_SxFCR_FEIE  )     // no interrupt
        ;
    
        DMAStream->CR = 0
          | (_Channel_                * DMA_SxCR_CHSEL_0   )  // channel select
          | (DMA_SxCR_xBURST_INCR1    * DMA_SxCR_MBURST_0  )  // memory burst (only in FIFO mode)
          | (DMA_SxCR_xBURST_INCR1    * DMA_SxCR_PBURST_0  )  // peripheral burst (only in FIFO mode)
          | (0                        * DMA_SxCR_ACK       )  // "reserved" (says manual)
          | (0                        * DMA_SxCR_CT        )  // current target (only in double-buffer mode)
          | (0                        * DMA_SxCR_DBM       )  // double-buffer mode
          | (DMA_SxCR_PL_PRIORITY_VERY_HIGH * DMA_SxCR_PL_0      )  // priority level
          | (0                        * DMA_SxCR_PINCOS    )  // peripheral increment offset size (only if peripheral address increments, FIFO mode and PBURST is 0)
          | (DMA_SxCR_xSIZE_WORD      * DMA_SxCR_MSIZE_0   )  // memory data size; in direct mode forced to the same value as PSIZE
          | (DMA_SxCR_xSIZE_WORD      * DMA_SxCR_PSIZE_0   )  // peripheral data size
          | (1                        * DMA_SxCR_MINC      )  // memory address increments
          | (1                        * DMA_SxCR_PINC      )  // peripheral address increments
          | (0                        * DMA_SxCR_CIRC      )  // circular mode (forced to 1 if double-buffer mode, forced to 0 if flow control is peripheral)
          | (DMA_SxCR_DIR_M2P         * DMA_SxCR_DIR_0     )  // data transfer direction
          | (0                        * DMA_SxCR_PFCTRL    )  // peripheral is the flow controller (i.e. who determines end of transfer) - only for SDIO
          | (0                        * DMA_SxCR_TCIE      )  // transfer complete interrupt enable
          | (0                        * DMA_SxCR_HTIE      )  // half transfer interrupt enable
          | (0                        * DMA_SxCR_TEIE      )  // transfer error interrupt enable
          | (0                        * DMA_SxCR_DMEIE     )  // direct mode error interrupt enable
          | (1                        * DMA_SxCR_EN        )  // stream enable        ;
        ;
    
    
    
      RCC->APBxENR |= RCC_APBxENR_TIMzEN;
    
    
      TIMz->PSC = 0;  // clk is 16MHz, no prescaler
      TIMz->ARR = 100;   // -> the whole 10-beat DMA transfer takes cca 1000 clk
      TIMz->DIER = TIM_DIER_UDE;   /* Update DMA enable */
      TIMz->CR1 = TIM_CR1_CEN;   /* Counter enable */
    
    
      while (!(DMAx->yISR & DMA_yISR_TCIFz));    // wait until DMA transfer finishes
    
      __NOP();  // place "finished" breakpoint here
    
      while(1) {
    
      }
    
    }
  • 相关阅读:
    EasyNetQ使用(三)【Publish与Subcribe】
    EasyNetQ使用(二)【连接RabbitMQ,SSL连接,Logging】
    EasyNetQ使用(一)【介绍】
    .net core使用EasyNetQ做EventBus
    .NET Core微服务之开源项目CAP的初步使用
    CAP 介绍及使用【视频】
    .NET Core 事件总线,分布式事务解决方案:CAP
    微服务中的异步消息通讯
    使用 Metrics.net + influxdb + grafana 搭建项目自动化监控和预警方案
    编写高效的jQuery代码
  • 原文地址:https://www.cnblogs.com/shangdawei/p/4749321.html
Copyright © 2011-2022 走看看