Autor Tema: (Tutorial) DMA esta gran olvidada pero tan util!  (Leído 10438 veces)

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

Desconectado MerLiNz

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2463
(Tutorial) DMA esta gran olvidada pero tan util!
« en: 07 de Mayo de 2012, 15:37:45 »
Bueno, pues visto que en este foro apenas se habla de la DMA de los dspic (supongo que tambien aplicable a pic32) he decidido abrir un post para comentar todo sobre este controlador que traen la mayoria de los dspics y que casi nadie usa, o habla de ello, a pesar de que una vez comprendido es bastante sencillo de usarla.

Bien, lo primero saber es que DMA es un controlador de memoria por asi decirlo, intentare explicarlo de forma sencilla con ejemplos sencillos, nada de tecnicismos, para que todo el mundo lo pueda entender. DMA significa direct access memory, osea acceso directo a memoria, pero como digo es un controlador el cual actua entre "memorias" haciendo transferencias o recepciones.

¿Y para que sirve?
-Pues sirve para hacer transferencias/recepciones entre distintos perifericos que trae el pic (SPI, USART, CAN, ADC...) y la memoria de sistema (ya sea memoria DMA o la RAM normal del pic).

¿Vale pero que diferencia hay entre usar el metodo tradicional y usar el DMA para usar los perifericos?
-En principio si vamos a usar ese periferico para transmitir pocos bytes no merece la pena usar el DMA, pero cuando queremos enviar/recibir gran cantidad de datos es muy muy util, por ejemplo enviar cada x tiempo las capturas de 10 entradas analogicas al puerto usart. El numero de bytes o words (2 bytes) esta limitado a 16KBytes o bien 16KWords (lo que serian 32Kbytes) por buffer, normalmente se pueden usar 2 buffers por lo cual seria 32kbytes y 32kwords respectivamente, todo esto depende de que tipo de transferencia queramos hacer (8bits o 16bits), todo esto lo explicare mas adelante.

-¿Alguna ventaja mas?
-Pues si, son varias mas, entre ellas esta en que hace la transferencia automaticamente sin que la CPU actue, por lo cual podemos estar transferiendo datos por usart mientras nuestro programa esta haciendo otra cosa, incluso podemos dejar que lo haga de forma continua (una vez acaba empieza de nuevo). Asi nos evitamos tener que estar haciendo un for(), o esperando interrupciones para estar enviando/recibiendo datos, por lo cual podermos hacer un codigo mas complejo sin tener que recurrir a mucha velocidad ya que nos evitamos el estar ejecutando funciones para las transmisiones/recepciones.

-¿Cuando hablaste de memoria DMA y memoria RAM normal que quisiste decir?
-Bien, pues habria que mirar si nuestro pic cuenta con memoria dma, y de cuanta memoria dispone, para esto en el datasheet suele venir, tambien en la web de microchip te viene, el pic que yo uso (dspic33ep512mu810) lleva 4Kbytes de DMA (la verdad es que es poca).
La diferencia de la memoria DMA y la RAM es que la DMA es de 2 puertos, esto quiere decir que el controlador DMA puede estar escribiendo/leyendo la memoria DMA mientras que la CPU tambien lo hace, sin que ninguno tenga que esperar a que el otro acabe. Existe excepciones, por ejemplo si el DMA quiere escribir/leer la misma direccion que la CPU hay una pequeña tabla que explica cual prevalece sobre cual, esto ya lo explicare mas adelante.

-¿Que mas deberia saber?
-Pues como dije el DMA es un controlador, este cuenta con determinados canales (el que yo uso 16 canales), normalmente se usan 2 canales por periferico (uno para enviar y otro para recibir), pero esto quiere decir que tu puedes configurar los canales que quieras para el periferico que quieras, no tienen porque ser todos, o ninguno...
Tambien saber que si usamos el controlador DMA para que use la memoria RAM normal existe unas preferencias entre varios controladores, y no todos pueden leerla/escribirla simultaneamente, primero lo haria uno (por defecto la CPU) y luego otro.. Existe un registro para cambiar las prioridades, pero todo esto lo explicare con diagramas para que sea mas sencillo de entender.

Bien, ahora mas o menos se deberia entender cual es su uso, y para que sirve.

