Autor Tema: DMA para leer 6 puertos GPIO  (Leído 1483 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado planeta9999

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3520
    • Pinballsp
DMA para leer 6 puertos GPIO
« en: 23 de Octubre de 2017, 10:11:00 »
 

No estoy seguro si es posible hacerlo, he leído sobre el DMA vinculado a puertos, SPI, UART, creo que también CAN Bus, Ethernet y otros, pero lo que necesito es capturar 6 señales de datos sincronizadas con una señal de reloj externa.

En principio no estaría vinculado a ningún tipo de puerto, porque de hacerlo por SPI, necesitaría que el micro tuviera 6 puertos SPI, y al menos con estos Kinetis creo que no hay tantos puertos SPI, ni siquiera en los TQFP144, creo que solo tiene 2 ó 3 puertos.

Por algún sitio me suena haber leído que se pueden capturar directamente puertos GPIO, vinculando cada uno a un buffer de DMA, y todo sincronizado con una señal de reloj externa.

¿ Os suena si esto es posible con DMA ?. En mi caso es para hacerlo con Kinetis, aunque igual lo podría hacer con STM32 o SAM S70.

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:DMA para leer 6 puertos GPIO
« Respuesta #1 en: 23 de Octubre de 2017, 14:47:12 »
Que micro ( Kinetis ) estamos hablando ?

Y por ahi no necesitas un 6 SPI, sino tal ves 2 QSPI, lo feo es que, el dato se armaria de a nibbles, y luego deberias corregirlo. Pero si tenes un QSPI y un DSPI seria aun peor, ya que uno completa en 3 ciclos y el otro en 2. Con QSPI me refiero a Quad SPI, el cual permite hasta 4 entradas/salidas + 1 clk, y el DSPI 2 in/out + clk.

Pero ES mucho mas simple usar el DMA para transferir desde un periferico a memoria. tanto que ni vale la pena usar lo anterior.

Y dependiendo del micro vas a poder configurar un pin de algun PORT donde algun flanco pueda o no generar un request del DMA, sino posee la posibilidad de disparar el DMA, entonces directamente te conviene hacerlo por software a la toma de datos.
Luego el DMA es simplemente configurarlo igual que el SPI ( 1 byte), lo que cambiaria es la direccion de donde lo toma ( ahora el PORT) , la fuente de disparo, la cantidad de datos.

Desconectado planeta9999

  • Moderadores
  • DsPIC30
  • *****
  • Mensajes: 3520
    • Pinballsp
Re:DMA para leer 6 puertos GPIO
« Respuesta #2 en: 23 de Octubre de 2017, 15:15:28 »
Que micro ( Kinetis ) estamos hablando ?

Un MK66, TQFP144, 180Mhz.


Citar
Y por ahi no necesitas un 6 SPI, sino tal ves 2 QSPI, lo feo es que, el dato se armaria de a nibbles, y luego deberias corregirlo. Pero si tenes un QSPI y un DSPI seria aun peor, ya que uno completa en 3 ciclos y el otro en 2. Con QSPI me refiero a Quad SPI, el cual permite hasta 4 entradas/salidas + 1 clk, y el DSPI 2 in/out + clk.

Pero ES mucho mas simple usar el DMA para transferir desde un periferico a memoria. tanto que ni vale la pena usar lo anterior.

Y dependiendo del micro vas a poder configurar un pin de algun PORT donde algun flanco pueda o no generar un request del DMA, sino posee la posibilidad de disparar el DMA, entonces directamente te conviene hacerlo por software a la toma de datos.
Luego el DMA es simplemente configurarlo igual que el SPI ( 1 byte), lo que cambiaria es la direccion de donde lo toma ( ahora el PORT) , la fuente de disparo, la cantidad de datos.


He encontrado ya alguna cosa, y no está vinculado a ningún tipo de puerto serie como SPI, sino a capturar señales del GPIO, sincronizadas con una señal de reloj externa, y por DMA se transfiere directamente a RAM, que viene a ser lo mismo que cargar los datos a una matriz.

En concreto he localizado está aplicación de ejemplo (AN4627 de NXP), que hace casi lo mismo que yo necesito, solo que en ese ejemplo están capturando los datos de un sensor de cámara de video, y yo lo que voy a capturar son las imágenes que se visualizan en paneles LED.


/*************************************************************/
/* DMA is configured to be HW triggered and have the highest channel         */
/* priority. DMA transfer is constructed to read 1 byte at a time from           */
/* same address of the PORT and write to a consecutive address in RAM      */
/************************************************************/
void Set_Dma(void) 
{
  DMA_CR = 0;        // no minor loop mapping
  DMA_DCHPRI15 = 15;  // cannot be pre-empeted, can pre-empt, highest priority , same as reset value 
   
DMA_TCD15_SADDR = DMA_SOURCE_ADDRESS ;    // Address of first 8 bits of PORT E
DMA_TCD15_SOFF = 0;    // No need of offset, transferring only 1 Byte of the same address
DMA_TCD15_ATTR = DMA_ATTR_SMOD(0)
                             | DMA_ATTR_SSIZE(0)
                             | DMA_ATTR_DMOD(0)
                             | DMA_ATTR_DSIZE(0);   // 8 bit S&D, no modulo
  DMA_TCD15_NBYTES_MLNO    = 1;    // Transferring 1Byte in each itteration
  DMA_TCD15_SLAST    = 0;   
  DMA_TCD15_DADDR   = DMA_FRAME_DESTINATION ;
  DMA_TCD15_DOFF   = 1;    // destination address progresses while source address remains the same
  DMA_TCD15_CITER_ELINKNO  = DMA_CITER_ELINKNO_CITER(QQVGA_columns*2);  // not major loop counter is 320 (160 bits of a row x2 for each pixel)
  DMA_TCD15_DLASTSGA  = -(QQVGA_columns*2);
  DMA_TCD15_CSR           = 0;              // working without an interrupt
  DMA_TCD15_BITER_ELINKNO  = DMA_BITER_ELINKNO_BITER(QQVGA_columns*2);  // BITER value = CITER value
  DMA_ERQ = DMA_ERQ_ERQ15_MASK;   // Enable DMA trigger in HW request
}


/***************************************************/
/* Configure DMA Mux for Channel 15                                      */
/***************************************************/
void Set_Dma_Mux(void) 
{
// Enable routing of DMA request from source PORT B, no triggering
  DMAMUX_CHCFG15 |= DMAMUX_CHCFG_ENBL_MASK | DMAMUX_CHCFG_SOURCE(50);   
}



/************************************************************************/
/*  Once a VSYNC signal is detected it initiates the following routine: */
/*  isr flag is cleared, enabling the HREF isr for falling egde and     */
/*  enabling the DMA HW request by the PCLK pin.                        */
/************************************************************************/
void vsync_isr(void)
{
  PORTE_ISFR=0xFFFFFFFF;  // Clear Port E ISR flags
    if ( frames == 0 )            // when 2 frames are fully transferred and a new frame arrives
  {
    frames = frame_count;  // Starting frame count again
    DMA_TCD15_DADDR = DMA_FRAME_DESTINATION ;   // Resetting the destination address of DMA
  }
  PORTC_PCR15 = PORT_PCR_IRQC(0x0A)|PORT_PCR_MUX(0x01);  // Enabling interrupt on falling edge for HREF signal
  PORTB_PCR18 |= PORT_PCR_IRQC(0x02)
              | PORT_PCR_PE_MASK
              | PORT_PCR_PS_MASK
              | PORT_PCR_DSE_MASK ;  // DMA request enabled with PCLK signal rise
  frames-- ;   // Counting down number of frames
 
}


/***********************************************************************/
/*  Once a HREF signal is detected it initiates the following routine: */
/*  Counting down the number of rows in a QQVGA frame and setting      */   
/*  it back when countdown is exhausted.                               */
/*  Everytime HREF indicates an end of a row the DMA destination       */
/*  address updated in the number of pixel per line x2.                */
/***********************************************************************/

void href_isr(void)
{
  PORTC_ISFR=0xFFFFFFFF;    //Clear Port C ISR flags
  rows-- ;                              // Counting down the rows for a frame
  if (rows==0)                       // When a full frame is fully transferred
    rows=QQVGA_rows;          // Starting Rows count again
  DMA_TCD15_DADDR = DMA_TCD15_DADDR + (QQVGA_columns*2);   // DMA dest address update after every row transfer
}




« Última modificación: 23 de Octubre de 2017, 15:25:30 por planeta9999 »


 

anything