Me gustaría que me echaran una mano con esto:
Quiero hacer un "helloled", es decir encender un led con un comando desde el host GNU/Linux por USB, pero todos los firmwares que he encontrado tienen algo que me lo imposibilita.
PUF: No me funciona en lo absoluto (ni siquiera el bootloader) (No quiero un bootloader por ahora)
Enzman FW: con el FirmWare precompilado el dispositivo se enumera correctamente, pero todo el código esta echo y se puede compilar con SDCC en windows (no logro compilarlo con SDCC en Linux)
Maccioni FW: Tanto el FW como la aplicación del host estan echos para Linux, pero el FW esta echo con MPLAB y compila con MC18 pero una versión "antigua" y no lo logro compilar tampoco (y el FW precompilado no logra enumerar el dispositivo)
Y de otro FW que he encontrado (para SDCC):
Código
/* * Firmware framework for USB I/O on PIC 18F2455 (and siblings) * Copyright (C) 2005 Alexander Enzmann * adapted to MCC18 by Alberto Maccioni on 1/8/09 * re-adapted to SDCC 2.9.0 by Enrique Olivares (EOL) on 22/06/10 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA * or see <http://www.gnu.org/licenses/> */ #include <pic18f4550.h> #include <stdio.h> #include <string.h> #include "usb.h" // Note: there are timing related problems associated with GET_FEATURE // when run at less than 48 MHz #define CLK_48MHZ 1 // Define configuration registers (fuses) #if defined(pic18f2550) || defined(pic18f2455) || defined(pic18f4550) || defined(pic18f4455) #if CLK_48MHZ code char at 0x300000 CONFIG1L = 0x24; // USBDIV=2(0x20), CPUDIV=no dividido(0x00),PLLDIV=5(0x04) 20MHz #else code char at 0x300000 CONFIG1L = 0x3c; // USB, /6 post (16MHz), /5 pre (20 MHz) #endif code char at 0x300001 CONFIG1H = 0x0e; // (FOSC xtal alta velocidad,PLL enable) (0x01),FCMEN disable(0x00), IESO disable (0x00) code char at 0x300002 CONFIG2L = 0x3d; // PWRTE disa(0x01),BODEN ena at start, disa on sleep (0x04),BORV 2.0(0x18),VREGEN ena (0x20) code char at 0x300003 CONFIG2H = 0x1e; // WDT disable(0x00), WDTPS post scaler 1:32768(0x1e) code char at 0x300004 CONFIG3L = 0xff; // Unused configuration bits code char at 0x300005 CONFIG3H = 0x00; // CCP2MX RB3(0x00), PBADEN digital(0x00), LPT1OSC disa(0x00), MCLRE disa (a Vdd)(0x00) code char at 0x300006 CONFIG4L = 0x81; // STVREN ena pila llena(0x01), LVP disa(0x00),XINST disa(0x00), DEBUG disa in-circuit(0x80) code char at 0x300007 CONFIG4H = 0xff; // Unused configuration bits code char at 0x300008 CONFIG5L = 0x0f; // Proteccion de codigo: disable CP_0(0x0), CP_1(0x02), CP_2(0x04), CP_3(0x08) code char at 0x300009 CONFIG5H = 0xc0; // CPB disable(0x40) code char at 0x30000A CONFIG6L = 0x0f; // WRT disable: WRT_0(0x01), WRT_1(0x02), WRT_2(0x04), WRT_3(0x08) code char at 0x30000B CONFIG6H = 0xe0; // WRTC disable: WRTC disa (0x20), WRTB disa (0x40) code char at 0x30000C CONFIG7L = 0x0f; // EBTR disable: EBTR_0 disa(0x01), EBTR_1 disa (0x02), EBTR_2 disa (0x04), EBTR_3 disa (0x08) code char at 0x30000D CONFIG7H = 0x40; // EBTRB disable (0x40) #endif // HID feature buffer //~ volatile unsigned char HIDFeatureBuffer[HID_FEATURE_REPORT_BYTES]; /******************************************************************************/ void high_isr(void) shadowregs interrupt 1 { if(PIR2bits.USBIF) { ProcessUSBTransactions(); UIRbits.SOFIF = 0; UIRbits.URSTIF = 0; PIR2bits.USBIF = 0; UEIR = 0; } } /******************************************************************************/ void low_isr(void) shadowregs interrupt 2 { ; ; } // Allocate buffers in RAM for storage of bytes that have either just // come in from the SIE or are waiting to go out to the SIE. volatile char txBuffer[HID_INPUT_REPORT_BYTES]; volatile char rxBuffer[64]; unsigned int timestamp=0; extern byte transferType; //Probando ADC. //Espacio temporal para el resultado de la conversion. unsigned char adch = 0x00; unsigned char adcl = 0x00; //Cachureos para probar. unsigned char adchaux = 0x00; unsigned char adclaux = 0x00; unsigned char esperaaux = 0x00; unsigned char cuentasumaaux = 0x00; //Campos de bits para banderas y semaforos. typedef struct { unsigned char flag01: 1; unsigned char flag02: 1; unsigned char flag03: 1; } banderas; //Un valor de 16 bit para el ADC. unsigned int valor = 0; //El resultado de la sumatoria de conversiones. unsigned int sumavalor = 0; //El promedio de las sumatorias. unsigned int promedio = 0; //El contador de las sumas de conversiones. unsigned char cuentasumavalor = 0; //Probando el ADC. Aqui el estado ADC GO/DONE. y otras cosas. banderas estado_adc; //Un contador para construir un tiempo de espera unsigned char espera = 0; /******************************************************************************/ // Entry point for user initialization. void UserInit(void) { LATA=0; TRISA=0b11111111; //Todas son entradas ahora, cuando pruebo el ADC. LATB=0; TRISB=0; T0CON=0x80; // Timer0 period = T*2^16:2 = 5.46ms:2 = 10.93ms (PS=2) LATC=0; TRISC=0b00000000; ADCON1 = 0b00001110; //Vref+=vss. Vref-=vdd. AN0 es entrada analoga, el resto es I/O digital. TRISAbits.TRISA0=1; ADCON0 = 0b00000000; //canal 0 (AN0). ADC en espera. ADC deshabilitado. ADCON2 = 0b10000101; //justificado a la derecha. 0 Tad (inicio manual). Fosc/16 ADCON0bits.ADON = 1; //modulo ADC habilitado. ADCON0bits.GO = 1; //Comienza conversion AD. //Inicializa flags. estado_adc.flag01 = 0; estado_adc.flag02 = 0; estado_adc.flag03 = 0; //Inicializa cosas para el ADC. sumavalor = 0; espera = 0; valor = 0; cuentasumavalor = 0; promedio = 0; } #define LOBYTE(x) (*((char *)&x)) #define HIBYTE(x) (*(((char *)&x)+1)) /******************************************************************************/ // If we got some bytes from the host, then echo them back. static void USBEcho(void) { byte rxCnt,i=0; if ((deviceState < CONFIGURED) || (UCONbits.SUSPND==1)) return; // Find out if an Output report has been received from the host. rxCnt=CDCgets(rxBuffer); // If no bytes in, then nothing to do if (rxCnt == 0) return; // Copy input bytes to the output buffer // for (i=0;i<rxCnt;i++) // txBuffer[i] = rxBuffer[i]; for(i=0;i<=32;i++) { while ( ADCON0bits.GO == 1 ){;} txBuffer[2*i]=ADRESH; if(i<32) txBuffer[2*i+1]=ADRESL; ADCON0bits.GO=1; } // As long as the SIE is owned by the processor, we let USB tasks continue. while (EP_IN_BD(CDC_DATA_EP_NUM).Stat.UOWN) // ProcessUSBTransactions(); ; if(strncmp(rxBuffer,"hola\r\n",6)==0) CDCputs(txBuffer,62); else CDCputs("nada",4); } /******************************************************************************/ void ProcessIO(void) { // User Application USB tasks if ((deviceState < CONFIGURED) || (UCONbits.SUSPND==1)) return; // Process USB: Echo back any bytes that have come in. USBEcho(); // Probando el ADC. if ( ADCON0bits.GO == 0 ) { if ( estado_adc.flag01 == 0 ) { adch = ADRESH; adcl = ADRESL; estado_adc.flag01 = 1; //Dos bytes de 8 en un word de 16. valor = (int)ADRESL | ( (int)ADRESH << 8 ); sumavalor = sumavalor + valor; cuentasumavalor++; if ( cuentasumavalor >= 20 ) { //Rescata el numero de sumatorias. cuentasumaaux = cuentasumavalor; //Calcula el promedio. promedio = sumavalor / 20; //Desarma el promedio de 16 bit en dos partes de 8 bits. adchaux = HIBYTE(promedio); adclaux = LOBYTE(promedio); //Reinicia las areas de trabajo. sumavalor = 0; cuentasumavalor = 0; promedio = 0; } } espera++; if ( espera >= 100 ) { //Rescata tiempo de espera. esperaaux = espera; //Reinicia ADC. ADCON0bits.GO=1; //Reinicia flag de entrada. estado_adc.flag01 = 0; espera = 0; } } } /******************************************************************************/ // Handle control out. This might be an alternate way of processing // an output report, so all that's needed is to point the output // pointer to the output buffer // Initialization for a SET_REPORT request. This routine will be // invoked during the setup stage and is used to set up the buffer // for receiving data from the host. // void SetupOutputReport(byte reportID) // { // if (reportID == 0) // { // // When the report arrives in the data stage, the data will be // // stored in HIDFeatureBuffer // // inPtr = (byte*)&HIDRxBuffer; // } // } /******************************************************************************/ // Post processing for a SET_REPORT request. After all the data has // been delivered from host to device, this will be invoked to perform // application specific processing. // void SetOutputReport(byte reportID) // { // // #if DEBUG_PRINT // printf("SetOutputReport(0x%hx)\r\n", reportID); // #endif // // // Currently only handling report 0, ignore any others. // if (reportID != 0) // return; // // // LATB=HIDRxBuffer[0]; // // // x11 to signal SET_REPORT transfer // LATBbits.LATB1=1; // LATBbits.LATB0=1; // // // // TBD: do something. Not currently implemented because the output // // report is being handled by an interrupt endpoint. // } /******************************************************************************/ // Handle a control input report. // void GetInputReport(byte reportID) // { // // #if DEBUG_PRINT // printf("GetInputReport: 0x%uhx\r\n", reportID); // #endif // // if (reportID == 0) // { // byte i; // // Send back the contents of the HID report // // TBD: provide useful information... // // outPtr = (byte *)&HIDTxBuffer; // // // // HIDTxBuffer[0]=PORTA; // // // HIDTxBuffer[1]=0xF2; //this is to differentiate between different transfer types // // // HIDTxBuffer[2]=HIBYTE(timestamp); // // // HIDTxBuffer[3]=LOBYTE(timestamp); // for(i=4;i<HID_INPUT_REPORT_BYTES;i++) // // HIDTxBuffer[i]=HIDRxBuffer[i]; // // // The number of bytes in the report (from usb.h). // wCount = HID_INPUT_REPORT_BYTES; // transferType=0; // } // } void init_CDC() { INTCON=0; INTCON2=0xC0; UCON=0; UCFG=0; 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; // Initialize USB for CDC UCFG = 0x14; // Enable pullup resistors; full speed mode deviceState = DETACHED; remoteWakeup = 0x00; currentConfiguration = 0x00; // And enable USB module while(deviceState != CONFIGURED) { EnableUSBModule(); if(UCFGbits.UTEYE != 1) ProcessUSBTransactions(); } } /******************************************************************************/ // Entry point of the firmware. void main(void) { byte led_cnt=0; // Set all I/O pins to digital ADCON1 |= 0x0F; PIE1=0; PIE2=0; // Initialize USB // UCFG = 0x14; // Enable pullup resistors; full speed mode // // deviceState = DETACHED; // remoteWakeup = 0x00; // currentConfiguration = 0x00; init_CDC(); PIE2bits.USBIE = 1; INTCON = 0xC0; // Call user initialization function UserInit(); #define LED1 LATCbits.LATC0 //#define LED2 LATAbits.LATA2 while(1) { // Ensure USB module is available // EnableUSBModule(); //esto es de usb.c, lo deja en el estado powered // // // As long as we aren't in test mode (UTEYE), process // // USB transactions. // if(UCFGbits.UTEYE != 1)//no se debe conectar el usb si UTEYE esta activo por que este genera un testeo // ProcessUSBTransactions();//esta en usb.c tmb // Application specific tasks // ProcessIO(); USBEcho(); //Blink LED2 @ 1Hz when configured if(INTCONbits.TMR0IF){ INTCONbits.TMR0IF=0; timestamp++; led_cnt++; if (deviceState<CONFIGURED&&led_cnt>=10){ //LED2 = !LED2; LED1 = !LED1; led_cnt=0; } else if (deviceState == CONFIGURED&&led_cnt>=46){ //LED2 = !LED2; LED1 = !LED1; led_cnt=0; } } } }
Simplemente no compila, arroja:
Citar
sdcc --use-non-free -mpic16 -p18f4550 -V --debug -I/home/alx/silly-bytes/usb/para piclinux/ -c PICUSBFW.c
+ "/usr/bin/sdcpp" -nostdinc -Wall -I/home/alx/silly-bytes/usb/para\ piclinux/ -Dpic18f4550 -D__18f4550 -D__SDCC_PIC18F4550 -DSTACK_MODEL_SMALL -D__STACK_MODEL_SMALL -obj-ext=.o -D__SDCC_USE_NON_FREE -DSDCC_USE_NON_FREE -D__SDCC=3_2_0 -DSDCC=320 -D__SDCC_REVISION=8008 -DSDCC_REVISION=8008 -D__SDCC_pic16 -DSDCC_pic16 -D__pic16 -D__STDC_NO_COMPLEX__ -D__STDC_NO_THREADS__ -D__STDC_NO_ATOMICS__ -D__STDC_NO_VLA__ -isystem "/usr/bin/../share/sdcc/include/pic16" -isystem "/usr/share/sdcc/include/pic16" -isystem "/usr/bin/../share/sdcc/include" -isystem "/usr/share/sdcc/include" -isystem "/usr/bin/../share/sdcc/non-free/include/pic16" -isystem "/usr/share/sdcc/non-free/include/pic16" -isystem "/usr/bin/../share/sdcc/non-free/include" -isystem "/usr/share/sdcc/non-free/include" "PICUSBFW.c"
PICUSBFW.c:38: error: token -> 'char' ; column 12
*** Salida con estado: 1 ***
Alguien sabe de un proyecto libre para hacer esto? o alguien lo ha echo antes, como puedo hacerlo?
Muchas gracias!, Saludos.