Primero empezare explicando los registros para usarla, y los bits de configuracion. Cuando ponga una x en minuscula querra decir un numero, en este caso seria el numero de canal, por ejemplo DMAxCON, la x seria entre 0 y 15, DMA0CON=registro configuracion del canal DMA 0.


*CHEN=Canal activado/desactivado, poniendo este bit a 1 seria activo, y 0 desactivado
*SIZE=el tamaño, es lo que explique anteriormente, transferencias de 16bits o 8bits, 0=16bits; 1=8bits
*DIR=es la direccion del canal (transferencia o recepcion), 1=lectura desde la ram y escritura al periferico (transferencia), 0=lectura del periferico y escritura a la ram (recepcion)
*HALF=se genera una interrupcion al final de la transferencia/recepcion, o bien cuando lleve la mitad de los datos (0=al final), (1=a la mitad).
*NULLW=se utiliza para enviar datos nulos, mas adelante lo explico.
*AMODE= tipo de direccionamiento, esto lo explico mas detenidamente:
-11=(ni idea que haria este valor)
-10=(este modo no lo comprendo muy bien, intentare explicarlo mas adelante)
-01=Registro indirecto SIN incremento. Que quiere decir esto? Pues imaginaos que queremos enviar siempre el mismo dato, por ejemplo para el SPI enviamos un dato para poder recibir otro dato, siempre debemos escribirle algo para poder recibirlo, con este tipo de modo hariamos que el DMA envie los datos que apunten a determinada direccion de memoria durante x veces sin que el registro de memoria se incremente, por lo cual siempre apuntaria a la misma direccion y siempre enviaria el mismo dato.
-00=Registro indirecto CON incremento. Es lo contrario del anterior, es decir, imaginemos que queremos enviar un array de 16 direcciones, el array se encontraria en la direccion 0x1000 (por ejemplo), en el primer envio enviaria lo que se encuentre en la direccion 0x1000, en el segundo envio 0x1001, en el tercero 0x1002.... y asi hasta 0x0015. En el caso de "01" siempre enviaria el contenido de la direccion 0x1000 SIN INCREMENTAR.
*MODE=tipo de modo
-11=Esto funcionaria de la siguiente forma: enviaria el numero de datos que queramos, y una vez los ha enviado se desactiva automaticamente, tiene el modo ping-pong activado, como hable anteriormente se pueden enviar 2 buffers, el modo ping-pong quiere decir esto, una vez envia el buffer1 pasaria al buffer2 y una vez acabe el buffer2 se desactivaria como anteriormente dije.
-10=Enviaria continuamente, como el modo anterior este tiene el modo ping-pong activado, lo que haria seria, transferir buffer1, luego el 2, luego el 1 de nuevo, luego 2.... y asi hasta que lo desactivemos.
-01=Funcionaria como el "11" pero no tiene el modo ping-pong activado, por lo cual enviaria el buffer1, y una vez se acabe se desactiva.
-00=Funcionaria como el "10" pero sin el modo ping-pong, enviaria continuamente el buffer1 hasta que lo desactivemos.


DMAxREQ: Este registro se usa para seleccionar la IRQ, es decir a que periferico acudira el canal que elijamos, como anteriormente decia, el DMA se utiliza para la transferencia entre perifericos/memoria. Existe una lista donde te indica a que periferico concuerda cada numeracion, como no quiero confundir a la gente ya que posiblemente entre pics pueda variar os recomiendo que busqueis en el apartado DMA/registros/DMAxREQ y mireis la lista para cada pic, por ejemplo para mi pic seria:
00001010 = SPI1 – Transfer Done, si ponemos DMA0REQ=0b00001010; usariamos el canal dma0 para el SPI1
-FORCE: este bit se usa para FORZAR la transferencia sin que el periferico lo haga, muchos perifericos (SPI por ejemplo) no empiezan la transmision hasta que TU se lo ordenes, poniendo el bit FORCE a 1 haces eso, una vez hecho esto, automaticamente se sigue transmitiendo durante las veces que le indique en el registro que a continuacion pongo.



Como anteriormente os he hablado de X transferencias, este registro se usa para indicar cuantas transferencias se hara, es IMPORTANTE saber que siempre habria que poner x-1, es decir, si queremos hacer 10 transferencias tendriamos que poner 9, en caso de 1  transferencia tendriamos que poner 0 y asi siempre.
DMA0CNT=15; //hariamos 16 transferencias.



