DMA Nedir ?

Başlatan muhittin_kaplan, 16 Kasım 2012, 21:23:10

muhittin_kaplan

Evde Yatıp Duruyor, Çalışsın Biraz.
(Aramızda Kalsın)

Mucit23

Hatun işini sevdim :)

ADC ilgimi çekti. Normade ADC de çevrim işlemini biz başlatıyoruz çevrim bittiğinde ya kesmeyle yada direk adc değerini okuyoruz. Bu işi DMA ya devrettiğimizde ADC ye hiç dokunmamız gerekmiyormu?

Yani DMA sırayla ADC çevrimini başlatıp, Çevrim bittiğinde değeri alıp usart ile gönderebiliyormu. Bu işlemin sıklığını ayarlayabiliyormuyuz?

yamak

Hocam ADC yi başlatıyosunuz DMA aracılığıyla ADC yi UART a bağlıyosunuz o da ADC dene gelen verileri direkt uart a gönderiyo. Mesela osiloskop gibi uygulamaların yapımında çok işe yarıyo hızlıca ADC den gelen verileri istediğiniz birime aktarıyosunz.

Mucit23

Anladım..
Sonuç olarak yine her işlem bittiğinde bizim tekrarlamamız gerekecek. Ama mesela ADC çevriminin bitmesini beklemeyiz.


eistain_54

#19
Genel anlamda dma olayı gönderimi yapmak istediğiniz veri yolunun adresini tanımlıyorsunuz ve veri transferi boyunca o yolun kontrolünü dma modülüne bırakıyorsunuz.Modül işini bitirdiğinde flagları set clear ederek size bildirebiliyor.İsterseniz...
Cortexlerde falan nasıl tam olarak henüz incelemedim ancak pic18f25j50 de spi dma modülünü inceliyorum ve makaleyi henüz tamamlamadığımdan yayınlayamıyorum.Yayınladım eksiklerden kaldırdım.Bitince buradan da yayınların İnşAllah.
Olay şu (18f25j50 için.Diğerlerinde ne değişir bilmiyorum.Henüz!): Dma modülü için sram kullanılıyo.Modülün toplamda 5 miydi neydi o kadar registeri var.Onların farklı işlevli olanları var (int rut, veri adresi,uzunluğu vs vs). Modüle diyorsunuz ki sramda şu adreste bulunan veriyi al spi ile gönder.Bu sırada spi falan kurulmuş olmalı tabii.Sonra siz main Programda diğer işlerinizle meşgül oluyorsunuz.Ancak o sırada belirttiğiniz adrese müdahele de edebiliyorsunuz.Ancak o esnada işlem yapılan (veri kopyalanan adrese) adrese dokunmazsanız sanıyorum faydanıza olacaktır.
.
.
.
/*burada spi kuruldu dma kuruldu gerekli dma ayarları yapıldı adres gösterildi hedef belirtildi vs..*/

.
.
.
/*Burada da dma için gereken bir kaç satır daha kod var onlar halledildi.*/
#int_timer0
void timer_kesme(){

/*timer içinde ne arıyorsak artık :)*/
}

void main(){

output_high(pin_a0);
set_pwm_duty(200);
}


Bu benim uydurduğum bir kaç satır. Birde bu var:

;For this example, let's use RP5(RB2) for SCK2,
;RP4(RB1) for SDO2, and RP3(RB0) for SDI2
;Let's use SPI master mode, CKE = 0, CKP = 0,
;without using slave select signalling.
InitSPIPins:
movlb 0x0F ;Select bank 15, for access to ODCON3 register
bcf ODCON3, SPI2OD ;Let's not use open drain outputs in this example
bcf LATB, RB2 ;Initialize our (to be) SCK2 pin low (idle).
bcf LATB, RB1 ;Initialize our (to be) SDO2 pin to an idle state
bcf TRISB, RB1 ;Make SDO2 output, and drive low
bcf TRISB, RB2 ;Make SCK2 output, and drive low (idle state)
bsf TRISB, RB0 ;SDI2 is an input, make sure it is tri-stated
;Now we should unlock the PPS registers, so we can
;assign the MSSP2 functions to our desired I/O pins.
movlb 0x0E ;Select bank 14 for access to PPS registers
bcf INTCON, GIE ;I/O Pin unlock sequence will not work if CPU
;services an interrupt during the sequence 
movlw 0x55 ;Unlock sequence consists of writing 0x55
movwf EECON2 ;and 0xAA to the EECON2 register.
movlw 0xAA
movwf EECON2
bcf PPSCON, IOLOCK ;We may now write to RPINRx and RPORx registers
bsf INTCON, GIE ;May now turn back on interrupts if desired
movlw 0x03 ;RP3 will be SDI2
movwf RPINR21 ;Assign the SDI2 function to pin RP3
movlw 0x0A ;Let's assign SCK2 output to pin RP4 
movwf RPOR4 ;RPOR4 maps output signals to RP4 pin
movlw 0x04 ;SCK2 also needs to be configured as an input on the 
same pin
movwf RPINR22 ;SCK2 input function taken from RP4 pin
movlw 0x09 ;0x09 is SDO2 output
movwf RPOR5 ;Assign SDO2 output signal to the RP5 (RB2) pin
movlb 0x0F ;Done with PPS registers, bank 15 has other SFRs
InitMSSP2:
clrf SSP2STAT ;CKE = 0, SMP = 0 (sampled at middle of bit)
movlw b'00000000' ;CKP = 0, SPI Master mode, Fosc/4
movwf SSP2CON1 ;MSSP2 initialized
bsf SSP2CON1, SSPEN ;Enable the MSSP2 module
InitSPIDMA:
movlw b'00111010' ;Full duplex, RX/TXINC enabled, no SSCON
movwf DMACON1 ;DLYINTEN is set, so DLYCYC3:DLYCYC0 = 1111
movlw b'11110000' ;Minimum delay between bytes, interrupt
movwf DMACON2 ;only once when the transaction is complete
;Somewhere else in our project, lets assume we have
;allocated some RAM for use as SPI receive and 
;transmit buffers.
; udata 0x500
;DestBuf res 0x200 ;Let's reserve 0x500-0x6FF for use as our SPI
; ;receive data buffer in this example
;SrcBuf res 0x200 ;Lets reserve 0x700-0x8FF for use as our SPI
; ;transmit data buffer in this example
PrepareTransfer:
movlw HIGH(DestBuf) ;Get high byte of DestBuf address (0x05)
movwf RXADDRH ;Load upper four bits of the RXADDR register
movlw LOW(DestBuf) ;Get low byte of the DestBuf address (0x00)
movwf RXADDRL ;Load lower eight bits of the RXADDR register
movlw HIGH(SrcBuf) ;Get high byte of SrcBuf address (0x07)
movwf TXADDRH ;Load upper four bits of the TXADDR register
movlw LOW(SrcBuf) ;Get low byte of the SrcBuf address (0x00)
movwf TXADDRL ;Load lower eight bits of the TXADDR register
movlw 0x01 ;Lets move 0x200 (512) bytes in one DMA xfer
movwf DMABCH ;Load the upper two bits of DMABC register
movlw 0xFF ;Actual bytes transferred is (DMABC + 1), so
movwf DMABCL ;we load 0x01FF into DMABC to xfer 0x200 bytes
BeginXfer:
bsf DMACON1, DMAEN ;The SPI DMA module will now begin transferring
;the data taken from SrcBuf, and will store
;received bytes into DestBuf.
;Execute whatever ;CPU is now free to do whatever it wants to
;and the DMA operation will continue without
;intervention, until it completes.
;When the transfer is complete, the SSP2IF flag in
;the PIR3 register will become set, and the DMAEN bit
;is automatically cleared by the hardware.
;The DestBuf (0x500-0x7FF) will contain the received
;data. To start another transfer, firmware will need
;to reinitialize RXADDR, TXADDR, DMABC and then 
;set the DMAEN bit.


Not: Kaydediciler de bunlarmış:
DMACON1 • DMACON2
• TXADDRH • TXADDRL
• RXADDRH • RXADDRL
• DMABCH • DMABCL
Dip not: Bazı bilgiler hatalı olabilir.Henüz dökümanın hazırlanması tamamlanmadı...Umarım faydalı olur![/code]
Her gün 24 altın verilirken bunun için kime şükredersin ey ademoğlu!?!

fatih6761

