Titel: Wieder mal USB
Beitrag von: BL1 am Juni 23, 2010, 14:04:34
Moin, ich kämpfe mit USB. Ich versuche das Bootloader-Beispiel von Sprut (http://sprut.de/electronic/pic/8bit/18f/programm/usbbootloader/usbboot.htm#1) auf einer eigenen Platine zum laufen zu bringen. Die Platine "lebt" inzwischen. Der Pic taktet ordentlich und ohne die USB-Geschichte macht er zu Testzwecken auch eine LED an und aus. Den Schalter, wonach der Pic beim Booten erst guckt, ob er per Bootloader neue Daten kriegt, habe ich zunächst auskommentiert. Also enabelt er als erstes die USB-Schnittstelle. Dadurch schaltet er auch das "D+"-Pin auf 3,3 V(gemessen 2,89V). Nun hatte ich gedacht, dass der Host diese 3,3V sieht und damit weiß, dass da was dranhängen muß. Anschließend müßte er doch diese USB-Schnittstelle ansprechen. Oder ist diese Denke falsch? Jedenfalls merkt Windows auch nichts von einem neuen Gerät. Es müßte ja eigentlich nach einem Treiber fragen. Darauf habe ich mich mit dem Debug-Mode per ICD2 dahin getastet, wo er die 3,3V auf D+ legt. Indem er im UCON USBEN auf 1 setzt. Anschließend wartet er, dass das Bit SE0 gelöscht wird. An der Stelle schwimme ich. Normalerweise müßte doch der Host/Hub nachdem er die 3,3V erkannt hat, beide D-Leitungen auf Null ziehen und das der Pic mit dem SE0-Bit erkennen. Oder? Der Pic schaltet auch das SE0-Bit von 1 auf 0, auf dem Oszi sieht man das aber nicht. Müßte es also nun so sein oder anders oder steht das irgendwo so, dass es auch die älteren Symester verstehen? void USBCheckBusStatus(void) { UCON = 0b00001000; // Enable USBEN only /* * After enabling the USB module, it takes some time for the voltage * on the D+ or D- line to rise high enough to get out of the SE0 condition. * The USB Reset interrupt should not be unmasked until the SE0 condition is * cleared. This helps preventing the firmware from misinterpreting this * unique event as a USB bus reset from the USB host. */ while(UCONbits.SE0); // Blocking loop UIR = 0; // Clear all USB interrupts UIE = 0b00010001; // Unmask RESET & IDLE interrupts only usb_device_state = POWERED_STATE; }//end USBCheckBusStatus
BL
Titel: Re:Wieder mal USB
Beitrag von: Stampede am Juni 24, 2010, 10:14:52
Hi BL,
zeig mal die komplette main.c mit allen deinen Änderungen her. Die USB Beispiele von MC laufen eigentlich immer problemlos, daher wundert es mich dass der da angeblich hängen bleibt. Ist der PIC auch richtig knfiguriert (PLL, WDT, etc.) ?
Grüße Stefan
Titel: Re:Wieder mal USB
Beitrag von: BL1 am Juni 27, 2010, 09:24:12
zeig mal die komplette main.c mit allen deinen Änderungen her. Kein Problem: /** I N C L U D E S **********************************************************/ #include <p18cxxx.h> #include <p18f4455.h> #include "system\typedefs.h" // Required #include "system\usb\usb.h" // Required #include "io_cfg.h" // Required
#include "system\usb\usb_compile_time_validation.h" // Optional
/** C O N F I G U R A T I O N ************************************************/
#if defined(__18F4550)||defined(__18F4455)|| \ defined(__18F2550)||defined(__18F2455)|| \ defined(__18F4553)||defined(__18F4458)|| \ defined(__18F2553)||defined(__18F2458)
// Note: Some of the below configuration bits are commented out // to prevent build errors with some of the above listed devices. // For example, on the PIC18F4458 CP3, WRT3, and EBTR3 don't exist.
#pragma config PLLDIV = 2 //8MHz (5:20 MHz input) #pragma config CPUDIV = OSC1_PLL2 #pragma config USBDIV = 2 // Clock source from 96MHz PLL/2 #pragma config FOSC = HSPLL_HS //#pragma config FCMEN = OFF #pragma config IESO = OFF #pragma config PWRT = ON #pragma config BOR = OFF //#pragma config BORV = 3 #pragma config VREGEN = ON #pragma config WDT = OFF #pragma config WDTPS = 32768 #pragma config MCLRE = ON #pragma config LPT1OSC = OFF #pragma config PBADEN = OFF #pragma config CCP2MX = OFF #pragma config STVREN = ON #pragma config LVP = OFF //#pragma config ICPRT = OFF // Dedicated In-Circuit Debug/Programming #pragma config XINST = OFF // Extended Instruction Set #pragma config CP0 = OFF #pragma config CP1 = OFF #pragma config CP2 = OFF //#pragma config CP3 = OFF #pragma config CPB = OFF #pragma config CPD = OFF #pragma config WRT0 = OFF #pragma config WRT1 = OFF #pragma config WRT2 = OFF //#pragma config WRT3 = OFF #pragma config WRTB = OFF // Boot Block Write Protection #pragma config WRTC = OFF #pragma config WRTD = OFF #pragma config EBTR0 = OFF #pragma config EBTR1 = OFF #pragma config EBTR2 = OFF //#pragma config EBTR3 = OFF #pragma config EBTRB = OFF
#endif
/** V A R I A B L E S ********************************************************/ #pragma udata
/** P R I V A T E P R O T O T Y P E S ***************************************/
/** V E C T O R R E M A P P I N G *******************************************/
#pragma code _HIGH_INTERRUPT_VECTOR = 0x000008 void _high_ISR (void) { _asm goto RM_HIGH_INTERRUPT_VECTOR _endasm }
#pragma code _LOW_INTERRUPT_VECTOR = 0x000018 void _low_ISR (void) { _asm goto RM_LOW_INTERRUPT_VECTOR _endasm }
void mein_main(void);
#pragma code
/** D E C L A R A T I O N S **************************************************/ #pragma code /****************************************************************************** * Function: void main(void) * * PreCondition: None * * Input: None * * Output: None * * Side Effects: None * * Overview: Main program entry point. * * Note: None *****************************************************************************/ void main(void) { byte temp; temp = ADCON1; ADCON1 |= 0x0F; //TRISBbits.TRISB4 = 1; // Reset value is already '1' //Check Bootload Mode Entry Condition // if(PORTBbits.RB4 == 1) // If not pressed, User Mode
// if (PORTEbits.RE3 == 1) // kein jumper { // _asm goto RM_RESET_VECTOR _endasm // }//end if //Bootload Mode mInitAllLEDs(); mInitializeUSBDriver(); // See usbdrv.h USBCheckBusStatus(); // Modified to always enable USB module while(1) { USBDriverService(); // See usbdrv.c BootService(); // See boot.c }//end while }//end main
#pragma code user = RM_RESET_VECTOR
/*****************************************************************************/ /*****************************************************************************/ /*****************************************************************************/
void mein_main(void) { while(1) { PORTAbits.RA4 = 1; PORTAbits.RA4 = 0; }//end while } /** EOF main.c ***************************************************************/
Inzwischen ist die Geschichte so weit gediehen, als dass ich einmal im Gerätemanager ein neues unbekanntes Gerät gesehen hatte. Den Treiber dafür einzubinden habe ich zwar nichzt gleich hingekriegt, aber das war mir im Moment noch nicht wichtig. Das Problem scheint zumindest auch am Windows7 zu liegen. Der Rechner mußte erst mit angestöpseltem Pic hochlaufen, um zu erkennen, das da was dran war. Um gekehrt blieb das nicht erkannte Gerät sowohl im Gerätemanager als auch im usbview stehen, als es wieder abgestöpselt war. Wieder erst nach Neustart war es weg. Ich habe es zunächst nicht weiter verfolgt, da zunächst noch einige Wissenslücken schließen wollte, wie auch C18 für mich neu ist(bisher CC8e). Dabei bin ich auf ein Buch gestoßen, dass einen anderen Ansatz verfolgt, nämlich USB via Interrupt zu steuern. Das ist mir sympathischer, weil die Baugruppe später Logging-Funktionen erfüllen soll. Ich komme später drauf zurück. BL
Titel: Re:Wieder mal USB
Beitrag von: BL1 am Juli 06, 2010, 11:18:09
Hallo,
ich bin ein Stück weiter - oder auch nicht.
Ich habe also die Sache nochmal neu angefangen, mit einer anderen Softwarevorlage. Das ist mir übersichtlicher und wegen der Interrups sympathischer. Dazu habe ich jetzt auch einen anderen Host-Rechner mit XP, statt Win7.
Nur, ich bleibe an der gleichen Stelle stehen. Der D+-Pin zieht hoch, wenn USBEN gesetzt wird, SE0 geht mit hoch und im nächsten Takt wieder runter, wenn die D+-Leitung eingeschwungen ist und dann passiert nichts mehr.
Muß an der Stelle der Host nicht einen USB-Reset auslösen, auch ohne, dass er einen Treiber für das Device hat? Wie sollte er sonst herausfinden, was es für ein Gerät ist?
BL
Titel: Re:Wieder mal USB
Beitrag von: BL1 am Juli 07, 2010, 08:39:25
Manchmal stellt man fest, dass man auch im "mittleren" Alter, selbst nach vielen, vielen und sogar wirklich glücklichen Ehejahren nachts noch Erfolgserlebnisse haben kann. ;)
So jedenfalls kam mir des Nachts die Erleuchtung, doch mal das USB-Kabel zu prüfen. Und siehe da....
Ich möchte hier nicht schildern, welche Tobsuchtsanfälle ich vorher durchlebt, nachdem ich alles andere, mir Erdenkliche ausprobiert hatte. Danach auf das Kabel zu kommen, war jetzt nichts die wirklich große geistige Glanztat. (anderer Host, anderes Betriebssytem, andere Device-Software, zum Schluß andere Device-HW) Aber schön ist es nun doch, etwas gefunden zu haben.
BL
Titel: Re:Wieder mal USB
Beitrag von: Edson am Juli 07, 2010, 13:20:55
Manchmal stellt man fest, dass man auch im "mittleren" Alter, selbst nach vielen, vielen und sogar wirklich glücklichen Ehejahren nachts noch Erfolgserlebnisse haben kann. ;)
Freut mich das zu hören, man selbst wird ja auch nicht jünger... ;) Danach auf das Kabel zu kommen, war jetzt nichts die wirklich große geistige Glanztat. (anderer Host, anderes Betriebssytem, andere Device-Software, zum Schluß andere Device-HW) Aber schön ist es nun doch, etwas gefunden zu haben. Solche Vorgänge haben glücklicherweise nichts mit dem Alter zu tun, es besteht also Hoffnung. ;) Viele Grüße, Edson
Titel: Re:Wieder mal USB
Beitrag von: BL1 am Juli 29, 2010, 08:01:15
Hallo,
ich hänge wieder mit dem USB.
Folgender Stand: Das Device läuft ordentlich hoch, schaltet den USB-D+ auf 3,3V, der PC löst einen USB-Reset aus, das Device geht in den Inzerrupt. Dann müßte doch eigentlich vom PC aus ein Request angestoßen werden, indem das Device seine Adresse kriegt? Das macht der komischer Weise nicht, sondern immer neue Resets.
Muß da vielleicht das Device auf den Bus-Reset irgendwas antworten?
BL
Titel: Re:Wieder mal USB
Beitrag von: Stampede am Juli 29, 2010, 15:21:25
Hi, noch mal die Nachfrage: Führst du die "mein_main" irgendwo aus? Ich verstehe ehrlich gesagt nicht, warum der Code nicht laufen sollte. Durch die auskommentieren IF Anweisungen springst du immer in den Bootloader Code, der eigentlich alles von alleine tut, von Init über Enumeration bis zum Schreiben in den Flash. Und der funktioniert auch unter Windows 7, ich habe meinen Code unter XP und Win7 immer erfolgreich zum laufen gebracht. Grundsätzlich verwendet der Bootloader keine Interrupts, ich sehe auch keinen Vorteil warum man diese nutzen sollte. Ich glaube, du hast bei dem Lösungsansatz einen Denkfehler: Du versuchst, Applikation und Bootloader in eine Applikation zu gießen. Davon rate ich dir aber ab, weil das die Sache nur unnötiger Weise verkompliziert. Ich schlage vor, dass du in einem Projekt den reinen USB BL programmierst, dort wird auch abgefragt, ob der BL oder die Applikation gestartet wird. Sinnvollerweise aktivierst du gleich die BL Code Protection, damit ist sichergestellt, dass der Bootloader nicht zerstört werden kann. Für die eigentliche Applikation erstellst du wiederum ein eigenes Projekt, das alle gewünschten Funktionen zur Verfügung stellt. Dabei musst du nur die Interruptvektoren und die Startadresse auf die im Bootloader festgelegten Adressem um biegen. Hier spricht auch nichts gegen die Benutzung von einer interruptbasierten Abarbeitung der USB Anfragen. Bei mir sieht der BL so aus (Auszug): void main(void) { [...] //Check Bootload Mode Entry Condition if(PORTAbits.RA1 == 1 && boot != 0xA9 && boot != 0xff) // If not pressed, value set by setup or { // if program space is emtpy (eeprom is 0xff) _asm goto RM_RESET_VECTOR _endasm }//end if
[..]
//Bootload Mode mInitAllLEDs(); mLED_1_Off(); mLED_2_On(); led_count = 0; //Initialize blink rate counter mInitializeUSBDriver(); // See usbdrv.h USBCheckBusStatus(); // Modified to always enable USB module while(1) { USBDriverService(); // See usbdrv.c BootService(); // See boot.c }//end while }//end main
Grüße Stefan
Titel: Re:Wieder mal USB
Beitrag von: BL1 am Juli 29, 2010, 16:53:39
Hallo, da gibt es ein Mißverständnis. Ich nehme nicht mehr das Sprut-/Microchip-Projekt zur Grundlage, sondern eines aus einem Buch "USB in der Meßtechnik" von Henry Bruhns. Der wiederum hat sein Projekt in Assembler geschrieben und ich daraus meinen C-Code gemacht. Sieht ungefähr so aus: #pragma config PLLDIV = 2 //8MHz (5:20 MHz input) #pragma config CPUDIV = OSC1_PLL2 #pragma config USBDIV = 2 // Clock source from 96MHz PLL/2 #pragma config FOSC = HSPLL_HS //#pragma config FCMEN = OFF #pragma config IESO = OFF #pragma config PWRT = ON #pragma config BOR = OFF //#pragma config BORV = 3 #pragma config VREGEN = ON #pragma config WDT = OFF #pragma config WDTPS = 32768 #pragma config MCLRE = ON #pragma config LPT1OSC = OFF #pragma config PBADEN = OFF #pragma config CCP2MX = OFF #pragma config STVREN = ON #pragma config LVP = OFF //#pragma config ICPRT = OFF // Dedicated In-Circuit Debug/Programming #pragma config XINST = OFF // Extended Instruction Set #pragma config CP0 = OFF #pragma config CP1 = OFF #pragma config CP2 = OFF //#pragma config CP3 = OFF #pragma config CPB = OFF #pragma config CPD = OFF #pragma config WRT0 = OFF #pragma config WRT1 = OFF #pragma config WRT2 = OFF //#pragma config WRT3 = OFF #pragma config WRTB = OFF // Boot Block Write Protection #pragma config WRTC = OFF #pragma config WRTD = OFF #pragma config EBTR0 = OFF #pragma config EBTR1 = OFF #pragma config EBTR2 = OFF //#pragma config EBTR3 = OFF #pragma config EBTRB = OFF
... //---------------------------------------------------------------------------- // High priority interrupt vector
#pragma code InterruptVectorHigh = 0x08 void InterruptVectorHigh (void) { _asm goto InterruptHandlerHigh //jump to interrupt routine _endasm }
//---------------------------------------------------------------------------- // Low priority interrupt vector
#pragma code InterruptVectorLowh = 0x18 void InterruptVectorLow (void) { _asm goto InterruptHandlerLow //jump to interrupt routine _endasm }
//--------------------------------------------------------------------------------- #pragma code boot_sector = 0x0020 void main(void) { // OSCCON = 0b01100010; regsetup(); DEVICE_init(); USB_init(); USB_reset(); PIR2bits.USBIF = 0; //reset any USB interrupts pending IPR2bits.USBIP = 1; //USB is a high priority interrupt source RCONbits.IPEN = 1; //enable interrupt priority levels INTCONbits.PEIE = 1; //enable peripheral interrupt sources PIE2bits.USBIE = 1; //enable USB interrupt UIR = 0; INTCONbits.GIE = 1; //global interrupt enable bit
USBTMCindicator_pulse();//fliegt noch raus
Hauptschleife:
while (1) { PORTAbits.RA4 = !PORTAbits.RA4; }
} //-----------------------------Register einstellen--------------------------------- void regsetup(void) { InitAdcons(); //Macro in iocfg.h InitPORTA(); //Macro in iocfg.h InitPORTB(); //Macro in iocfg.h InitPORTC(); //Macro in iocfg.h InitPORTD(); //Macro in iocfg.h InitPORTE(); //Macro in iocfg.h EECON1 = 0; EECON2 = 0; TABLAT = 0; TBLPTRL = 0; TBLPTRH = 0; TBLPTRU = 0; IPR1 = 0; //nur USB hohe Int.Priority IPR2 = 0x20; //nur USB hohe Int.Priority T0CON = 0; T1CON = 0; T2CON = 0; T3CON = 0; TMR0L = 0; TMR0H = 0; TMR1L = 0; TMR1H = 0; TMR2 = 0; TMR3L = 0; TMR3H= 0;
PIR1 = 0; //Alle Flags aus PIR2 = 0; //Alle Flags aus // PIR3 = 0; //Alle Flags aus RCON = 0b00000000; //IP verbieten INTCON = 0b00000000; //nix erlauben INTCON2 = 0b10000000; // INTCON3 = 0b00000000; //nix erlauben PIE1 = 0b00000000; //CCPIE an PIE2 = 0; // hilf = 0; // PIE3 = 0; // } //---------------------------------------------------------------------------- // High priority interrupt routine
#pragma code #pragma interrupt InterruptHandlerHigh
void InterruptHandlerHigh (void) { //HighInt //; save working registers retteArbeitsregisterHighInt() //Macro in inthandvo1.h
LATCbits.LATC0 = 1; if (hilf==4) { Nop(); Nop(); } TestCounter[hilf] = UIR; hilf++;
HighIntuerrif_test: if (UIRbits.UERRIF) goto HighIntUerrif; HighIntStallif_test: if (UIRbits.STALLIF) goto HighIntStall; HighIntUrstif_test: if (UIRbits.URSTIF) goto HighIntUSBreset; HighIntTrnif_test: if (UIRbits.TRNIF) goto HighIntTrnif; HighIntActvif_test: if (UIRbits.ACTVIF) goto HighIntActvif;
HighInt2:
//; insert here: any other high priority interrupt queries
HighIntEnd: PIR2bits.USBIF = 0; goto fast_end; //; this is an USB reset interrupt HighIntUSBreset: USB_reset(); HighIntSE0Test: while (UCONbits.SE0); UIRbits.URSTIF = 0; goto fast_end; //; this is an USB transaction complete interrupt HighIntTrnif: USBtranscompleteInterrupt(); UIRbits.TRNIF = 0; goto fast_end; //; this is an USB stall interrupt HighIntStall: UIRbits.STALLIF = 0; USBStallInterrupt(); goto fast_end; //; this is an USB resume interrupt HighIntActvif: USBresumeInterrupt(); goto fast_end; //; this is an USB error interrupt HighIntUerrif: USBerrorInterrupt(); goto fast_end;
//; insert here: all other fast interrupt service routine calls
//; this is all fast ISR's end
fast_end: //; restore working registers UIR = 0; PIR2bits.USBIF = 0; LATCbits.LATC0 = 0; holeArbeitsregisterHighInt() //Macro in inthandvo1.h _asm RETFIE 1 _endasm //;never use 'retfie fast' because of early silicon errors
}
//; Low priority interrupt routine #pragma interrupt InterruptHandlerLow
void InterruptHandlerLow() { retteArbeitsregisterLowInt() //Macro in inthandvo1.h /*** low priority interrupt code goes here ***/ //; execute operation pending function
holeArbeitsregisterLowInt() // retfie }
void DEVICE_init(void) { REN = 0; RLstate = 0; //LOCS STB = 0; // ESR.byte = 0; // ESE = 0; // BULKOUT_PROGRESS = 0; //no transfer is in progress BULKOUT_CONTENT = 0; //bulk-OUT is empty BULKOUT_RXD[0] = 0; //no data transmitted BULKOUT_RXD[1] = 0; // BULKOUT_RXD[2] = 0; // BULKOUT_RXD[3] = 0; // BULKIN_PROGRESS = 0; //no transfer is in progress BULKIN_CONTENT = 0; //bulk-IN is empty BULKIN_TXD[0] = 0; //no data transmitted BULKIN_TXD[1] = 0; // BULKIN_TXD[2] = 0; // BULKIN_TXD[3] = 0; // OperCond[0] = 0; //status reporting acc. SCPI Syntax & Style chapter 9 OperCond[1] = 0; // OperEven[0] = 0; // OperEven[1] = 0; // OperEnab[0] = 0; // OperEnab[1] = 0; // QuesCond[0] = 0; // QuesCond[1] = 0; // QuesEven[0] = 0; // QuesEven[1] = 0; // QuesEnab[0] = 0; // QuesEnab[1] = 0; // ErrorCount = 0; //no errors in the Error/Event Queue ESR.PON = 1; //ESR noopFLAG = 0xFF; // OPCstate.OCIS = 1; OPCstate.byte = 0xFF; // OQIS = 0xFF; OPCqstate.byte = 0xFF; return; }
void USB_init(void) { UCON = 0; //;clear USB Control Register UADDR = 0; //USB address 0 (done automatically if USB reset occurs) SetAddress = 0; USBAddress = 0; bConfigurationValue = 0; //device is not configured //; CPU gets ownership of the whole USB RAM and clears the buffer descriptors // FSR0L = 0; // FSR0H = 0x04; DescriptorPointer = 0; EPx.EParray[0] = 0x00; do { DescriptorPointer++; EPx.EParray[DescriptorPointer] = 0x00; }while (DescriptorPointer<0xFF);
UCFG = 0b00010100;
UEP0 = 0; UEP1 = 0; UEP2 = 0; UEP3 = 0; UEP4 = 0; UEP5 = 0; UEP6 = 0; UEP7 = 0; UEP8 = 0; UEP9 = 0; UEP10 = 0; UEP11 = 0; UEP12 = 0; UEP13 = 0; UEP14 = 0; UEP15 = 0;
//; Initialization of the USB interrupt funnel (reference: DS39632C Section 17.5) clearACTVIF(); UIR = 0; UIE = 0; UEIR = 0; UEIE = 0; UIRbits.URSTIF = 0; //clear interrupt status flag UIEbits.URSTIE = 1; //enable reset interrupt UIEbits.STALLIE = 1; //enable stall interrupt UIEbits.TRNIE = 1; //enable transaction complete interrupt
//; enable USB interface UCONbits.USBEN = 1;
while (UCONbits.SE0);
return; } / void clearACTVIF(void) { UCONbits.SUSPND = 0; while (UIRbits.ACTVIF) { UIRbits.ACTVIF = 0; } return; }
void USB_unconfig(void) { bConfigurationValue = 0; //this will be read back with "GET_CON- //; FIGURATION USBindicatorUNCONFIG(); return; }
void USBindicatorUNCONFIG(void)
{ return; }
void USB_reset(void) { UADDR = 0; //USB address 0 (done automatically if USB reset occurs) bConfigurationValue = 0; //device is not configured UIR = 0; //clear all pending USB interrupts UEIR = 0; //clear all USB error interrupts //;disable all endpoints UEP0 = 0; UEP1 = 0; UEP2 = 0; UEP3 = 0; UEP4 = 0; UEP5 = 0; UEP6 = 0; UEP7 = 0; UEP8 = 0; UEP9 = 0; UEP10 = 0; UEP11 = 0; UEP12 = 0; UEP13 = 0; UEP14 = 0; UEP15 = 0; //;unconfigure device USB_unconfig(); //;configure endpoint 0 config_EP0(); UCONbits.PKTDIS = 0; //clear packet transfer disable //;flush any pending transactions while (UIRbits.TRNIF); return; }
void config_EP0(void) { //; Control OUT Buffer Descriptor //; can receive 64 bytes //; buffer starts at adress 0x0480 union { struct { unsigned char low8; unsigned char high8; }; unsigned int gesamt; }adr;
//Die Adresse des Output-Buffers in den Endpunkt0 schreiben adr.gesamt = (unsigned short long) USB_CONTROL_OUT; EPx.BD0ADRL = adr.low8; EPx.BD0ADRH = adr.high8;
//Die Adresse des Input-Buffers in den Endpunkt1 schreiben adr.gesamt = (unsigned short long) USB_CONTROL_IN; EPx.BD1ADRL = adr.low8; EPx.BD1ADRH = adr.high8;
EPx.BD0CNT = 64; //Buffer-Breite 64Bit EPx.BD0STAT = 0b10000000; //turn ownership to SIE
//; configure UEP0 Register UEP0 = 0;
return; }
void USBTMCindicator_pulse(void) {
// timerIndicator = 100; //count down in 0.5s // IndicateINDICATORon(); return; }
void BulkTransferIndicator(void) {
if (timerBulk==0) return; timerBulk = 30; return; }
void USBresumeInterrupt(void) { clearACTVIF(); //; set oscillator to primary clock source OSCCONbits.SCS1 = 0; OSCCONbits.SCS0 = 0; OSCCONbits.IDLEN = 0; UIEbits.ACTVIE = 0; //;disable bus activity interrupt UIRbits.IDLEIF = 0; return; }
void USBtranscompleteInterrupt(void) { //; read USB status register to localize the endpoint TINKER = 0x78 & USTAT; switch (TINKER) { case 0x00: // goto transcmpl_0; //transaction complete in physical endpoint 0 break;
case 0x08: // goto transcmpl_1; //transaction complete in physical endpoint 1 break;
case 0x10: // goto transcmpl_2; //transaction complete in physical endpoint 2 break;
case 0x18: // goto transtest_over; //transaction complete in physical endpoint 3 break; }
transtest_over: return; }
void USBStallInterrupt(void) { if (UEP0bits.EPSTALL==0) return;
StallTrap: //; return ownership of control OUT endpoint to SIE EPx.BD0STAT = 0x08; //10000000 //; return ownership of control IN endpoint to CPU EPx.BD1STAT = 0; //; reset EPSTALL-bit UEP0bits.EPSTALL = 0; return; }
void USBerrorInterrupt() { UEIR = 0; return; }
void transtest_over_ctl_out(void) { UCONbits.PKTDIS = 0; //clear packet transfer disable //; Control OUT Buffer Descriptor //; can receive 64 bytes //; buffer starts at adress 0x0500 EPx.BD0CNT = 64; EPx.BD0STAT = 0x80; //turn ownership to SIE return; }
Ist natürlich noch unfertig. Ziel ist zunächst ausschließlich, die Schnittstelle zum Leben zu bringen. Bootlader, Meßroutinen usw. kommen erst lande danach. Nahziel ist im Moment, nach dem ersten Bus Reset den ersten Request zu empfangen. In der High-Priotity-Interruptroutine stehen einige Befehlszeilen ganz am linken Rand. Das sind Codeschnipsel, mit denen ich beispielsweise einen Ausgang zu Triggerzwecken schalte und die UIR-Werte der einzelnen Interupts mitschreibe, um sie später via ICD2 auslesen zu können. Die Situation ist nun die, dass der Bus seinen ersten Reset macht und der Controller daher in den richtigen Interrupt geht. Dann aber macht der Bus weitere Resets, statt den SET_ADDRESS-Request zu bringen. Folglich müßte irgendwas doch dem Bus mitteilen, dass weitere Resets nicht notwendig sind. Der Controller geht bei jedem Reset in den Interrupt und zeigt dann aber eine 0x41 im UIR, also das Reset- und das Start-of-frame-Flag. Das eine(SOFIF) kann ich mir erklären. Das wäre ja das, was ich will. Das andere eigentlich auch. Beides zusammen aber nicht. Da weiß ich im Moment noch nicht weiter. BL
Titel: Re:Wieder mal USB
Beitrag von: BL1 am Juli 30, 2010, 08:09:11
Inzwischen habe ich den Oszi etwas gequält.
Der PC sendet nach dem Reset eben doch Daten. Ist nur schwer, es mit den Reset-Impulsen zusammen auf einem Billig-Oszi darzustellen. Daher erkennt der PIC folgerichtig den SOF(K-Zustand). Im Bruhns sind Buch und Software nun darauf getrimmt, dass der Pic keinen SOF-Interrupt bringt. Der würde sich erst melden, wenn die Transaktion abgeschlossen ist(Transaction-Complete-Interrupt). Nun kommt mein Pic nicht bis dahin und an der Stelle weiß ich noch nicht, warum. Das zweite ist, wie erkennt denn der PC, dass der Pic nicht reagiert?
BL
Titel: Re:Wieder mal USB
Beitrag von: Stampede am Juli 31, 2010, 12:24:59
Hi BL, da haben wir wirklich aneinander vorbei geredet, ich dachte du nutzt noch das Microchip Beispiel. Ich habe mal auf Basis eines Assembler Codes aus dem MC Forum eine Firmware geschrieben, bei der ich noch die BULK Transfers für MSD ergänzt habe. Die Enumeration war schon implementiert, ich habe mich darum also nicht mehr kümmern müssen, daher kenne ich mit damit auch nicht so detailiert aus. Was ich allerdings nicht verstehe, ist warum du den USB neu schreiben möchtest. Der MC Code funktioniert super, is USB zertifiziert und kostenlos verfügbar. Dein Vorhaben hat eher akademischen Charakter... :) Fall du Literatur benötigst, so kann ich dir die beiden Bücher von Jan Axelson empfehlen: "USB Complete" und "USB Mass Storage". Bei Interesse PM an mich. Das zweite ist, wie erkennt denn der PC, dass der Pic nicht reagiert? Simpler Timeout. Daher müssen die USB Routinen so groß alle 1ms ausgeführt werden, sonst wird hostseitig ein Timeout erkannt. Noch etwas: Du programmierst in C und nutzt "goto" Befehle! Das ist ganz schlechter Stil. Nimm anstatt dieser if und goto Kombinationen lieber ein switch / case Anweisungen. Grüße Stefan
Titel: Re:Wieder mal USB
Beitrag von: BL1 am August 01, 2010, 16:48:00
Hallo Stefan,
es mag ja im Prinzip so aussehen, dass ich das Rad neu erfinden wollte, nur ganz so ist es auch wieder nicht. So wie Du eine Vorlage aus dem MC-Forum(?) genommen hast, hatte ich es auf diese aus dem Bruhns abgesehen. Zudem habe ich Erfahrungen mit Software-Vorlage dahingehend gemacht, dass ich es sowieso nicht hinkriege, bevor ich nicht jede Zeile einigermaßen versteh. Das ist beim MC-Framework nun auch nicht eben simpel.
Mit meinem Problem hier bin ich blöderweise noch nicht weiter. Ich habe beide Varianten(meine und die Vorlage) bis zur ersten Kommunikation nach dem Reset durchgespielt. Alles wesentlichen Register sind gleich. Der PC funkt den Pic an. Die Vorlage reagiert darauf und mein Ding nicht.
Was für einen Assembler Codes aus dem MC Forum hattest Du den verwendet?
BL
Titel: Re:Wieder mal USB
Beitrag von: Stampede am August 03, 2010, 14:05:52
Hi BL, es mag ja im Prinzip so aussehen, dass ich das Rad neu erfinden wollte Ja, es scheint so :) So wie Du eine Vorlage aus dem MC-Forum(?) genommen hast, hatte ich es auf diese aus dem Bruhns abgesehen. Zudem habe ich Erfahrungen mit Software-Vorlage dahingehend gemacht, dass ich es sowieso nicht hinkriege, bevor ich nicht jede Zeile einigermaßen versteh. Das ist beim MC-Framework nun auch nicht eben simpel.
Im Nachhinein war es blödsinnig, alles mit Assembler neu zu schreiben, und bei C wird es nicht anders sein. Klar, man lernt viel über USB, aber bis man einen halbwegs stabilen Code hat, vergehen Ewigkeiten. Daher rate ich dir, den MC Stack zu verwenden. Wenn du die Zeit, die du für die Entwicklung deiner eigenen Software brauchst, nimmst um dich in den Stack einzuarbeiten, wird das viel schneller und effektiver zum Ziel führen. Meiner Meinung nach ist das USB Framework recht gut zu bedienen. Man fügt in seine Applikation die Init des USBs rein, in die main muss dann nur noch der USB Handler der alles übernimmt. Ein paar Callback-Routinen müssen noch kopiert werden, aber das ist nicht der Rede wert. Und mit den vielen Beispielen findet man sich gut zurecht. Zugebenermaßen dachte ich am Anfang auch, die Stacks seien schwierig in der Bedienung, aber das stimmt nicht. Da findet sich schnell ein, ohne zu tief in die Materie gehen zu müssen. Was für einen Assembler Codes aus dem MC Forum hattest Du den verwendet? Der Code ist von Brad Minch, Link: http://www.microchip.com/forums/m89669.aspx Gruß Stefan
Titel: Re:Wieder mal USB
Beitrag von: BL1 am August 04, 2010, 07:57:33
Moin Stefan,
Im Prinzip will ich Dir ja nicht wiedersprechen.
Nur, ich hatte halt andere Überlegungen und die führten zur Interruptsteuerung, was ich im Framework nicht gefunden habe, aber im Bruhns. Nun hat der aber eben den Nachteil, dass er den ganzen Quatsch in Assembler gemacht hat. Nach Deinem Beitrag habe ich mir das Ganze nochmal angesehen und durch den Kopf gehen lassen. Ich bleibe beim Bruhns. Jetzt noch mal von vorne anzufangen, hieße, die ganzen bisherigen Wochen wegzuschmeißen.
Also habe ich weitergemacht. Und siehe da... Mit Geduld uns Spucke findet man doch mal was. Ich hatte in einer Unterfunkrion der USB-Reset-Routine den UEP0 falsch, bzw. beschrieben. Dadurch war das Bit EPHSHK nicht gesetzt. Das wiederum hat verhindet, dass das Device einen Handshake generiert(obwohl ich gelesen hatte, dass dies bei einem Setup-Token ohnehin gemacht wird). Ohne Handshake hat aber der PIC keinen Transaction-Complet-Interrupt generiert und der PC wiederum den USB immer wieder resetet. Dadurch ging der PIC zwar immer schön in den Interrupt, aber in den falschen.
So, dann stehen wir mal, wo es als nächstes hängt.
BL
|