Este registro se usa para indicar la DIRECCION del PERIFERICO, es muy simple, por ejemplo para el SPI1 seria &SPI1BUF, para el USART1 RX seria &U1RXREG, para USART1 TX &U1TXREG.
Ejemplo:
DMA0PAD=&U1RXREG; //para que el DMA0 se utilice con el registro de recepcion del USART1
DMA1PAD=&U1TXREG; //para que el DMA1 se utilice con el registro de envio USART1


Bueno, este registro es muy importante saber como se usa, por lo cual deberia quedaros superclaro.
En momentos anteriores he estado hablando de "buffers", tambien dije que se podian usar 2 buffers para aumentar el numero de transferencias, digamos que estos registros son los que controlan los buffers.
Antes de nada hay que saber como funciona la asignacion de memoria, todas las variables que sean globales o estaticas se almacenan en una direccion de memoria, por ejemplo "unsigned int variable;" esto lo determina automaticamente el compilador, a no ser que nosotros se lo especifiquemos de forma manual, pero aqui no me voy a meter.
Un int ocupa 16bits, un char ocupa 8bits (no me voy a meter en variables de mayor tamaño para no confundir), y OJO es posible que variando el compilador tambien varien el tamaño de las variables, por eso es bueno saberlo cuando empezamos a programar con determinado compilador.
Bien, como decia antes cada variable se posiciona en una direccion determinada de memoria, como hablamos del DMA como transferencia de grandes cantidades de datos pues lo ideal es usar un array para almacenar todas, o bien una struct y enviarla al completo.
Por ejemplo unsigned int array[32];
Esta variable contendria 32 unsigned ints, lo que quiere decir que su tamaño seria 32*16=512BITS, si lo queremos ver por bytes, seria 32*2=64bytes.
Un ejemplo igual seria: unsigned char array[64]; //seria del mismo tamaño
Bien, pues imaginemos que el primer array empieza en la direccion 1000 de la RAM, si nosotros queremos saber la informacion que contiene la posicion 5 del array utilizariamos array[4] (recordad que empieza en el 0 y acaba en el 31). En nuestro caso al ser un unsigned int cada posicion se aumentaria en 2 direcciones, por lo cual estariamos viendo lo que hay en la direccion 1010, en el caso del unsigned char tendriamos que utilizar array[9] para ver la misma direccion.
Sabiendo esto en el DMAxSTAL y H hay que poner la direccion de memoria de nuestros buffers, para ello en C utilizamos el & para que nos diga en que posicion se encuentra esa variable. Es importante saber que el DMAxSTAL es para los 16bits de direccion de memoria baja, y DMAxSTAH para la parte alta, es decir si nuestra variable esta en la direccion 1000 la parte alta no la necesitariamos, con asignarle 0 vale. Cabe decir que dependiendo del pic quizas nunca se utilice la parte H ya que el pic no tiene tanta ram como para asignarle una direccion tan grande. Pero bien sigamos:
DMA0STAH=0;
DMA0STAL=(unsigned int)&array; //es importante poner el unsigned int delante para hacer la conversion y que no nos de un warning el compilador.
Como veis es simple, unicamente le asignamos la direccion de nuestro buffer y se acabo.
En caso de querer usar los 2 buffers, utilizariamos tambien el registro DMAxSTBH y DMAxSTBL, seria igual, lo unico que cambia es el STA por STB.

Bien, hasta aqui tenemos todos los registros, existen varios registros mas de errores para colisiones entre transferencias y cosas parecidas, pero de eso no hablare, si quereis investigar esta al final de la seccion DMA.
« Última modificación: 08 de Mayo de 2012, 17:02:32 por MerLiNz »

Desconectado manutek

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 555
Re: (Tutorial) DMA esta gran olvidada pero tan util!
« Respuesta #1 en: 07 de Mayo de 2012, 20:21:31 »
Espectacular info ¡¡¡¡ me suscribo al hilo
muchísimas gracias merlinz ¡¡¡¡ ((:-)) ((:-)) ((:-)) ((:-)) ((:-)) ((:-)) ((:-))
No es la conciencia del hombre la que determina su ser, sino, por el contrario, es su ser social el que determina su conciencia

