| 
	
	|  |  |  
	
		| View previous topic :: View next topic |  
		| Author | Message |  
		| dman232323 
 
 
 Joined: 19 May 2022
 Posts: 8
 
 
 
			    
 
 | 
			
				| DSPIC33: SPI AND DMA |  
				|  Posted: Thu May 19, 2022 5:05 am |   |  
				| 
 |  
				| Hi, 
 I would like to read data from flash using SPI and DMA.
 
 I understand that i will need 2 dma channels, 1 to read and 1 to write while I read (dummy).
 
 I can't seem to make it work.
 
 
  	  | Code: |  	  | #BANK_DMA
 int8 dma0_buffer[256] = {0}; // dummy send
 
 #BANK_DMA
 int8 dma1_buffer[256]; // receive
 
 
 
 ....
 
 
 
 #INT_DMA0
 void dma0_isr(void)
 {
 
 dma_0_done_flag = 1;
 }
 
 #INT_DMA1
 void dma1_isr(void)
 {
 dma_1_done_flag = 1;
 }
 
 
 
 void main() // Main function
 {
 int8 rc = restart_cause(); // debug
 initialize();
 
 setup_dma(0, DMA_OUT_SPI2, DMA_BYTE);
 setup_dma(1, DMA_IN_SPI2, DMA_BYTE);
 
 enable_interrupts(int_dma0);
 enable_interrupts(int_dma1);
 
 ..... code
 
 // ask the flash for data
 
 
 
 output_low(FLASH_CS); // select flash
 spi_read2(FLASH_FREAD); // execute read command
 spi_read2(make8(addr, 2)); // address MSB
 spi_read2(make8(addr, 1)); //
 spi_read2(make8(addr, 0)); // address LSB
 spi_read2(0); // dummy data - for clocks
 // enable dma spi input
 dma_start(1, DMA_ONE_SHOT|DMA_FORCE_NOW, &dma1_buffer[0],256);
 // enable spi send (dummy_send)
 dma_start(0, DMA_ONE_SHOT|DMA_FORCE_NOW, &dma0_buffer[0],256);
 output_high(FLASH_CS);
 
 | 
 When i read the input buffer, its 0xFF.
 
 But when i don't use the dma, and just regular spi_read, the data is ok.
 
 Could you please help me?
 |  |  
		|  |  
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19966
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu May 19, 2022 5:58 am |   |  
				| 
 |  
				| My own setup for doing SPI receive on SPI2, is: 
 setup_dma(0, DMA_TRIGGER_SPI2RX, DMA_BYTE | DMA_RELOAD_ADDRESS);
 
 Then the DMA start is:
 
 dma_start(0, DMA_SOURCE_ADDR_UNCHANGED | DMA_INC_DEST_ADDR | DMA_REPEATED, DMA_ADC_RX, getenv("SFR:SPI2BUFL"), 256);
 
 I trigger by sending the setup sequence using DMA1. The chip's reply is
 then what starts the receive.
 |  |  
		|  |  
		| dman232323 
 
 
 Joined: 19 May 2022
 Posts: 8
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu May 19, 2022 6:08 am |   |  
				| 
 |  
				|  	  | Ttelmah wrote: |  	  | My own setup for doing SPI receive on SPI2, is: 
 setup_dma(0, DMA_TRIGGER_SPI2RX, DMA_BYTE | DMA_RELOAD_ADDRESS);
 
 Then the DMA start is:
 
 dma_start(0, DMA_SOURCE_ADDR_UNCHANGED | DMA_INC_DEST_ADDR | DMA_REPEATED, DMA_ADC_RX, getenv("SFR:SPI2BUFL"), 256);
 
 I trigger by sending the setup sequence using DMA1. The chip's reply is
 then what starts the receive.
 | 
 
 Thanks.
 
 Those are not valid options in my chip.
 I am using dspic33ep512gm306....
 |  |  
		|  |  
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19966
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu May 19, 2022 6:18 am |   |  
				| 
 |  
				| The key thing you are missing is the difference between DMA_CONTINUOUS and DMA_ONE_SHOT.
 |  |  
		|  |  
		| dman232323 
 
 
 Joined: 19 May 2022
 Posts: 8
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu May 19, 2022 6:24 am |   |  
				| 
 |  
				| OK, could you please elaborate? because i think I tried some variation with continues,
 but as I see it,
 there is a point in my program, in which i would like to get data from the FLASH. It's a spesific moment, let's say it's a user pressing a button.
 So, for me, it sounds like a one-shot...
 |  |  
		|  |  
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19966
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu May 19, 2022 6:47 am |   |  
				| 
 |  
				| No. The transfer stops after a block either way, but with 'continuous' the
 address counter goes back to the start of the buffer. With one shot it
 doesn't. If you don't select this, unless you do another 'setup', it goes
 on up the memory.
 It goes 'continuous', if you select ping_pong & continuous. Otherwise
 it still stops.
 
 Try this:
 dma_start(1, DMA_CONTINUOUS|DMA_FORCE_NOW|DMA_PERIF_ADDR, dma1_buffer,256);
 
 I must admit I've never tried sending the setup without DMA. I send the
 setup as a defined block with the target address using the other DMA
 channel, and the completion of this triggers the receive.
 |  |  
		|  |  
		| dman232323 
 
 
 Joined: 19 May 2022
 Posts: 8
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu May 19, 2022 7:13 am |   |  
				| 
 |  
				| Regarding the last part of your message, i also tried sending the commands as part of the dma0 
 int8 dma0_buffer[256] = {RD_OP, ADDR_2,ADDR_1,ADDR_0,DUMMY};
 
 I looked at the signals going out on the MOSI line, they look ok.
 
 regarding the main part of your message, i tried it, i get 0's back.
 
 so my line of code now looks like this:
 output_low(FLASH_CS);
 dma_start(1, DMA_CONTINUES|DMA_FORCE_NOW|DMA_PERIF_ADDR, &dma1_buffer[0],256);
 dma_start(2, DMA_ONE_SHOT|DMA_FORCE_NOW, &dma0_buffer[0],256);
 output_high(FLASH_CS);
 
 tried also continues with dma0 did not make a difference
 
 so if MISO lines are OK
 There is a problem with the recieve DMA
 because when i use standalone SPI it all works fine, MISO MOSI , data is valid.
 
 
 on a side note, when using continies, i noticed the lines of CLK and MOSI are always active, the dont stop...
 
 Thanks for the help
 |  |  
		|  |  
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19966
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu May 19, 2022 8:46 am |   |  
				| 
 |  
				| OK. The problem you have is that nothing is starting the clocking.
 Think about it without clocks, the bytes can't read, and nothing is
 saying to the SPI 'start clocking'.
 I started the transaction by sending a null byte. This then makes the
 receive buffer load, and the SPI starts receiving, and the DMA reads
 this.
 |  |  
		|  |  
		| dman232323 
 
 
 Joined: 19 May 2022
 Posts: 8
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu May 19, 2022 9:51 am |   |  
				| 
 |  
				|  	  | Ttelmah wrote: |  	  | OK. The problem you have is that nothing is starting the clocking.
 Think about it without clocks, the bytes can't read, and nothing is
 saying to the SPI 'start clocking'.
 I started the transaction by sending a null byte. This then makes the
 receive buffer load, and the SPI starts receiving, and the DMA reads
 this.
 | 
 
 Yeah, but as i see it, i am sending 256- 5 = 252  null bytes.
 The clock should be there (scratching my head...)
 |  |  
		|  |  
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19966
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu May 19, 2022 1:03 pm |   |  
				| 
 |  
				| No, you are asking it to receive. You are reading the RX buffer, not writing. That is the point. To send, you have to write, then the read
 will occur.
 |  |  
		|  |  
		| dman232323 
 
 
 Joined: 19 May 2022
 Posts: 8
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Thu May 19, 2022 1:45 pm |   |  
				| 
 |  
				| I will not be at the lab for the next couple of days, but i can't let go   
 So you are suggesting that on the dma channel i am writing, i will keep the buffer to a size of 5 which is the size of the instruction i am required to send in order to read.
 And then execute, when i get a flag that it has ended, the start of the read dma which is let's say 256 or whatever amount of bytes i want to read?
 |  |  
		|  |  
		| dman232323 
 
 
 Joined: 19 May 2022
 Posts: 8
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Sun May 22, 2022 4:08 am |   |  
				| 
 |  
				| So... I am gonna need a little more help here. I am now using DMA0 just to send the data in order to enable the read: OPCODE ADDRESSX3 and DUMMY bytes required by datasheet => 5 bytes.
 EDIT:
 I seem to be able to do one read of 256 bytes from the flash, but i cannot re-generate the operation, to read multiple pages (chunks).
 
 Here is my current code:
 
  	  | Code: |  	  | #BANK_DMA int8 dma0_buffer[5] = {RD_OP, ADDR_2,ADDR_1,ADDR_0,DUMMY};
 
 #BANK_DMA
 int8 dma1_buffer[256]; // receive
 
 ....
 
 
 #INT_DMA0
 void dma0_isr(void)
 {
 dma_start(1, DMA_FORCE_NOW, &dma1_buffer[0],255); // once the data send is over, call for receive dma of 256 bytes
 dma_0_done_flag = 1;
 }
 
 #INT_DMA1
 void dma1_isr(void)
 {
 dma_1_done_flag = 1;
 }
 
 
 
 void main() // Main function
 {
 int8 rc = restart_cause(); // debug
 initialize();
 
 setup_dma(0, DMA_OUT_SPI2, DMA_BYTE);
 setup_dma(1, DMA_IN_SPI2, DMA_BYTE|DMA_WRITE_NULL);
 
 enable_interrupts(INT_DMA0);
 enable_interrupts(INT_DMA1);
 
 //..... code
 
 // ask the flash for data
 
 for(page_num=0;page_num<4 ; page_num++)
 {
 addr = addr + page_num*256;
 dma0_buffer[1] = make8(addr,2);
 dma0_buffer[2] = make8(addr,1);
 dma0_buffer[3] = make8(addr,0);
 
 output_low(FLASH_CS); // select flash
 dma_start(1, DMA_ONE_SHOT, &dma1_buffer[0],4); // prepare to dummy read, no use of the incoming data caused from upcoming write (next_line)
 dma_start(0, DMA_ONE_SHOT|DMA_FORCE_NOW, &dma0_buffer[0],4); // write the sequence needed in order to start false read
 
 while(!dma_1_done_flag ){}; // as long as the receiving dma did not flag its done, stay here
 output_high(FLASH_CS);
 
 // code to read from dma_1 buffer and send via uart
 // ...
 }
 
 | 
 |  |  
		|  |  
		| Ttelmah 
 
 
 Joined: 11 Mar 2010
 Posts: 19966
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Tue May 24, 2022 3:03 am |   |  
				| 
 |  
				| The reading device can start the transfer. You don't need to use the write device:
 
 
  	  | Code: |  	  | dma_start(1, DMA_ONE_SHOT|DMA_FORCE_NOW,, &dma1_buffer[0],256);
 
 | 
 
 This will write 256 nulls, and read the replies. If you have WRITE_NULL
 selected this will do your read transaction.
 
 However you must not call the setup_dma, until after you have done
 the memory chip initialisation with SPI. You are not allowed to write to the
 SPI buffer register except with DMA once the DMA transaction is setup.
 
 To do another transfer just call another dma_start.
 |  |  
		|  |  
		| dman232323 
 
 
 Joined: 19 May 2022
 Posts: 8
 
 
 
			    
 
 | 
			
				|  |  
				|  Posted: Tue May 24, 2022 5:04 am |   |  
				| 
 |  
				| Thanks! Got it to work.
 its functioning well now.
 
 Thanks Ttelmah for the help
 |  |  
		|  |  
		|  |  
  
	| 
 
 | You cannot post new topics in this forum You cannot reply to topics in this forum
 You cannot edit your posts in this forum
 You cannot delete your posts in this forum
 You cannot vote in polls in this forum
 
 |  
 Powered by phpBB © 2001, 2005 phpBB Group
 
 |