TODOPIC

Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: Modulay en 01 de Abril de 2008, 19:03:29

Título: USB en CCS: Detectando y gestionando la interrupción
Publicado por: Modulay en 01 de Abril de 2008, 19:03:29
Hola amigos.
Después de varios días peleando con el usb he sacado algunas cosillas en claro.Entre ellas cómo tener mi propia rutina de interrupción cuando se reciben datos por algún endpoint que no sea el endpoint 0,además de saber como acceder a los datos de forma más directa y controlada sin hacer uso de las funciones usb_gets, usb_get_packet o el consabido usb_kbhit.
No se si esto resulta válido para todas las clases de dispositivo,pero bueno,ahí va.

Las rutinas implicadas son usb_isr (pic18_usb.h), usb_isr_tok_out_dne (usb.c) y usb_isr_tok_dne() (pic18_usb.h)

Lo que yo he hecho es traerme a mi fichero principal las rutinas usb_isr y usb_isr_tok_dne() desde el fichero pic18_usb.h y colocar al final de usb_isr_tok_dne() una llamada a la que es mi rutina de interrupción (datos_endpoint)

Código: CSS
  1. #int_usb
  2. void usb_isr() {
  3.  
  4.    if (usb_state==USB_STATE_DETACHED) return;   //should never happen, though
  5.    if (UIR) {
  6.       debug_usb(debug_putc,"\r\n\n[%X] ",UIR);
  7.       if (UIR_ACTV && UIE_ACTV) { usb_isr_activity();}  //activity detected.  (only enable after sleep)
  8.       if (UCON_SUSPND) return;
  9.       if (UIR_UERR && UIE_UERR) {usb_isr_uerr();}          //error has been detected
  10.       if (UIR_URST && UIE_URST) {usb_isr_rst();}        //usb reset has been detected
  11.       if (UIR_IDLE && UIE_IDLE) {usb_isr_uidle();}        //idle time, we can go to sleep
  12.       if (UIR_SOF && UIE_SOF) {usb_isr_sof();}
  13.       if (UIR_STALL && UIE_STALL) {usb_isr_stall();}        //a stall handshake was sent
  14.       if (UIR_TRN && UIE_TRN) {
  15.          usb_isr_tok_dne();
  16.          UIR_TRN=0;    // clear the token done interrupt., 0x190.3
  17.       }  
  18.    }
  19. }
  20.  
  21.  
  22. void usb_isr_tok_dne() {
  23.    int8 en;
  24.    en=USTAT>>3;
  25.          debug_usb(debug_putc,"T ");
  26.          debug_usb(debug_putc,"%X ", USTAT);
  27.       if (USTAT==USTAT_OUT_SETUP_E0) {   //new out or setup token in the buffer
  28.          debug_usb(debug_putc,"%X ", EP_BDxST_O(0));
  29.          if ((EP_BDxST_O(0) & 0x3C)==USB_PIC_PID_SETUP) {
  30.             EP_BDxST_I(0)=0;   // return the in buffer to us (dequeue any pending requests)
  31.             debug_usb(debug_putc,"(%U) ", EP_BDxCNT_O(0));
  32.             debug_display_ram(EP_BDxCNT_O(0), usb_ep0_rx_buffer);
  33.             usb_isr_tok_setup_dne();
  34.             //if setup_0_tx_size==0xFF - stall ep0 (unhandled request)
  35.             //if setup_0_tx_size==0xFE - get EP0OUT ready for a data packet, leave EP0IN alone
  36.             //else setup_0_tx_size=size of response, get EP0OUT ready for a setup packet, mark EPOIN ready for transmit
  37.             if (__setup_0_tx_size==0xFF)
  38.                usb_flush_out(0,USB_DTS_STALL);
  39.             else {
  40.                usb_flush_out(0,USB_DTS_TOGGLE);
  41.                if (__setup_0_tx_size!=0xFE) {
  42.                   usb_flush_in(0,__setup_0_tx_size,USB_DTS_USERX);
  43.                }
  44.             }
  45.             UCON_PKTDIS=0;       // UCON,PKT_DIS ; Assuming there is nothing to dequeue, clear the packet disable bit
  46.          }
  47.          else if ((EP_BDxST_O(0) & 0x3C)==USB_PIC_PID_OUT) {
  48.             usb_isr_tok_out_dne(0);
  49.             usb_flush_out(0,USB_DTS_TOGGLE);
  50.             if ((__setup_0_tx_size!=0xFE)&&(__setup_0_tx_size!=0xFF)) {
  51.                usb_flush_in(0,__setup_0_tx_size,USB_DTS_DATA1);   //send response (usually a 0len)
  52.             }
  53.          }
  54.       }
  55.       else if (USTAT==USTAT_IN_E0) {   //pic -> host transfer completed
  56.          __setup_0_tx_size=0xFF;
  57.          usb_isr_tok_in_dne(0);
  58.          if (__setup_0_tx_size!=0xFF)
  59.             usb_flush_in(0,__setup_0_tx_size,USB_DTS_TOGGLE);
  60.          else
  61.             usb_init_ep0_setup();
  62.       }
  63.       else {
  64.          if (bit_test(USTAT,2)) {
  65.             usb_isr_tok_in_dne(en);
  66.          }
  67.          else {
  68.             usb_isr_tok_out_dne(en);
  69.             datos_endpoint(en);
  70.          }
  71.       }
  72. }

Dicha rutina se ejecuta cuando se reciben datos del host por el endpoint "en".Este endpoint siempre será distinto del endpoint 0,por lo que las transferencias de control del pic con el host nos serán transparentes y no nos molestarán.

Ahora bien ¿y dónde están los datos recibidos?
Cuando el módulo usb está habilitado,el pic coloca a partir de la posición de memoria 0x400 lo que viene a llamarse "Buffer Descriptor Table",que contiene una serie de registros que permiten gestionar los datos que fluyen a través de los endpoints,ya sea para transferencias OUT (PC -> PIC) como para transferencias IN (PIC -> PC)