Desconectado MerLiNz

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2463
Re: (Tutorial) DMA esta gran olvidada pero tan util!
« Respuesta #2 en: 07 de Mayo de 2012, 20:34:34 »
lo ire completando poco a poco, entre mis ratos de aburrimiento  :D

Desconectado rivale

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1707
Re: (Tutorial) DMA esta gran olvidada pero tan util!
« Respuesta #3 en: 07 de Mayo de 2012, 21:08:41 »
 (((:-)))

Gracias Merlinz, me suscribo ;-)
"Nada es imposible, no si puedes imaginarlo"

Desconectado fram_22

  • PIC18
  • ****
  • Mensajes: 316
Re: (Tutorial) DMA esta gran olvidada pero tan util!
« Respuesta #4 en: 07 de Mayo de 2012, 21:56:22 »
fabuloso! Ya lo agregue a mis favoritos

Desconectado Nocturno

  • Administrador
  • DsPIC33
  • *******
  • Mensajes: 17673
    • MicroPIC
Re: (Tutorial) DMA esta gran olvidada pero tan util!
« Respuesta #5 en: 08 de Mayo de 2012, 02:13:20 »
Muchas gracias por tan magnífica info, Merlinz.

Yo hace cinco años andaba intentando hacer un osciloscopio casero y usaba un ADC de Analog que iba escupiendo lecturas por una salida paralelo de 16 bits al ritmo de un oscilador. Esto lo ingresaba a un dsPIC33F mediante la DMA y aunque al principio me costó montarlo, lo logré.
Nunca terminé el osciloscopio y ahora no sé ni en qué rincón de qué cajón estará  :D

Aquí el hilo: http://www.todopic.com.ar/foros/index.php?topic=15440.0
Un saludo desde Sevilla, España.
Visita MicroPIC                                                                                        ɔ!doɹɔ!ɯ ɐʇ!s!ʌ

Desconectado MGLSOFT

  • Moderadores
  • DsPIC33
  • *****
  • Mensajes: 7842
Re: (Tutorial) DMA esta gran olvidada pero tan util!
« Respuesta #6 en: 08 de Mayo de 2012, 08:33:35 »
Me anoto !! ((:-)) ((:-))
Todos los dias aprendo algo nuevo, el ultimo día de mi vida aprenderé a morir....
Mi Abuelo.

Desconectado MerLiNz

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2463
Re: (Tutorial) DMA esta gran olvidada pero tan util!
« Respuesta #7 en: 08 de Mayo de 2012, 16:42:04 »
Gracias a todos, a ver si voy escribiendo algo mas xD

Nocturno, si tu supieras la de proyectos que tengo medio empezados y sin terminar xD

El tema del osciloscopio quizas sea un poco lento, como mucho conseguirias 1msps y para un osciloscopio es poca cosa, aunque para ver frecuencias bajas puede servir.


Desconectado jeremylf

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 1339
Re: (Tutorial) DMA esta gran olvidada pero tan util!
« Respuesta #8 en: 12 de Mayo de 2012, 01:30:14 »
Interesante info, gracias por compartir!

Desconectado MerLiNz

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2463
Re: (Tutorial) DMA esta gran olvidada pero tan util!
« Respuesta #9 en: 13 de Mayo de 2012, 20:37:35 »
Bueno continuo, voy poniendolo en distintos posts para que la gente lo vaya siguiendo, ya que editandolo la gente no sabria si he puesto algo nuevo o no.

Hoy hablare de las transferencias, las pondre 1 por 1.

Aqui el ejemplo que viene en el datasheet de microchip.


Explica como se hacen las transferencias de forma general:
A)Se configura el canal 5 del DMA
B)El periferico asignado el canal 5 tiene datos para transferir, este envia una interrupcion al controlador DMA para que procese la transferencia.
C) El canal 5 lee los datos del periferico
D) El canal 5 transfiere estos datos a la memoria (en este caso memoria DMA)


Este modo lo explique en el registro DMAxCON, AMODE=00
Como se puede ver el canal DMA 3 hace la primera transferencia (utiliza la direccion DMA3STA), en la siguiente transferencia DMA3STA+1, siguiente DMA3STA+2... en cada transferencia se decrementa el registro DMA3CNT (solo a nivel interno, a nivel externo este registro no se modifica).