Zaten donanımların Register'ları, Tamponlaı da ana bellek üzerinde adreslendiği için ( ben böyle biliyorum ) DMA'nın yaptığı iş bellekte veri taşımaya özelleşmiş çok spesifik bir işlemci. Yaptığı tek şey Source işaretçisinden belirttiğiniz uzunlukta veriyi Target işaretçisine yazmak. Yani atıyorum ADC değer tamponu bellekte 0x0ADC adresinde yer alıyor. SPI ise 0x0123 adresinde yer alsın. Her ADC çevriminde 512 byte'lık örneklemler oluşuyor olsun. Bu durumda DMA sizin isteğinizle 0x0ADC de bulunan tampon hazır olduğunda ( Flag'ları beklemeyebilir, bunlarda da Wait State tarzı bir kilitlenme olması lazım ) 0x0ADC adresinden 512-bytlelık veriyi alıp 0x0123 adresine kopyalıyor. STM32F407'lerde DMA1 ve DMA2 olmak üzere iki DMA çekirdeği var. Her çekirdeğin kontrolünde 8 DMA kanalı var. Yani aynı anda bellekte 2 farklı veriyi ( tamponlar da dahil ) taşıyabilirken işlemciyi de meşgul etmemiş olursunuz. Bu 8 kanala Stream (akış) da denir. Bir merkeze bağlı akışlardan en fazla aynı anda 1 tanesi çalışabilir. Özet olarak mikrodenetleyicinin değişmekle birlikte General Purpose bir çekirdeği, Memory-specific iki veya daha fazla ( İşlemci + N tane DMA çekirdeği ) çekirdeği var.

camby

#21
STM32F100RB için ,

2 farklı adres register'ı var :

DMA channel x peripheral address register (DMA_CPARx)
DMA channel x memory address register (DMA_CMARx)

Memory to memory modunda veri transferi yaparken verinin hangi adresden hangi adresten kopyalandığı bilgisini RM0041'de bulamadım. Bilen gören var mıdır ?

Hedefi hangi register'a kaynağı hangi register'a yazacağım ?

Deneme yanılma yaparak buldum ancak...

mesaj birleştirme:: 17 Kasım 2012, 17:57:20

Buldum :

Bit 4 DIR: Data transfer direction
This bit is set and cleared by software.
0: Read from peripheral
1: Read from memory

Memory to memory bölümünde bir açıklama bekliyordum : )

muhittin_kaplan

konu biraz sönük kalmış, yada ben anlamıyorum.  Şimdi std_lib kullanarak bir örnek yapmak istiyorum. Takip edeceğim yol nedir ?

Klein

#23
https://www.picproje.org/index.php/topic,43472.0.html

Dma'nın ayarlandığı bölüme göz at. Onun üzerinden konuşalım.

UAR3 TX için DMA ayarlama
void Usart3_TxDMAConfig(uint32_t priority){
NVIC_InitTypeDef NVIC_InitStruct;
DMA_InitTypeDef DMA_InitStructure1;

  DMA_DeInit ( DMA1_Channel2);
  DMA_Cmd(DMA1_Channel2,DISABLE);

  DMA_InitStructure1.DMA_PeripheralBaseAddr = 0x40004804;
  DMA_InitStructure1.DMA_DIR = DMA_DIR_PeripheralDST;
  DMA_InitStructure1.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
  DMA_InitStructure1.DMA_MemoryInc = DMA_MemoryInc_Enable;
  DMA_InitStructure1.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
  DMA_InitStructure1.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
  DMA_InitStructure1.DMA_Mode = DMA_Mode_Normal;
  DMA_InitStructure1.DMA_Priority = priority;
  DMA_InitStructure1.DMA_M2M = DMA_M2M_Disable;
  DMA_Init(DMA1_Channel2, &DMA_InitStructure1);

  DMA_ITConfig (DMA1_Channel2, DMA_IT_TC, ENABLE);
  USART_DMACmd(USART3, USART_DMAReq_Tx , ENABLE);

  NVIC_InitStruct.NVIC_IRQChannel = DMA1_Channel2_IRQn;
  NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
  NVIC_Init(&NVIC_InitStruct);
//  DMA_Cmd(DMA1_Channel2, ENABLE);
}



muhittin_kaplan

Hocam Stm32F103 için konuşuyorum.
Usart3 e 4 adet adc degerlerini göndereceğim.
Eski Sistem, ADC yi Teker Teker Okuyorum sprintf ile birleştirip bir katar halinde usart a gönderiyorum.
ilk önce şu adc okuma yöntemlerini irdelemem gerek. Örneğin kendisinin Yani ADC nin Taramasını istediğim an, ben bu tarama işlemini İşlemciyemi yaptıracağım yoksa ADC modülü bunu kendisimi yapıyor ?

Klein

ADC modülü kendisi yapıyor.  Sen sadece ilkcevirimi başlatırsın. Eğer Sürekli çevirim demişsen, belirlediğin sayı kadar kanal sürekli taranır. Tek çevirim seçtiysen, seçilmiş kanalların tümü 1 kez taranır sonra durur. Senin çevirimi tekrar başlatman gerekir.