|
楼主 |
发表于 2013-11-6 18:08:59
|
显示全部楼层
本帖最后由 Gorgon_Meducer 于 2013-12-31 11:17 编辑
Sensor Hub 硬件触发的例子
应用场景描述:
我们来用DMA配合信号系统来构建一个芯片梦游的例子。是的,梦游,整个过程中,CPU都处于休眠状态。
应用是这个样子的:
a. CPU完成最初DMA和信号网络的配置以后就进入休眠模式并不再唤醒。
b. 假设外部有一个传感器,该传感器通过SPI从机模式与芯片通信,当传感器完成数据采样后,会拉高信号
线EXT_REQ(熟悉手机内部应用的人都很清楚这种结构,一般也把这根信号叫做中断信号) 。
c. 芯片在EXT_REQ的上升沿回复系统时钟,但并不唤醒内核,随后该信号触发DMA完成一次数据传送,
用以开启SPI的时钟。
d. 当SPI时钟开启后,由于发送缓冲中(TX_FIFO)预先填充了7个字节的数据,通信立即开始。
e. 在SPI通信的过程中,由于接受缓冲不为空,RX_FIFO_DAVL(RX FIFO Data Available)信号为高,该
信号持续触发DMA及时的将SPI接受缓冲中的数据搬运到指定的SRAM缓冲区内
f. 当SPI通信结束后,帧结束信号FRM_EXCHANGE将触发 DMA将 SPI的时钟关闭,并在关闭时钟后,预先
填充下一次通讯所需的7个字节的数据到SPI的发送缓冲中。由于SPI时钟已经关闭,FIFO仍然能操作,
但是数据却要等到下一次时钟恢复时才能发送了。
g. 当所有外设完成工作后,系统重新进入休眠模式。
可以看到,整个过程中内核并未参与。如果不需要数据处理,芯片只是采集传感器信息,集中后,以固定
的频率(比如100Hz)发送给主控芯片,那么仍然不需要涉及到内核。如果需要简单的数据处理,那么内核
可以在必要的时候唤醒,快速完成功能后重新进入休眠。这种思想,就是我在另外一个帖子里面提到的脉冲
工作模式。
- void dma_cfg(void)
- {
- static uint32_t wSrc0 @0x20008004 = 0;
- static uint32_t wSrc1 @0x20008008 = 1;
- static uint32_t wOutputBuffer[8] @0x2000800C = {0xAC,0,1,2,3,4,5};
- static uint32_t wInputBuffer[8] @0x20008104 ;
- //!< init dma
- DMA_CHN_CFG(
- DMA_CHANNEL0, //!< channel0
- DMA_CHN_TRIG_RISING_EDGE_SENSITIVE ,
- //! Open SPI0 P_CLK
- DMA_TSF_CFG(
- DMA_TSF_MODE_MEMORY_TO_PERIPHRAL |
- DMA_TSF_MANUAL_TRIGGER_NEXT |
- DMA_TSF_DATA_BITS_32 ,
- 1 ,
- &wSrc1 ,
- &GSP_CMC.PCLKDIV[PCLK_SPI0].Value
- ),
- );
-
- DMA_CHN_CFG(
- DMA_CHANNEL1, //!< channel1
- DMA_CHN_TRIG_RISING_EDGE_SENSITIVE |
- DMA_CHN_BURST_TRANSFER |
- DMA_CHN_BURST_SIZE_1 ,
- //! read spi data CMD(Ignored) + 6 Bytes
- DMA_TSF_CFG(
- DMA_TSF_MODE_PERIPHRAL_TO_MEMORY |
- DMA_TSF_MANUAL_TRIGGER_NEXT |
- DMA_TSF_DATA_BITS_32 ,
- 7 ,
- &GSP_SPI0.DR.Value ,
- wInputBuffer
- ),
- );
- //!< init dma
- DMA_CHN_CFG(
- DMA_CHANNEL2, //!< channel2
- DMA_CHN_TRIG_RISING_EDGE_SENSITIVE ,
- //! disable SPI P_CLK
- DMA_TSF_CFG(
- DMA_TSF_MODE_MEMORY_TO_PERIPHRAL |
- DMA_TSF_AUTO_TRIGGER_NEXT |
- DMA_TSF_DATA_BITS_32 ,
- 1 ,
- &wSrc0 ,
- &GSP_CMC.PCLKDIV[PCLK_SPI0].Value
- ),
- //! fill spi fifo with CMD + 6 Bytes(Dummy write for spi read)
- DMA_TSF_CFG(
- DMA_TSF_MODE_MEMORY_TO_PERIPHRAL |
- DMA_TSF_MANUAL_TRIGGER_NEXT |
- DMA_TSF_DATA_BITS_32 ,
- 7 ,
- wOutputBuffer ,
- &GSP_SPI0.DR.Value
- ),
- );
- }
- void spi_dma_test_init(void)
- {
- ...
- // enable dma
- PM_AHB_CLK_ENABLE(AHBCLK_DMA);
- IO_CFG(
- {PA7, IO_WORKS_AS_APIO0, IO_PULL_UP},
- {PA1, IO_WORKS_AS_SPI0_SCK, IO_PULL_UP},
- {PA2, IO_WORKS_AS_SPI0_MISO, IO_PULL_UP},
- {PA3, IO_WORKS_AS_SPI0_MOSI, IO_PULL_UP},
- {PA4, IO_WORKS_AS_SPI0_CS, IO_PULL_UP},
- );
-
- SPI_CFG(
- SPI0,
- SPI_MODE_MASTER |
- SPI_MODE_FORMAT_SPI |
- SPI_MODE_CLK_IDLE_LOW |
- SPI_MODE_SAMP_SECOND_EDGE,
- SPI_MODE_DATASIZE_8,
- SPI_PCLK_DIV_1
- );
- SPI0.Open(); //!< enable spi0
- PM_PCLK_SET(PCLK_SPI0,0); //!< disable P_CLK for SPI manually
-
- //! fill spi fifo with CMD + 6 Bytes(Dummy write for spi read)
- SPI0.Write(0xAC);
- SPI0.Write(0x00);
- SPI0.Write(0x01);
- SPI0.Write(0x02);
- SPI0.Write(0x03);
- SPI0.Write(0x04);
- SPI0.Write(0x05);
-
- //! signal connection
- SIGNAL_CFG(
- /*----------------------------------------------------------------------------------------------*
- * SIGNAL Source Signal Usage Digtal Filter *
- *----------------------------------------------------------------------------------------------*/
- /*! \note Use the raising edge of APIO0 to trigger DMA Channel0, the APIO0 is connected to
- * PA7 in IO_CFG(). It is the trigger signal called EXT_REQ in the wave form.
- */
- { SIGNAL0, USE_SIGNAL_APIO0, TO_TRIGGER_DMA0_CHN0, ON_RAISING_EDGE },
- /*! \note When there are any data available in SPI0 RX FIFO (signal gose high), general pulse
- * to trigger DMA channel2 to fetch data from spi. Here EVERY_5_TIMES is the pulses
- * prescaler, which means the pulse frequency is the 1/5 of the system clock.
- */
- { SIGNAL1, USE_SPI0_RX_FIFO_DAVL, TO_TRIGGER_DMA0_CHN1, ON_HIGH_LEVEL | EVERY_5_TIMES },
- /*! \note When SPI Frame complete, trigger the dma channel3 transfer
- */
- { SIGNAL2, USE_SPI0_FRM_EXCHANGED, TO_TRIGGER_DMA0_CHN2, },
- );
-
- //! configure DMA
- dma_cfg();
- //! fall in sleep and NEVER wake up.
- PM_SLEEP(DEEP_SLEEP);
- }
复制代码
|
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?注册
x
|