Este modo es el AMODE=01
El ejemplo en las 3 primeras transferencias utiliza el autoincremento, y en las 2 ultimas utiliza el modo SIN INCREMENTO.
Como se puede observar hace las transferencias DMA3STA+0; +1; +2; pero en las 2 siguientes transferencias el DMA3STA permanece en la posicion de memoria +2 y +2. Este modo es muy util cuando quieres enviar el mismo dato constantemente, por ejemplo enviar por SPI un dato basura para que este nos responda con datos que necesitamos obtener.

Desconectado gera

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2188
Re: (Tutorial) DMA esta gran olvidada pero tan util!
« Respuesta #10 en: 26 de Diciembre de 2013, 19:09:13 »
Buenas buenas!!
Muy buen aporte MerLiNz, muy útil!! Actualmente estoy trabajando en un proyecto con un PIC18f26J50, el cual posee DMA para el puerto SPI. Me viene de 10 porque tengo un conversor ADC que funciona por SPI, debo leer varias muestras mientras proceso otras cosas. Por lo que leí en la hoja de datos, no es muy difícil de usar. Sin embargo estoy usando el compilador CCS y no tiene librerías ni nada por el estilo.
Por lo tanto pienso hacer mis propias librerías, y a medida que vaya avanzando iré compartiendo mis experiencias ;)

Bueno, saludos y gracias por el aporte!

"conozco dos cosas infinitas: el universo y la estupidez humana. Y no estoy muy seguro del primero." A.Einstein

Desconectado MerLiNz

  • Colaborador
  • PIC24H
  • *****
  • Mensajes: 2463
Re: (Tutorial) DMA esta gran olvidada pero tan util!
« Respuesta #11 en: 26 de Diciembre de 2013, 21:10:18 »
Buenas buenas!!
Muy buen aporte MerLiNz, muy útil!! Actualmente estoy trabajando en un proyecto con un PIC18f26J50, el cual posee DMA para el puerto SPI. Me viene de 10 porque tengo un conversor ADC que funciona por SPI, debo leer varias muestras mientras proceso otras cosas. Por lo que leí en la hoja de datos, no es muy difícil de usar. Sin embargo estoy usando el compilador CCS y no tiene librerías ni nada por el estilo.
Por lo tanto pienso hacer mis propias librerías, y a medida que vaya avanzando iré compartiendo mis experiencias ;)

Bueno, saludos y gracias por el aporte!

Yo mismo uso tambien un ADC por SPI, en concreto un ads7953 de TI, aparte del DMA este integrado permite la sincronizacion del CS mediante un unico pulso, por lo cual es tan simple como activar el SPI+DMA y olvidarte de lo demas, yo lo tengo asi, con un sampleado de unos 500khz y cuando quiero saber que valor tiene cada canal de ADC simplemente leo la variable y eso es lo que tiene. En realidad con el mismo pic tambien se puede hacer esto por su adc interno, sin embargo el tema de que solo puedes poner adc de 3.3v es un poco rollo, y hacer divisores resistivos y demas para 15 canales es un poco jodido.

El DMA es algo bastante util, puedes usarlo con cualquier periferico admitido y no necesitas intervenir para nada, por ejemplo si quieres hacer un PWM variable simplemente activas el DMA, el PWM y un timer para sincronizarlo y se acabo, te olvidas de tener que atender interrupciones ni nada, yo en el proyecto que ando haciendo llevo usado 7 canales de DMA de los 15 que tiene.
« Última modificación: 26 de Diciembre de 2013, 21:13:31 por MerLiNz »

Desconectado ALE1973

  • Colaborador
  • PIC16
  • *****
  • Mensajes: 229
Re: (Tutorial) DMA esta gran olvidada pero tan util!
« Respuesta #12 en: 27 de Diciembre de 2013, 00:29:47 »
Excelente, gracias por la información, estoy por empezar con los pics24, y lei que tienen DMA, asi que a usarla.

Saludos.
Alejandro.


Desconectado fidodido18

  • PIC18
  • ****
  • Mensajes: 312
Re: (Tutorial) DMA esta gran olvidada pero tan util!
« Respuesta #13 en: 07 de Noviembre de 2014, 11:40:43 »
lastima que no han seguido con este post. por favor podrían actualizar las imágenes, estoy interesado en el tema. Gracias.