(http://img258.imageshack.us/img258/4434/descriptoresbufferrh2.jpg)

Esta tabla de descriptores está ubicada al inicio del banco 4 y contendrá tantos descriptores (Buffer Desciptors) como endpoints use nuestro pic (por partida doble,UN DESCRIPTOR PARA IN ENDPOINT y OTRO PARA OUT ENDPOINT).
O sea,si en nuestro pic sólo usamos el Endpoint 1 (para IN y para OUT) en la tabla de descriptores de buffer tendríamos 4 descriptores,los dos del endpoint 0 (esos siempre deben estar,según las especificaciones) y los dos del endpoint 1.

En la imagen se ve el descriptor de buffer correspondiente al OUT Endpoint 0 (0x400-0x403)...consecutivo a él estaría el correspondiente al IN Endpoint 0 (0x404-0x407)...después estaría el OUT Endpoint 1 (0x408-0x40B)....etc

Hay que recordar que IN y OUT se consideran SIEMPRE desde la perspectiva del host,por lo que una transferencia OUT será siempre en el sentido PC -> PIC....así que los datos que se reciben desde el pc los gestionaremos siempre con el correspondiente EPn OUT Buffer Descriptor (siendo "n" el endpoint en cuestión).

Cada descriptor de buffer está compuesto de 4 registros:

BDnSTAT: Registro de estado del descriptor de buffer.
BDnCNT: Número de bytes (recibidos o a transmitir,según sea un IN Endpoint o un OUT Endpoint).
BDnADRL: Byte menos significativo de la dirección de comienzo de los datos.
BDnADRH: Byte más significativo de la dirección de comienzo de los datos.

Los bits 0 y 1 del registro BDnSTAT (CB8 y CB9) se usan para concatenarlos a los 8 del registro BDnCNT en el caso de transferencias de más de 256 bytes.
El bit 7 (UOWN) del mismo registro indica quien tiene la posesión del descriptor y su correspondiente búffer de datos.

¿y qué quiere decir esto?
Pues sencillo.

Tanto el CORE del micro (el programador y su programa,a fin de cuentas) como la SIE (módulo interno que gestiona el bus usb) tienen acceso a los descriptores y sus búferes,y tanto uno como el otro pueden realizar operaciones de escritura sobre ellos,por lo que el micro implementa una especie de semáforo (bit UOWN) para indicar cuando la SIE tiene el control y no se deben realizar operaciones de escitura ni en el descriptor ni en el búfer.

Los bits restantes del registro de estado y sus respectivas funciones cambian en función de quien tiene el control de los bufers.Os animo a que echeis un ojo al datasheet para saber un poco más de esto (Capítulo 17.4.1.2).

El registro BDnCNT no tiene mayor misterio...indica la cantidad de bytes recibidos tras una transferencia en un OUT Endpoint y deberá ser escrito con el valor adecuado en el caso de una transferencia a través de un IN Endpoint.

Los registros BDnADRH y BDnADRL son lo que son,un puntero para saber donde tenemos que ir a buscar los datos para transferencias OUT o un puntero para que la SIE sepa dónde tiene que ir a buscar los datos en una transferencia IN.

Hay que tener presente una cosa...el pic da la posibilidad de usar los buffers en modo Ping-Pong.Esto permite que,en vez de tener un descriptor y un buffer por cada endpoint (cuando digo "cada" estoy considerando IN Enpoint y OUT Endpoint por separado),tengamos todo por partida doble (descriptores y buffers).Dicha cosa permitiría por ejemplo que mientras la SIE está enviando un paquete de datos al host nosotros estemos escribiendo otro paquete al mismo tiempo.Esto para la agilización de las tasas de transferencia viene de perlas  :) aunque,por lo visto,el modo Ping-Pong no es fácil de domar.
En función de cual de los 4 modos Ping-Pong se use,la estructura de los descriptores cambia,por lo que hay que conocer el valor de los bits PPB1:PPB0 (registro SFR UCFG ) para determinar donde están nuestros descriptores.

(http://img230.imageshack.us/img230/9365/pingpongvg2.jpg)

Y bueno,un ejemplo de lo que pudiera ser la rutina de interrupción sería (considerando el modo Ping-Pong desactivado):

Código: CSS
  1. #define BD1OSTAT        0x408
  2. #define BD1OCNT         0x409
  3. #define BD1OADRL        0x40A
  4. #define BD1OADRH        0x40B
  5.  
  6. int8 buffer_usb_in[64];
  7.  
  8. void datos_endpoint(int8 ep)
  9. {
  10.   int8 i,bytes_recibidos,*ptr;
  11.   bytes_recibidos = *(BD1OCNT + ep*8);
  12.   ptr = 256*(*(BD1OADRH + 8*ep)) + (*(BD1OADRL + ep*8));
  13.   for(i = 0; i < bytes_recibidos; i++)
  14.     {
  15.     buffer_usb_in[i] = *ptr;
  16.     ptr++;
  17.     }
  18.   usb_flush_out(ep, USB_DTS_TOGGLE);  
  19. }

No hay que olvidar la llamada a usb_flush_out,que básicamente lo que hace es habilitar el endpoint para seguir recibiendo datos.

Pos lo dicho,espero que sea provechoso.
Saludo.






Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: RedPic en 02 de Abril de 2008, 01:34:31
Jose, no se si aplaudirte desde aquí o salir corriendo a Málaga a besarte a tornillo.  :D :D :D

Me voy a estudiar tu post como si fuese para un final de curso. Muchas gracias por abrir la brecha en este muro.  :mrgreen:
Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: Azicuetano en 02 de Abril de 2008, 03:14:13
Mmmhhh... información de la buena...  :D 

Thanks.


Un saludo desde Alicante.
Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: Modulay en 02 de Abril de 2008, 09:00:32
Me alegra que os sea de utilidad :)
Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: PalitroqueZ en 02 de Abril de 2008, 16:36:29
hey, muchas gracias por la información Modulay

una pregunta, y el consumo de recursos, ¿bajó? o ¿se mantiene en el 56%?

pd: lo extraño es que compilando tanto en el 2550 como en el 4550, siempre sale el 56%  :shock:

Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: Modulay en 02 de Abril de 2008, 17:32:27
Imagino que te refieres al consumo de ram.
Ambos micros cuentan con la misma cantidad de ram por lo que es normal que el consumo sea el mismo para los dos.

Yo estoy usando en estos momentos el 18F66J50 y estoy compilando al 86% de la capacidad de la ram.Aunque,resulta muy curioso el hecho de que la barra aparezca de color amarillo cuando normalmente lo hace de color verde.

