Control USB con PICF4x bajo GNU/Linux

Iniciado por dac, 9 Diciembre 2012, 16:52 PM

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

dac

Saludos comunidad!

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 (cpp) [Seleccionar]
/*
* 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.