Desconectado rpm

  • PIC10
  • *
  • Mensajes: 1
Re: (Tutorial) DMA esta gran olvidada pero tan util!
« Respuesta #14 en: 25 de Noviembre de 2014, 14:39:17 »
Hola

queria saber porque no veo las imagenes ya que tambien estoy intersado en el tema del DMA yo tengo un lio porque lo tenia todo configurado por UART y sin DMA Ahora decidi cambiarlo y todo correcto pero lo que no entiendo ahora es como almaceno en memoria y la reciclo es decir yo tengo esta interrupcion para la uart y dma 0 y 1:


void init_UART1()
{
   // configure U1MODE
    U1MODEbits.UARTEN = 0;  // Bit15 TX, RX DISABLED, ENABLE at end of func
    //U1MODEbits.notimplemented;    // Bit14
    U1MODEbits.USIDL = 0;   // Bit13 Continue in Idle
    U1MODEbits.IREN = 0;    // Bit12 No IR translation
    U1MODEbits.RTSMD = 0;   // Bit11 Simplex Mode
    //U1MODEbits.notimplemented;    // Bit10
    U1MODEbits.UEN = 0;     // Bits8,9 TX,RX enabled, CTS,RTS not
    U1MODEbits.WAKE = 0;    // Bit7 No Wake up (since we don't sleep here)
    U1MODEbits.LPBACK = 0;  // Bit6 No Loop Back
    U1MODEbits.ABAUD = 0;   // Bit5 No Autobaud (would require sending '55')
    U1MODEbits.URXINV =0;   // Bit4 IdleState = 1  (for dsPIC)
//  U1MODEbits.URXINV =0;   // Bit4 IdleState = 1  (for dsPIC)
    U1MODEbits.BRGH = 0;    // Bit3 16 clocks per bit period
    U1MODEbits.PDSEL = 0;   // Bits1,2 8bit, No Parity
    U1MODEbits.STSEL = 0;   // Bit0 One Stop Bit   
    // Load a value into Baud Rate Generator.  Example is for 9600.
    // See section 19.3.1 of datasheet.
    //  U1BRG = (Fcy/(16*BaudRate))-1
    //  U1BRG = (37.75M/(16*38400))-1
    //  U1BRG = 60.49
    U1BRG = BRGVAL; // 37.75Mhz osc, 38400 Baud
    // Load all values in for U1STA SFR
    U1STAbits.UTXISEL1 = 0; //Bit15 Int when Char is transferred (1/2 config!)
    U1STAbits.UTXINV =0;    //Bit14 N/A, IRDA config
    U1STAbits.UTXISEL0 = 0; //Bit13 Other half of Bit15
    //U1STAbits.notimplemented = 0; //Bit12
    U1STAbits.UTXBRK = 0;   //Bit11 Disabled
    U1STAbits.UTXEN = 0;    //Bit10 TX pins controlled by periph
    //U1STAbits.UTXBF = 0;  //Bit9 *Read Only Bit*
    //U1STAbits.TRMT = 0;   //Bit8 *Read Only bit*
    U1STAbits.URXISEL = 0B00;   //Bits6,7 Int. on character recieved
    U1STAbits.ADDEN = 0;    //Bit5 Address Detect Disabled
    U1STAbits.RIDLE = 0;    //Bit4 *Read Only Bit*
    U1STAbits.PERR = 0;     //Bit3 *Read Only Bit*
    U1STAbits.FERR = 0;     //Bit2 *Read Only Bit*
    U1STAbits.OERR = 0;     //Bit1 *Read Only Bit*
    U1STAbits.URXDA = 0;    //Bit0 *Read Only Bit*
    IPC2bits.U1RXIP = 4;
    IFS0bits.U1TXIF = 0;    // Clear the Transmit Interrupt Flag
    IEC0bits.U1TXIE = 0;    // Enable Transmit Interrupts
    IFS0bits.U1RXIF = 0;    // Clear the Recieve Interrupt Flag
    IEC0bits.U1RXIE = 0;    // Enable Recieve Interrupts
    U1MODEbits.UARTEN = 1;  // And turn the peripheral on
    U1STAbits.UTXEN = 1;
    // I think I have the thing working now.
   DMA0CON = 0x2001; // One-Shot, Post-Increment, RAM-to-Peripheral
   DMA0CNT = 7; // 8 DMA requests
   DMA0REQ = 0x000C; // Select UART2 Transmitter DMA0REQ = 0x000C para UART1
   
   DMA0PAD = (volatile unsigned int) &U1TXREG;
   DMA0STA = __builtin_dmaoffset(BufferA);
   
   IFS0bits.DMA0IF = 0; // Clear DMA Interrupt Flag
   IEC0bits.DMA0IE = 1; // Enable DMA interrupt   
   
//   Set up DMA Channel 1 to Receive in Continuous Ping-Pong mode:
   DMA1CON = 0x0002; // Continuous, Ping-Pong, Post-Inc., Periph-RAM
   DMA1CNT = 7; // 8 DMA requests
   DMA1REQ = 0x000B; // Select UART2 Receiver DMA1REQ = 0x000B para UART1
   
   DMA1PAD = (volatile unsigned int) &U1RXREG;
   DMA1STA = __builtin_dmaoffset(BufferA);
   DMA1STB = __builtin_dmaoffset(BufferB);
   
   IFS0bits.DMA1IF = 0; // Clear DMA interrupt
   IEC0bits.DMA1IE = 1; // Enable DMA interrupt
   DMA1CONbits.CHEN = 1; // Enable DMA Channel
}
//***********************interrupciones de la UART1 con DMA0 transmision y DMA1 para recepcion *************************//
void __attribute__((interrupt, no_auto_psv)) _DMA1Interrupt(void)
{
   IFS0bits.DMA0IF = 0; // Clear the DMA0 Interrupt Flag;
}
void __attribute__((interrupt, no_auto_psv)) _DMA0Interrupt(void)
{
   static unsigned int BufferCount = 0; // Keep record of which buffer
   // contains Rx Data
   if(BufferCount == 0)
   {
   DMA0STA = __builtin_dmaoffset(BufferA); // Point DMA 0 to data
   // to be transmitted
   }
   else
   {
   DMA0STA = __builtin_dmaoffset(BufferB); // Point DMA 0 to data
   // to be transmitted
   }
   DMA0CONbits.CHEN = 1; // Enable DMA0 Channel
   DMA0REQbits.FORCE = 1; // Manual mode: Kick-start the 1st transfer
   BufferCount ^= 1;
   IFS0bits.DMA1IF = 0; // Clear the DMA1 Interrupt Flag
}