(http://img337.imageshack.us/img337/5227/ccspc8.jpg)

Y me da a mí que es debido al hecho de que la habilitación del módulo usb implica que los bancos 4,5,6 y 7 (25% aproximado del total de ram del 18F66J50,50% del total de ram de los 18Fxx5x) quedan a disposición de la SIE para los descriptores de búffer y los búfferes de datos,por lo que el compilador la considera como ram consumida,pero aún así,disponible para el usuario.

(http://img363.imageshack.us/img363/4010/bancosew1.jpg)

Estos 4 bancos también pueden ser usados para almacenar tus datos,pero hay que tener cuidado ya que en un momento dado la SIE los puede machacar con lo que recibe del bus,y por supuesto,no se te ocurra toquetear el banco 4 a no ser que sepas que estás usando zonas de memoria que no contienen descriptores de búffer.A esto se suma el hecho de que,según el datasheet,no hay mecanismo hardware que impida la escritura o la lectura sobre una zona concreta de ram que esté en ese momento poseída por la SIE (el bit UOWN correspondiente lo indicará),pero advierte que pueden ocurrir cosas raras cuando se haga

Desconozco que criterio sigue la SIE a la hora de colocar los datos procedentes del host,pero supongo que obedecerá a un patrón concreto y acorde a los descriptores de búffer existentes.

Para saciar la curiosidad,lo que se puede hacer es declarar varios arrays a los bestia ubicados en ese espacio de memoria (0x400-0x7FF) y ver si al compilar aumenta el consumo de ram...apostaría a que no
Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: gu1llermo en 02 de Abril de 2008, 18:25:23
Esto es un lujo de información, gracias Modulay por compartirla con todos nosotros  :mrgreen:

Saludos.
Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: Modulay en 02 de Abril de 2008, 18:49:31
Lo que me temía...ni se ha despeinado,oye  :D

(http://img383.imageshack.us/img383/6518/arraywb9.jpg)
Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: J1M en 02 de Abril de 2008, 19:23:36
Gracias por la explicación, la verdad siempre viene bien eso de 'olvidar' un poco lo que nos dan hecho, puesto que muchas veces podemos arrancarle unos cuantos bytes de optimización :)
Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: pocher en 03 de Abril de 2008, 06:19:37
Yo también te lo agradezco Modulay. Cuando pueda intentaré comprender esta valiosa información.

Un saludo
Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: Modulay en 03 de Abril de 2008, 06:43:54
Gracias por la explicación, la verdad siempre viene bien eso de 'olvidar' un poco lo que nos dan hecho, puesto que muchas veces podemos arrancarle unos cuantos bytes de optimización :)

No estaríamos hablando hoy de esto si en su día tú no nos hubieras abierto la puerta a este mundillo del usb.
Yo tan sólo puse una piedrecita más sobre lo que otros construyeron antes.
Y esperemos que siga creciendo!!
Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: PalitroqueZ en 03 de Abril de 2008, 16:04:53
uuy Modulay se me está haciendo agua la boca con esos candentes tips acerca del usb, me dan ganas de dejar de hacer el proyectico en que estoy metido para meterle al usb.. pero no puedo :(

hay una sospecha que tengo, referente al gran consumo de ram, puede que exista la posibilidad que esos codigos de ccs esten usando todos los endpoint y por ello se lleva tanta memoria. Habría que investigar (y es  otro reto que tengo) de hacer una modificación para usar un solo endpoint (con la interrupción por supuesto), y con ello reducir mas lineas.

en otros "driver" que he visto en la carpeta PICC, son demasiado genericos, y sacan muchas cuentas inutiles en proyectos particulares.


Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: Modulay en 03 de Abril de 2008, 17:47:33
El tema de los endpoints va encapsulado en el descriptor de configuración del dispositivo (cosa que el compilador no va a saber interpretar) y, aparte de eso, no hay más que un par de DEFINES por ahí que se añaden al programa para habilitar los endpoints que vayas a usar,de cara a las rutinas.

Localiza esta línea en la parte de arriba del fichero pic18_usb.h...

 #define USB_TOTAL_BUFFER_SPACE  ((int16)0x300)

...cambia el 0x300 por 0x200, 0x100, etc...compila y observa lo que pasa...

Después,un poco más abajo,localiza esta y coméntala:

#reserve 0x400:0x4FF+USB_BUFFER_NEEDED

...vuelve a compilar....y observa.

Ahora vuelve a poner la primera que cambiaste con el valor que tenía originalmente,localiza esta línea (allá por la línea 414) y coméntala...compila...

No se trata de que el compilador active endpoints a nuestras espaldas...lo que si hace es reservar memoria para sus búfferes y para los descriptores de los búfferes.

Pero ahora que has sacado el tema,hay una cosa que no mo cuadra,y es la coexistencia de esto...

Código: [Seleccionar]
char usb_data_buffer[USB_TOTAL_BUFFER_SPACE-USB_MAX_EP0_PACKET_LENGTH-USB_MAX_EP0_PACKET_LENGTH];
#locate usb_data_buffer=USB_BUFFER+USB_MAX_EP0_PACKET_LENGTH+USB_MAX_EP0_PACKET_LENGTH

// Array que ocupa al completo (quitando los búferes de EP0 IN y EP0 OUT,o sea 16 bytes) los bancos 5, 6 y 7 = 752 bytes

...con esto

Código: [Seleccionar]

#reserve 0x400:0x4FF + USB_BUFFER_NEEDED

// Reserva el banco 4 para los descriptores de buffer,vale,eso me parece bien...pero,si ya tenemos declarado un array que ocupa prácticamente toda la USB RAM y que contendrá los búfferes de todos los endpoints exceptuando el EP0 ¿¿¿[size=15pt]POR QUÉ[/size] reserva también USB_BUFFER_NEEDED bytes??


Me parece algo redundante teniendo en cuenta que el valor de USB_BUFFER_NEEDED depende de los endpoints que usemos y del tamaño que les pongamos...a más endpoints y más tamaño,más gorda es la redundancia.

Código: [Seleccionar]

#define USB_BUFFER_NEEDED (USB_EP0_TX_SIZE+USB_EP0_RX_SIZE+USB_EP1_TX_SIZE+USB_EP1_RX_SIZE+USB_EP2_TX_SIZE+USB_EP2_RX_SIZE
+USB_EP3_TX_SIZE+USB_EP3_RX_SIZE+USB_EP4_TX_SIZE+USB_EP4_RX_SIZE+USB_EP5_TX_SIZE+USB_EP5_RX_SIZE
+USB_EP6_TX_SIZE+USB_EP6_RX_SIZE+USB_EP7_TX_SIZE+USB_EP7_RX_SIZE+USB_EP8_TX_SIZE+USB_EP8_RX_SIZE
+USB_EP9_TX_SIZE+USB_EP9_RX_SIZE+USB_EP10_TX_SIZE+USB_EP10_RX_SIZE+USB_EP11_TX_SIZE+
USB_EP11_RX_SIZE+USB_EP12_TX_SIZE+USB_EP12_RX_SIZE+USB_EP13_TX_SIZE+USB_EP13_RX_SIZE+
USB_EP14_TX_SIZE+USB_EP14_RX_SIZE+USB_EP15_TX_SIZE+USB_EP15_RX_SIZE)


Yo uso 2 endpoints de 64 bytes.Tengo estas dos líneas en mi programa:

#define USB_EP1_TX_SIZE    64
#define USB_EP1_RX_SIZE    64

Lo que quiere decir que CCS me está consumiendo,por redundancia en la compilación, 128 bytes más de los que debe.

 :?







Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: Modulay en 03 de Abril de 2008, 17:52:51
Al final,de forma indirecta,has dado en el clavo.
Ese array no debería estar declarado de esa forma.Da por sentado de que los endpoints van a ocupar toda la USB RAM...y yo en mi caso solo ocupo 128 bytes,además de los 16 del EP0

Debería bastar con la directiva #reserve...esa si reserva la cantidad justa de RAM
Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: Modulay en 03 de Abril de 2008, 18:14:20
Me he cepillado el array,he programado el micro...sigue funcionando perfectamente...

Pero he pasado de esto...


(http://img396.imageshack.us/img396/1255/compilado1df5.jpg)


...a esto...


(http://img213.imageshack.us/img213/6133/compilado2nb1.jpg)


Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: gu1llermo en 03 de Abril de 2008, 21:58:26
Guao!!!  :shock: ya no te prende la luz amarilla, eso significa que tenemos más espacio para declarar más variables para nosotros como programadores?? y perdona mi ignorancia.

Saludos.
Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: Modulay en 04 de Abril de 2008, 09:16:53
Eso mismo.
El problema no es que la memoria no estuviera libre en tiempo de ejecución,que si lo está.El problema es que llega un momento en que para el compilador no lo está y no te deja seguir creando variables
Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: Modulay en 04 de Abril de 2008, 09:21:02
De todas formas habrá que ojear los ficheros auxiliares a ver qué uso le da el compilador a ese array.
Algo hará con él,digo yo.
Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: gu1llermo en 04 de Abril de 2008, 09:59:25
Ah! ok, gracias por responder.
Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: PalitroqueZ en 05 de Abril de 2008, 13:42:43
Modulay, ¡¡ya casi lo tienes!!  :P

el caso que te dije con lo de programas genericos, lo vi en el archivo mmc_spi.c hay muchas funciones que consumen mucho espacio, y como todos sabran, la idea es optimizar el código lo mejor posible.


con tu permiso voy a imprimir todo lo que has explicado generosamente.  :mrgreen:

Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: Modulay en 05 de Abril de 2008, 16:41:28
Tiene usted mi bendición :)
Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: PalitroqueZ en 07 de Abril de 2008, 12:33:07
Estuve leyendo la datasheet y otros documentos que imprimí en su tiempo. (por cierto tengo que leerlo varias veces para enterdelo mejor) a

a ver si comprendo, entonces quiere decir que ese ¿porcentaje de ram que muestra el ccs es virtual? porque puede darse el caso que yo en una condición ejecute procesos en el pic y otra condición use exclusivamente el usb.

de ser así la ram-usb solo sería usada en la última condición, aunque el ccs me la muestra estadisticamente como "apartada"

sabemos que UOWN se activa para indicarle al pic que se va acceder a la ram-usb, la pregunta a resolver es: ¿podemos determinar que segmento de la memoria utilizará la SIE para así no perjudicar las otras areas ram? todo ello con el objetivo de no machacar la ram usada tal como mencionas modulay

seguiré investigando...



Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: PalitroqueZ en 25 de Abril de 2008, 17:51:59
después de salcochar la lectura del capitulo en la datasheet respecto a la ram-usb llego a la conclusión que el problema es que 2KB de ram es muy poca memoria para los 18f4550, a la final solo tendras 1KB de ram para ti, la única forma es que uses los otros 1KB en una condición en que no estes usando el usb.

De lo contrario, es como dejar un objeto en una habitación compartida, no sabes si lo encuentras la próxima vez que pases por ahí  :x

pd: uff me pasé de offtopic, debería comentarlo en el hilo que hizo Bruno hace un tiempo.

Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: Modulay en 25 de Abril de 2008, 18:46:38
Vaya,no me dí cuenta de que había nuevas respuestas.

CCS reserva memoria para los búferes con la directiva #reserve y aparte declara un array que ocupa dichos búferes.Esto resulta redundante y, en tiempo de compilación, lo que hace es ocupar 2 veces la misma zona de memoria (aunque suene raro) sin ser "consciente" de ello,por lo que el indicador de RAM usada aumenta igualmente.

La solución que yo le veo a esto y que tras probarla parece ir bien es la de eliminar la declaración del array mencionado más arriba,ya que la memoria se sigue reservando de igual forma (en la justa medida que impongan los endpoints que uses) y no hay peligro de que tus variables se metan dentro de la zona de búferes...eso si,desconozco si se le llega a dar uso a ese array en alguna de las librerías...a mí por el momento me ha compilado y ejecutado bien.

Como dije antes,para saber que segmentos de la usb-ram van a ser accedidos por la SIE hay que ver qué endpoints se tienen activos,qué tamaño de paquete maneja cada uno y qué modo Ping-Pong se está usando...sabiendo estas tres cosas se puede deducir qué zonas de memoria pueden ser accedidas por la SIE,y consultando el bit UOWN que corresponda se podrá saber si en un instante dado un búffer está tomado por ella.

Realmente los 2kB están ahí (quitando desde 0x400 a 0x4FF,que se reserva para los descriptores de buffer y que seguramente también estén mal gestionados y gasten esa página de ram tontamente) y puedes usarlos,simplemente hay que eliminar el dichoso array.
Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: Cryn en 01 de Octubre de 2008, 14:25:07
Hola Modulay, muy buen trabajo el que haz hecho.
Tengo algunas dudas, espero que puedas ayudarme, o quizá algún otro forero

Miren les cuento que hice hace ya bastante tiempo hice la comunicación USB, pero utilizando el usb_kbhit() y pues esa vez me ha ido muy bien, ahora pretendo hacer un proyecto en el cual incluya tb la comunicación USB, pero esta vez debo gestionarlo por interrupción, pues el uC tb estará realizando otras operaciones.

He leído todos los post, y tengo algunas preguntas, ojalá puedan responderme

En el código, también tengo que incluir todas las librerias que se incluyen en la forma sin interrupcion? o solo copiar los código que están en los primeros posts del hilo?

Para inicializar el USB, y esperar la numeración, se hace lo mismo que en el método de no interrupción?

Talvez utilice un buffer de 128bytes como mínimo de IN y OUT, no hará falta que sea pinpong, cual es el máximo valor de buffer que puedo utilizar? y que pasa si solo necesito 1byte?

Modula, quizá sea muy atrevido de mi parte, pero si es puedes, nos colocas todo el codigo que hiciste apra poder ver las librerias qeu se incluyen, los pasos a seguir para habilitar el usb por interrupcion y todo ello.

Muchas gracias por la ayuda
un saludo.
Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: Modulay en 01 de Octubre de 2008, 15:58:58
En el código, también tengo que incluir todas las librerias que se incluyen en la forma sin interrupcion? o solo copiar los código que están en los primeros posts del hilo?

Las rutinas que te debes traer a tu fichero principal (si lo haces de la forma que yo sugerí) y el resto de rutinas que se usan para la inicialización del usb hacen uso de otras rutinas contenidas en las librerías, por lo que las invocaciones a éstas no pueden faltar.

Para inicializar el USB, y esperar la numeración, se hace lo mismo que en el método de no interrupción?



Talvez utilice un buffer de 128bytes como mínimo de IN y OUT, no hará falta que sea pinpong, cual es el máximo valor de buffer que puedo utilizar? y que pasa si solo necesito 1byte?

Que yo sepa, el tamaño máximo para transferencias bulk es 64 bytes.

Modula, quizá sea muy atrevido de mi parte, pero si es puedes, nos colocas todo el codigo que hiciste apra poder ver las librerias qeu se incluyen, los pasos a seguir para habilitar el usb por interrupcion y todo ello.

No es necesario, Cryn.
Las librerías usadas son las mismas.
La interrupción usb es habilitada con la llamada a usb_tasks() si no recuerdo mal. Aún sin ser consciente de ello, la interrupción usb ya se produce y se atiende aunque hagas polling con la función kbhit(), sólo que no tienes control sobre ella.
Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: Cryn en 01 de Octubre de 2008, 16:19:58
gracias por la respuesta Modulay.

Me quedó una duda más, si mal no recuerdo si hago USB como en uno de los primeros hilo sobre usb (J1M, creo que lo desarrollo muy bien) incluyendo todas las librerias y ejecutando las funciones necesarias el espacio de ROM (FLASH) que se usaba era de más o menos 50% del total, y ahora viendo tu codigo no ha ocupado ni el 20%, quizá sea por el micro que usaste, es mucha la diferencia de FLASH entre el 4550 y el micro que usaste?

dejame ver si he entendido bien, esto qeu desarrollaste utiliza interrupcion en USB, verdad? y al parecer ocupa menos FLASH? o es que me confundí?

un saludo
Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: Modulay en 01 de Octubre de 2008, 17:38:33
El micro que usé es distinto,sí.
Concretamente,es el 18F66J50.De ahí que las cuentas no te cuadren.
El consumo de memoria de programa no varía por enfocar el uso del usb gestionando tú mismo la interrupción...lo que sí puedes optimizar de forma considerable es el gasto de RAM, ya que ccs, por defecto, la administra de forma pésima cuando se habilita el usb (aunque eso tiene más que ver con la gestión de los búferes que con la interrupción en sí).
Ese tema también se trató en este hilo.
Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: Cryn en 02 de Octubre de 2008, 12:16:57
vale, si en efecto consume algo más de RAM, ya me fije en mi trabajo que hice hace tiempo.

Tengo unas nuevas duda, disculpa la insistencia y molestia.

Citar
Las rutinas que te debes traer a tu fichero principal (si lo haces de la forma que yo sugerí) y el resto de rutinas que se usan para la inicialización del usb hacen uso de otras rutinas contenidas en las librerías, por lo que las invocaciones a éstas no pueden faltar.
cuando dices traer te refieres a copiarlas o a moverlas, yo supongo que debe ser moverlas, o no?

si no me equivoco J1M modificó una parte de las librerias, esto afectará? pues estos usando lo que alguna vez J1M nos dejó, o uso netamente lo que nos da CCS?

Todavía no me queda claro lo de los endpoints, si podrías decirme porfavor que enpoints usaba J1M y si estos se deben especificar en el programa de la PC al momento de enviar y recibir datos? como te mencione creo que solamente usaré un buffer de Salida y otro de entrada, pero en la PC no me queda claro.

Agradezco tu ayuda y tu tiempo Modulay, un saludo


Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: Modulay en 02 de Octubre de 2008, 13:11:52
No puedes tener en tu código dos rutinas con el mismo nombre.Por lo que deberás moverlas,no copiarlas.

Que yo recuerde, las modificaciones que hizo J1M consistían únicamente en los descriptores de dispositivo. Dependiendo del tipo de dispositivo que vayas a implementar (CDC,MSD,AUDIO,HID,etc..) y de otras cuestiones como el tema de endpoints, dichos descriptores deben tener una estructura y contenido concretos.

Del lado del host, no recuerdo el modo de gestionar los endpoints, pero por lógica, también se deberían poder gestionar de forma independiente, es decir, recibir y/o enviar cada vez por un endpoint concreto.

Esto de los endpoints, mirándolo del lado del pic, imagínalos como si se tratara de usarts. Cada endpoint es una usart...con sus registros de control (descriptores de buffer), sus registros de dato (buffers),etc...la diferencia radicaría en que todos los endpoints lanzan una misma rutina de interrupción, y de la forma que yo implementé el tema, el endpoint responsable de la interrupción estará indicado por el parámetro "en" de la rutina "datos_endpoint(en)", por lo que sabrás a donde tienes que ir a buscar los datos que te han llegado cuando dicha interrupción se produzca.
Si sólo vas a usar un endpoint, pues dicho parámetro te es supérfluo.

Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: Cryn en 02 de Octubre de 2008, 13:30:09
ok ya lo entiendo mejor, si como dices el compilador me dio un error cuando encontró dos funciones iguales

ahora espero sean mis ultimas preguntas: tu usaste solo las librerías del CCS verdad? modificándolas un poco, verdad? y en que valores dejaste los parametros que modificaste para qeu no te consuma la ram innecesariamente??

crees que pueda ser asi:

#define USB_TOTAL_BUFFER_SPACE  ((int16)0x80)   //0x80 por los dos buffer de 64 bytes de I/O o solo 0x40?

//#reserve 0x400:0x4FF+USB_BUFFER_NEEDED  //esta linea comentada

char usb_data_buffer[USB_TOTAL_BUFFER_SPACE-USB_MAX_EP0_PACKET_LENGTH-USB_MAX_EP0_PACKET_LENGTH];
#locate usb_data_buffer=USB_BUFFER+USB_MAX_EP0_PACKET_LENGTH+USB_MAX_EP0_PACKET_LENGTH
estas dos lineas tb comentadas??

usaré los 64bytes maximos como tu, que lineas debo comentar o cambiar?

gracias por la ayuda Modulay y por responder tan rápido.
Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: Modulay en 02 de Octubre de 2008, 13:38:19
Mejor así

Código: C++
  1. #define USB_TOTAL_BUFFER_SPACE......... // esta no la toques
  2.  
  3. #reserve 0x400:0x4FF+USB_BUFFER_NEEDED
  4.  
  5. //char usb_data_buffer[USB_TOTAL_BUFFER_SPACE-USB_MAX_EP0_PACKET_LENGTH-USB_MAX_EP0_PACKET_LENGTH];
  6. //#locate usb_data_buffer=USB_BUFFER+USB_MAX_EP0_PACKET_LENGTH+USB_MAX_EP0_PACKET_LENGTH

Los endpoints que uses y sus respectivos tamaños y tipos (BULK,INTERRUPT,etc...) los puedes especificar en tu programa principal (J1M lo hace así en su ejemplo).
Eso sí,recuerda que todo descriptor de endpoint (los descriptores de dispositivo están contenidos en el fichero Pic_usb.h en el ejemplo de J1M) deberá reflejar también el tamaño de dicho endpoint.
Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: Cryn en 02 de Octubre de 2008, 16:21:57
bien, creo que todo lo preeliminar esta fuera de dudas.

Ahora me han surgido dudas en el momento de la obtención y envió de datos, antes hacía esto:

Código: [Seleccionar]
#define LEDV    PIN_A0
#define LEDR    PIN_A1
#define LED_ON  output_high
#define LED_OFF output_low

#define modo      recibe[0]
#define param1    recibe[1]
#define param2    recibe[2]
#define resultado envia[0]

int8 recibe[3];                  //declaramos variables
int8 envia[1];

void main(void) {
   LED_OFF(LEDV);                   //encendemos led rojo
   LED_ON(LEDR);
   usb_init();                      //inicializamos el USB
   usb_task();                      //habilita periferico usb e interrupciones
   usb_wait_for_enumeration();      //esperamos hasta que el PicUSB sea configurado por el host
/*------------------------------------------------------------------------------------------*/
   LED_OFF(LEDR);   //en este nivel me daba cuenta que el micro fue configurado correctamente
   LED_ON(LEDV);                    //encendemos led verde
/***************************************************************************/
   while (TRUE){
      if(usb_enumerated()){          //si el PicUSB está configurado
         if (usb_kbhit(1)){          //si el endpoint de salida contiene datos del host
            usb_get_packet(1, recibe, 3); //cojemos el paquete de tamaño 3bytes del EP1 y almacenamos en recibe, recibe es el nombre de mi buffer
            if (modo == 0){ // Modo_Suma
               resultado = param1 + param2;  //hacemos la suma
               usb_put_packet(1, envia, 1, USB_DTS_TOGGLE); //enviamos el paquete de tamaño 1byte del EP1 al PC
            }
            if (modo == 1){ //Modo_Led
               if (param1 == 0) {LED_OFF(LEDV); LED_OFF(LEDR);} //apagamos los leds
               if (param1 == 1) {LED_ON(LEDV); LED_OFF(LEDR);} //encendemos led verde
               if (param1 == 2) {LED_OFF(LEDV); LED_ON(LEDR);} //encendemos led rojo
            }
         }
      }
   }
}

ahora haciendo tu proceso como debo gestionar los datos?, como recibo y como transmito??

un saludo
Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: Modulay en 02 de Octubre de 2008, 18:01:18
Para enviar puedes usar:

usb_puts(endpoint, puntero_a_los_datos, bytes_a_enviar, 10);

Para recibir...deberías volver a leer el hilo con más detenimiento.
Si te surgen dudas al respecto, aquí ando :)
Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: Modulay en 02 de Octubre de 2008, 18:06:36
La llamada a usb_task() sobra.
Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: Cryn en 11 de Octubre de 2008, 12:37:32
hola modulay, ahora que he probado el usb con el kbhit, me doy cuenta que es mucho mejor gestionar uno mismo la interrupcion.

He vuelto a leer tus post, y pues entiendo que los datos se almacenarán a partir de la posición 0x400 de la ram, en realidad desde la x500, pues desde la x400 se almacenan registros para el amnejo de los endpoints. Pero mira nose si será que no lo leí o no lo entendí pero creo que debería haber algo que te diga que tu buffer ha terminado de recibir datos, quizá se me haya pasado o es que si no lo entendí. Si fueras tan amable de explicarme como saber que ya he recibido datos en mi buffer te lo agradeceré

un saludo amigo, gracias por la ayuda.
Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: Modulay en 11 de Octubre de 2008, 17:23:48
Cuando eso ocurre,salta la interrupción...de ahí que debas hacer el trapicheo de traerte a tu fichero principal las rutinas relacionadas y, como yo hice, coloques una llamada a una rutina tuya donde hagas el tratamiento de la interrupción. Los registros BD1OADRH y BD1OADRL contienen la dirección de comienzo de los datos recibidos y el registro BD1OCNT indica la cantidad de bytes que se han recibido (dando por hecho que estamos hablando del out endpoint 1)
Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: Modulay en 11 de Octubre de 2008, 17:28:56
El primer segmento de código del primer post son las rutinas que te tienes que traer al main...y si te fijas, al final de dicho segmento he añadido la llamada a la que es mi rutina de interrupción...
En el segundo segmento de código de ese mismo post está implementada dicha rutina a modo de ejemplo
Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: Cryn en 14 de Octubre de 2008, 15:41:22
ok, lo que me quieres decir entonces es que con esa tu rutina de interrupción ya haces que todos los datos necesarios esten donde deberían??

ahorita, en tu codigo existe algun flag que te diga que hay datos en el buffer? de no haberlo donde debería colocarlo?

disculpa la preguntadera, todavía sigo trasteando con el codig, gracias por la ayuda, me srve bastante, un saludo Modulay
Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: kain589 en 06 de Marzo de 2009, 22:40:56
...Entre ellas cómo tener mi propia rutina de interrupción cuando se reciben datos por algún endpoint que no sea el endpoint 0...

Una duda que tengo, esto es para todos los endpoints y ademas el "0", o para todos excluyendo el "0"

Es que al decir propia rutina para endpoint que no sea el cero, no sé si la de ccs solo sirve para el endpint cero
Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: Modulay en 07 de Marzo de 2009, 13:09:09
Es para todos los endpoints excluyendo el 0. Dicho endpoint se usa para transferencias de control y ccs ya se encarga de gestionarlas, por lo que no hay que preocuparse por el endpoint 0.
Por defecto, las rutinas de ccs para gestionar las interrupciones usb trabajan de la misma manera para todos los endpoints y lo hacen de forma "oculta" al programador...lo que se explica en este hilo son una serie de modificaciones para tener control sobre la interrupción (ya que por defecto sólo se puede acceder a los datos mediante polling) , permitiendo escribir una rutina de tratamiento de interrupción que se adapte a nuestras necesidades.
Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: kain589 en 07 de Marzo de 2009, 15:02:16
Muchas gracias por la contestacion, la verdad es que siempre habia creido que en los proyectos con usb se usaba el endpoint 0, pero ahora al mirarlos veo que usan el 1. Es una de esas veces que das algo por supuesto sin comprobarlo; y de ahi que me llamara la atencion que no usaras el endpoint que yo creia que todo el mundo usaba
Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: PalitroqueZ en 07 de Marzo de 2009, 15:36:57
kain es que el endpoint 0 se usa siempre, lo usa el dispositivo para responderle al host cuando se conecta la primera vez y todas las comunicaciones que no tienen que ver con los datos que nosotros gestionamos

Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: kain589 en 07 de Marzo de 2009, 18:05:25
PalitroqueZ, me referia a usado para los datos, siempre pense que todo,control y datos, se gestionaba mediante el endpoint 0, ahora veo que no. Gracias por las aclaraciones a los dos
Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: PalitroqueZ en 09 de Marzo de 2009, 17:13:30
PalitroqueZ, me referia a usado para los datos, siempre pense que todo,control y datos, se gestionaba mediante el endpoint 0, ahora veo que no. Gracias por las aclaraciones a los dos

ahh ¡entendido!  :mrgreen:

Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: Andres D en 20 de Abril de 2009, 20:54:01
Hola.

Quisiera saber si hay algún modo de gestionar la interrupción por USB sin necesidad de copiar las funciones de las librerias mencionadas, y usando el comando usb_get_packet.

Aclaro que no me interesa manipular los registros de los endpoint directamente, sino simplemente usar usb_get_packet cada vez que se detecte la interrupción.


Quisiera manipular la interrupción con un formato igual o parecido al siguiente (ejemplo para el ADC):

#int_ad
control_adc()
{
   adc_activo=FALSO;
}

Gracias.
Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: rafaelnotty en 29 de Julio de 2010, 18:39:22
...sta muy exelente este foro!! ahora a probar todo!

modulay! primero mis respetos por el manejo del tema q tienes

una preguntik la insercion de la funcion (datos_endpoint(en) ; ) esta dentro de un else q podria no entrar en esa parte del codigo
y no "continuar" con la interrupcion personalizada, una mejor opcion no seria dejar esta funcion fuera de todos los "if" para q siempre
se llegue a este codigo.
bno y otra cosa es el parametro de la funcion (en) aqui se utiliza 1,2,3? yo solo necesito un solo endpoint puedo dejar siempre un "1" alli?
Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: rafaelnotty en 29 de Julio de 2010, 23:43:05
hola a todos... agradesco quien me pueda colaborar en esto
bueno amplio aqui el planteamiento de mi problemilla:
mi targeta de comunicacion con el pic18f4550 recibe solo 1 solo paquete y no es posible recibir otro paquete solo conectandolo y lo desconectandolo del puerto usb
y pienso q todo el proble es por las interrupciones, intente hacer lo del amigo modulay pero bno, estoy intentandolo... (http://C:/ftproot)

interrupts disable during call to prevent re-entrancy: (usb_token_reset)


gracias por la colaboracion.
Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: Modulay en 30 de Julio de 2010, 09:15:07
Esas ramas "if" son necesarias, ya que engloban las comunicaciones en ambos sentidos, con transferencias de control por endpoint 0 implicadas y tal...

Pon tu código a ver si encontramos algo raro.

Saludo
Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: rafaelnotty en 30 de Julio de 2010, 17:38:51
bueno, aqui yo tengo varios enredos:

1. la velocidad del micro no esta bn, debido a que las rutinas delays no tardan lo que deberian pese a que el reloj esta en 4.000.000 y el cristal fisicamente sta bn

2. no entendi tu subrutina datosenpoit(en) por tanto no pude implementar algo parecido para sacar los datos directamente del buffer (porfa si puedes explicarla seria exelente)

3. consegui bn conexion con el usb, pero esta se pierde luego de recibir del pc los primeros 64 bytes (no se vuelven a producir interrupciones pero el codigo del main sigue ejecutandose) y entonces me di cuenta q conectando y desconectando podia restablecerse la conexion, entonces lo hice por los comandos usb_detach ();  usb_attach ();   usb_init();  usb_task();  usb_wait_for_enumeration(); despues de recibir cada paquete de 64bytes

4. funcionando esta parte, a mi me sirve porq solo necesito enviar comando a unas targetas por i2c pero aparecio otro problema, el usb deja de funcionar, ya probe con la misma tactica del usb_detach ();  usb_attach (); (conectando y desconectando por comandos) pero nada ya no funciona, como q no pueden coexistir estos 2 protocolos, ¿se necesitara algo mas?.

aqui esta el codigo:
Código: [Seleccionar]
#include <18F4550.h>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL1,CPUDIV1,VREGEN,MCLR,NOPBADEN
// No olvide que PLL1 = Para un Xtal de 4Mhz
//               PLL2 = Para un Xtal de 8Mhz
//               PLL3 = Para un Xtal de 12Mhz
//               PLL4 = Para un Xtal de 20Mhz , etc.
#use delay(clock=4000000)
#use i2c(Master,Fast,sda=PIN_B0,scl=PIN_B1,restart_wdt,force_hw)

#define USB_HID_DEVICE     FALSE              //deshabilitamos el uso de las directivas HID
#define USB_EP1_TX_ENABLE  USB_ENABLE_BULK    //turn on EP1(EndPoint1) for IN bulk/interrupt transfers
#define USB_EP1_RX_ENABLE  USB_ENABLE_BULK    //turn on EP1(EndPoint1) for OUT bulk/interrupt transfers
#define USB_EP1_TX_SIZE    64                 //size to allocate for the tx endpoint 1 buffer
#define USB_EP1_RX_SIZE    64                 //size to allocate for the rx endpoint 1 buffer

//#define USB_CON_SENSE_PIN PIN_B2  //CCS 18F4550 development kit has optional conection sense pin

#include <pic18_usb.h>              //Microchip PIC18Fxx5x Hardware layer for CCS's PIC USB driver
#include <usb_desc_scope.h>         //descriptors del Pic USB
#include <usb.c>                    //handles usb setup tokens and get descriptor reports

/*////////////////////////////////////////////////////////////////////
               
         0xD8,0x04,           //vendor id (0x04D8 is Microchip)
         0x0B,0x00,           //product id
         0x01,0x00,           //device release number

*/////////////////////////////////////////////////////////////////////

#BYTE ADCON1  = 0x0FC1                         
#BYTE CMCON   = 0x0FB4                         

int8 dato[64];
int8 dato2[64];

void main(void) {
   set_tris_a(0);
   set_tris_b(0);
   dato2[1]=123;
   output_a(0);
   delay_ms(1000);
   output_bit (pin_B0,1);
   output_bit (pin_B1,0);
   delay_ms(1000);
   usb_init();                                  // inicializamos el USB
   usb_task();                                  // habilita periferico usb e interrupciones
   usb_wait_for_enumeration();                  // esperamos hasta que el PicUSB sea configurado por el host
   output_bit (pin_B0,0);
   output_bit (pin_B1,1);
   delay_ms(1000);
   
   ADCON1 = 0x0F; 
   CMCON  = 0x07;   
   set_tris_a(0);
   //disable_interrupts(GLOBAL);

   while (TRUE)
   {
 
      if(usb_enumerated())                      // si el Pic está configurado via USB
      {
       if (usb_kbhit(1))                      // si el endpoint de salida contiene datos del host
         {
        // disable_interrupts(GLOBAL);
          delay_ms(10000);
          output_toggle(PIN_B7);
          delay_ms(10000);
          output_toggle(PIN_B7);
          delay_ms(2000);
         
          usb_get_packet(1, dato, 64);   
          output_a(dato[0]);
          delay_ms(1000);
          dato[0] =142;// input_c();                   
          usb_put_packet(1, dato, 64, USB_DTS_TOGGLE); //leer q es dts toggle
          delay_ms(1000);
          usb_detach ();
/*          delay_ms(100);
          i2c_start();
          i2c_write(2);     // Device address
          i2c_write(2);     // Device address
          delay_ms(1000);
          i2c_write(dato[0]);  // Data to device
          delay_ms(1000);
          i2c_stop();

*/         
          //enable_interrupts(GLOBAL);
          delay_ms(100);
          usb_attach ();
          usb_init();                                  // inicializamos el USB
          usb_task();                                  // habilita periferico usb e interrupciones
          usb_wait_for_enumeration();
         }
       }
   }
}

Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: Modulay en 30 de Julio de 2010, 21:19:13
Código: CSS
  1. #define BD1OSTAT        0x408
  2. #define BD1OCNT         0x409
  3. #define BD1OADRL        0x40A
  4. #define BD1OADRH        0x40B
  5.  
  6. int8 buffer_usb_in[64];
  7.  
  8. void datos_endpoint(int8 ep)
  9. {
  10.   int8 i,bytes_recibidos,*ptr;
  11.   bytes_recibidos = *(BD1OCNT + ep*8);      
  12.   ptr = 256*(*(BD1OADRH + 8*ep)) + (*(BD1OADRL + ep*8));
  13.   for(i = 0; i < bytes_recibidos; i++)
  14.     {
  15.     buffer_usb_in[i] = *ptr;
  16.     ptr++;
  17.     }
  18.   usb_flush_out(ep, USB_DTS_TOGGLE);  
  19. }

- bytes_recibidos contiene el número de bytes recibidos en el endpoint en cuestión. En tu caso almacena el valor 64.
- ptr se inicializa con la direccion de memoria a partir de la cual se almacenan los datos recibidos por el endpoint, y después
lo usamos para ir leyendo byte a byte y copiándolo en el array buffer_usb_in[].
- La llamada a usb_flush_out(ep, USB_DTS_TOGGLE) no debe faltar para que las interrupciones puedan seguir funcionando.
Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: rafaelnotty en 31 de Julio de 2010, 00:47:02
gracias, es ud muy atento;

aprobechando su generosidad y atencion le tengo una preguntik bn puntual;

¿porq las interrupciones por usb son desabilitadas en algun momento de recibir datos? o a lo largo de toda la libreria pic18_usb.h?
debido a mi problema (qno se generan nuevas interrupciones luego de reibir los 1eros 64 bytes)
¿seria valido editar todas las funciones y hacer un llamado a la funcion usb_flush_out(ep, USB_DTS_TOGGLE) en todas las funciones de las librerias??
esto para que no se pierda la continuidad de los datos por interrupcion... colaborame con esa duda y con este problemillo

gracias
Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: Modulay en 31 de Julio de 2010, 06:37:58
Cuando se atiende una interrupcion se debe evitar que vuelva a saltar la misma interrupción antes de terminar de procesar la anterior.
Esa que te puse es un ejemplo de rutina de interrupción que puedes usar como punto de partida para construir la tuya propia (llevando a cabo todos los cambios que explico en el primer post del hilo), y como puedes ver, al final lleva la llamada a usb_flush_out(ep, USB_DTS_TOGGLE), la cual vuelve a habilitar el endpoint para seguir funcionando. Lo que no recuerdo es si la interrupción es habilitada por dicha llamada o se hace previamente en otro sitio, pero habilitarse, se habilita.
Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: rafaelnotty en 31 de Julio de 2010, 15:57:47
gracias, exelente, voy a probar... y bueno otra preguntika... pueden coexistir el i2c y el usb?? alguna recomendacion en especial?
gracias...
Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: rafaelnotty en 01 de Agosto de 2010, 00:59:29
bno! como siempre agradecido x la colaboracion pero;
ya hize todo lo de pasar los codigos de las rutinas de pic18_usb.h al codigo principal del compilador
ya he probado tambn el codigo de datos_endpoint(en); lo anexe

pero persisten los problemas, luego de los primeros bytes el programa no vuelve a generar interrupciones
y usando otra vez la tactica de detach(); y el attach(); conectando y desconectando hardware logro seguir recibiendo datos pero etos no estan siendo logicos, los datos no son los q son o los que deberian ser, he hecho un par de pruebas como xej mostrar todas las posiciones de buffer_in[1,2,3,4,...] y no salen datos coherentes a lo q estoy enviando (si xej mando puros 1s salen puros datos raros)... bueno, estoy por rendirme en esto de comprnder a profundidad el usb

  bytes_recibidos = *(BD1OCNT + ep*8);                                      // el + ep*8 es para saltar el ep0 de control?
  ptr = 256*(*(BD1OADRH + 8*ep)) + (*(BD1OADRL + ep*8));      //igual aka?
     
estos mensajes warning me parecen raros pero no doi para resolverlos; con la operacion que modulay sugirio al principio del foro desaparecieron 2 de estos warning pero todavia salen 2 mas...

>>> Warning 203 "C:\Program files\PICC\drivers\pic18_usb.h"Line 523(1,1); Condition always TRUE                           // esto es una gran duda para mi
>>> Warning 216 "usb.c"Line 291(0,1): Interrupts disabled during call to prevent re-entrancy: (usb_token_reset)         //si puede echeme una mano(explicacion)

¿q hago? si puedes ayudame o aconsejame abandonar la comprension exaustiva del usb como ud la tiene...
Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: Modulay en 04 de Agosto de 2010, 16:38:53
Bueno, mi comprensión de este tema tampoco es tan exahustiva, aparte que tampoco conozco en profundidad la librería usb de ccs (para lo cual se hace necesario conocer el protocolo usb bastante bien).
En cuanto al i2c, no veo motivo por el cual no pueda coexistir con el usb.
Respecto a los warnings, la verdad q no recuerdo si a mí también me salían...si fué así, no creo que los tuviera muy en cuenta.


  bytes_recibidos = *(BD1OCNT + ep*8);                                      // el + ep*8 es para saltar el ep0 de control?
  ptr = 256*(*(BD1OADRH + 8*ep)) + (*(BD1OADRL + ep*8));      //igual aka?
     

Efectivamente. BD1OCNT, BD1OADRH y BD1OADRL se usan como direcciones base y se corresponden con el buffer y descriptor de buffer del endpoint cero.

La verdad es que no se que más puedo decirte.
Quizá, si lo que quieres es empezar a manejar el usb, lo mejor sea que empieces por algo más sencillo.
Pásate por este hilo (http://www.todopic.com.ar/foros/index.php?topic=2260.0) y prueba con el proyecto de J1M.
Una vez lo tengas funcionando bien, puedes pasar a controlar la interrupción.

Y por favor, no me llames de usted :oops:
Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: RICHI777 en 04 de Agosto de 2010, 18:05:40
Hola, no uso PIC ni CCS asi que mucho no te voy a poder ayudar, lo que si puedo es explicarte el primer warning, cuando el compilador se refiere a "condicion siempre es verdadera" se refiere a casos como este:

Código: C
  1. if ( 1 )
  2. {
  3.   printf( "Es 1" );
  4. }
  5. else
  6. {
  7.   printf( "Es 0 " );
  8. }

1 nunca puede ser otra cosa, con la cual la expresion siempre es verdadera

Creo que en el foro de CCS tratan este tema, fijate

http://www.ccsinfo.com/forum/viewtopic.php?p=118968

Saludos !

Título: Re: USB en CCS: Detectando y gestionando la interrupción
Publicado por: rafaelnotty en 08 de Agosto de 2010, 14:57:32
gracias, llevo el proyecto un poco mas adelantado. he tratado de ir solucionando mis problemas de una manera u otra y a la vez ir entendiendo cositas profundas de funcionamiento de los protocolos y de ccs... gracias por todo el apoyo... ahorita mismo stoy cuadrando el i2c bn para controlar desde la pc toda una red de uc´s.

gracias a ti richi tambn por la colaboracion. era cuestion del protocolo usb y la libreria pic18_usb.h