Bien me recepciona cuando reseteo rn171 y recibo el mensaje de inicio pero necesito que sea mas grande.

int main(void)
{
    //***************configuracion del PLL para un FCY de 37.7 MIPS*********************//
    init_cpu();
   init_ports();   
    //********************************UART1 y 2***************************************//
    init_UART1();
    //init_UART2();
    //********************************************************************************//
    char buftx1[BUFFERRXSIZE];
   char *bufptrtx1=buftx1;   
   int charmessage=0;
   
   
   
    PORTBbits.RB4=1;
    resethw();
    __delay32(35000000);
      
    strcpy(buftx1,messagern0);
    send_no_files();
    while(1);

}

Antes era muy facil con la uart interrupt
//void __attribute__((interrupt, auto_psv)) _U1RXInterrupt(void)
//{
//   IFS0bits.U1RXIF = 0;   // clear interrupt flag
//   while(BusyUART1());
//   {
//      rxstate1=1;
//      while(DataRdyUART1())
//      {   
//         (*(bufptr1))= ReadUART1();
//         WriteUART2(*(bufptr1));
//         if ((*(bufptr1)!=0x00))
//         {
//            *bufptr1++;
//            bufcont1++;           
//            }         
//      }
//   }
//    rxstate1=0;
//    txstate1=0;
//}
//
//void __attribute__((interrupt, no_auto_psv)) _U1TXInterrupt(void)
//{
//   IFS0bits.U1TXIF = 0;
//   txstate1=0;
//}


pero queria saber como guardo el    DMA0STA = __builtin_dmaoffset(BufferA); dentro de una variable porque ahora esta en BufferA que 8*16bit y quería guardar por lo menos 512*8bit. Como hacia antes

Alguien me puede decir alguna forma de hacerlo.

Gracias