add FPGA flash mechanism, support for Windows
This commit is contained in:
parent
c2c221703d
commit
4cd82c2369
|
@ -14,7 +14,10 @@ C_SOURCES=\
|
|||
src/osmosdr.c \
|
||||
src/sam3u.c \
|
||||
src/serial.c \
|
||||
src/utils.c
|
||||
src/utils.c \
|
||||
src/lattice/hardware.c \
|
||||
src/lattice/slim_pro.c \
|
||||
src/lattice/slim_vme.c
|
||||
|
||||
# general compiler flags
|
||||
CFLAGS=-Wall
|
||||
|
|
|
@ -0,0 +1,11 @@
|
|||
@echo off
|
||||
mkdir obj
|
||||
gcc -Wall -DWINDOWS -O2 -s -Werror -ffunction-sections -fdata-sections -c src/main.c -o obj/main.o
|
||||
gcc -Wall -DWINDOWS -O2 -s -Werror -ffunction-sections -fdata-sections -c src/osmosdr.c -o obj/osmosdr.o
|
||||
gcc -Wall -DWINDOWS -O2 -s -Werror -ffunction-sections -fdata-sections -c src/sam3u.c -o obj/sam3u.o
|
||||
gcc -Wall -DWINDOWS -O2 -s -Werror -ffunction-sections -fdata-sections -c src/serial.c -o obj/serial.o
|
||||
gcc -Wall -DWINDOWS -O2 -s -Werror -ffunction-sections -fdata-sections -c src/utils.c -o obj/utils.o
|
||||
gcc -Wall -DWINDOWS -O2 -s -Werror -ffunction-sections -fdata-sections -c src/lattice/hardware.c -o obj/hardware.o
|
||||
gcc -Wall -DWINDOWS -O2 -s -Werror -ffunction-sections -fdata-sections -c src/lattice/slim_pro.c -o obj/slim_pro.o
|
||||
gcc -Wall -DWINDOWS -O2 -s -Werror -ffunction-sections -fdata-sections -c src/lattice/slim_vme.c -o obj/slim_vme.o
|
||||
gcc -static -Wl,-Map=rumba.map -s -Wl,--gc-sections -o rumba.exe -Wl,--start-group obj/main.o obj/osmosdr.o obj/sam3u.o obj/serial.o obj/utils.o obj/hardware.o obj/slim_pro.o obj/slim_vme.o --Wl,--end-group
|
|
@ -0,0 +1,223 @@
|
|||
/**************************************************************
|
||||
*
|
||||
* Lattice Semiconductor Corp. Copyright 2008
|
||||
*
|
||||
*
|
||||
***************************************************************/
|
||||
|
||||
|
||||
/**************************************************************
|
||||
*
|
||||
* Revision History of hardware.c
|
||||
*
|
||||
*
|
||||
* 09/11/07 NN type cast all the mismatch variables
|
||||
***************************************************************/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include "opcode.h"
|
||||
#include "hardware.h"
|
||||
#include "../sam3u.h"
|
||||
|
||||
/*************************************************************
|
||||
* *
|
||||
* EXTERNAL FUNCTION *
|
||||
* *
|
||||
*************************************************************/
|
||||
|
||||
extern void ispVMStateMachine( char a_cNextState );
|
||||
|
||||
/*************************************************************
|
||||
* *
|
||||
* READPORT *
|
||||
* *
|
||||
* INPUT: *
|
||||
* None. *
|
||||
* *
|
||||
* RETURN: *
|
||||
* Returns the bit read back from the device. *
|
||||
* *
|
||||
* DESCRIPTION: *
|
||||
* This function is used to read the TDO pin from the *
|
||||
* input port. *
|
||||
* *
|
||||
* NOTE: This function should be modified in an embedded *
|
||||
* system! *
|
||||
* *
|
||||
*************************************************************/
|
||||
|
||||
unsigned char readPort()
|
||||
{
|
||||
uint32_t value;
|
||||
|
||||
sam3uRead32(g_ispFd, 0x400e0e00 + 0x3c, &value);
|
||||
|
||||
if(value & (1 << 6))
|
||||
return 1;
|
||||
else return 0;
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
* *
|
||||
* WRITEPORT *
|
||||
* *
|
||||
* INPUT: *
|
||||
* a_ucPins: a byte to indicate which pin will be *
|
||||
* depending on the value. *
|
||||
* *
|
||||
* a_ucValue: the value to determine of the pin above *
|
||||
* will be written out or not. *
|
||||
* *
|
||||
* RETURN: *
|
||||
* None. *
|
||||
* *
|
||||
* DESCRIPTION: *
|
||||
* To apply the specified value to the pins indicated. *
|
||||
* This routine will likely be modified for specific *
|
||||
* systems. As an example, this code is for the PC, as *
|
||||
* described below. *
|
||||
* *
|
||||
* This routine uses the IBM-PC standard Parallel port, *
|
||||
* along with the schematic shown in Lattice *
|
||||
* documentation, to apply the signals to the programming *
|
||||
* loop. *
|
||||
* *
|
||||
* NOTE: This function should be modified in an embedded *
|
||||
* system! *
|
||||
* *
|
||||
*************************************************************/
|
||||
|
||||
void writePort( unsigned char a_ucPins, unsigned char a_ucValue )
|
||||
{
|
||||
uint32_t value = 0;
|
||||
|
||||
if(a_ucPins & pinTDI)
|
||||
value |= (1 << 8);
|
||||
if(a_ucPins & pinTCK)
|
||||
value |= (1 << 7);
|
||||
if(a_ucPins & pinTMS)
|
||||
value |= (1 << 5);
|
||||
|
||||
if(a_ucValue)
|
||||
sam3uWrite32(g_ispFd, 0x400e0e00 + 0x30, value);
|
||||
else sam3uWrite32(g_ispFd, 0x400e0e00 + 0x34, value);
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
* *
|
||||
* ISPVMDELAY *
|
||||
* *
|
||||
* INPUT: *
|
||||
* a_uiDelay: delay in milliseconds *
|
||||
* *
|
||||
* RETURN: *
|
||||
* None. *
|
||||
* *
|
||||
* DESCRIPTION: *
|
||||
* The user must implement a delay to observe a_uiDelay, *
|
||||
* where a_uiDelay is the number of milliseconds that must *
|
||||
* pass before data is read from in_port. Since platforms and*
|
||||
* processor speeds vary greatly, this task is left to the *
|
||||
* user. This subroutine is called upon to provide a delay *
|
||||
* from 1 millisecond to a few hundreds milliseconds each time*
|
||||
* That is the reason behind using unsigned long integer in *
|
||||
* this subroutine. It is OK to provide longer delay than *
|
||||
* required. It is not acceptable if the delay is shorter than*
|
||||
* required. *
|
||||
* *
|
||||
* Note: user must re - implement to target specific hardware.*
|
||||
* *
|
||||
* Example: Use the for loop to create the microsecond delay. *
|
||||
* Loop 1K times to produce the milliseconds delay. *
|
||||
* *
|
||||
* Let the CPU clock (system clock) be F Mhz. *
|
||||
* *
|
||||
* Let the for loop represented by the 2 lines of *
|
||||
* machine code: *
|
||||
* LOOP: DEC RA; *
|
||||
* JNZ LOOP; *
|
||||
* Let the for loop number for one microsecond be L. *
|
||||
* Lets assume 4 system clocks for each line of *
|
||||
* machine code. *
|
||||
* Then 1 us = 1/F (microseconds per clock) *
|
||||
* x (2 lines) x (4 clocks per line) x L*
|
||||
* = 8L/F *
|
||||
* Or L = F/8; *
|
||||
* *
|
||||
* Convert the unit in microseconds to *
|
||||
* milliseconds. *
|
||||
* L = F/8 x 1000; *
|
||||
* Lets assume the CPU clock is set to 48MHZ. The C *
|
||||
* code then is: *
|
||||
* *
|
||||
* unsigned int F = 48; //MHZ. *
|
||||
* unsigned int L = F/8; //microseconds. *
|
||||
* unsigned int index, m; *
|
||||
* *
|
||||
* *
|
||||
* if (L < 1) L = 1; //minimum is i microsecond. *
|
||||
* for (index=0; index < a_uiDelay * L; index++) *
|
||||
* { *
|
||||
* //loop 1K times to produce milliseconds delay *
|
||||
* for (m=0; m<1000; m++); //milliseconds *
|
||||
* } *
|
||||
* return 0; *
|
||||
* *
|
||||
* *
|
||||
*************************************************************/
|
||||
|
||||
/* the unit of a_uiDelay is milliseconds */
|
||||
void ispVMDelay( unsigned int a_uiDelay )
|
||||
{
|
||||
//printf("sleep %d\n", a_uiDelay);
|
||||
//usleep(a_uiDelay * 1000);
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
* *
|
||||
* ENABLEHARDWARE *
|
||||
* *
|
||||
* INPUT: *
|
||||
* None. *
|
||||
* *
|
||||
* RETURN: *
|
||||
* None. *
|
||||
* *
|
||||
* DESCRIPTION: *
|
||||
* This function is called to enable the hardware. *
|
||||
* *
|
||||
* NOTE: This function should be modified in an embedded *
|
||||
* system! *
|
||||
* *
|
||||
*************************************************************/
|
||||
|
||||
void EnableHardware()
|
||||
{
|
||||
ispVMStateMachine(RESET);
|
||||
}
|
||||
|
||||
/*************************************************************
|
||||
* *
|
||||
* DISABLEHARDWARE *
|
||||
* *
|
||||
* INPUT: *
|
||||
* None. *
|
||||
* *
|
||||
* RETURN: *
|
||||
* None. *
|
||||
* *
|
||||
* DESCRIPTION: *
|
||||
* This function is called to disable the hardware. *
|
||||
* *
|
||||
* NOTE: This function should be modified in an embedded *
|
||||
* system! *
|
||||
* *
|
||||
*************************************************************/
|
||||
|
||||
void DisableHardware()
|
||||
{
|
||||
ispVMStateMachine(RESET);
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
#ifndef INCLUDE_HARDWARE_H
|
||||
#define INCLUDE_HARDWARE_H
|
||||
|
||||
#include "../utils.h"
|
||||
|
||||
HANDLE g_ispFd;
|
||||
const uint8_t* g_ispAlgo;
|
||||
size_t g_ispAlgoSize;
|
||||
const uint8_t* g_ispData;
|
||||
size_t g_ispDataSize;
|
||||
|
||||
|
||||
#endif // INCLUDE_HARDWARE_H
|
|
@ -0,0 +1,135 @@
|
|||
|
||||
/**************************************************************
|
||||
*
|
||||
* Revision History of opcode.h
|
||||
*
|
||||
*
|
||||
* 09/11/07 NN Updated to support version 1.3
|
||||
* This version supported new POLING STATUS LOOP opcodes
|
||||
* for Flash programming of the Lattice FPGA devices
|
||||
* #define LOOP = 0x58
|
||||
* #define ENDLOOP = 0x59
|
||||
***************************************************************/
|
||||
|
||||
|
||||
/*************************************************************
|
||||
* *
|
||||
* LATTICE CABLE DEFINTIONS. *
|
||||
* *
|
||||
* Define these only if the lattice cable is being used. *
|
||||
* *
|
||||
*************************************************************/
|
||||
|
||||
#define pinTDI 1
|
||||
#define pinTCK 2
|
||||
#define pinTMS 4
|
||||
#define pinENABLE 8
|
||||
#define pinTRST 16
|
||||
#define pinCE 32
|
||||
#define pinTDO 64
|
||||
|
||||
/*************************************************************
|
||||
* *
|
||||
* ERROR DEFINITIONS *
|
||||
* *
|
||||
*************************************************************/
|
||||
|
||||
#define ERR_VERIFY_FAIL -1
|
||||
#define ERR_FIND_ALGO_FILE -2
|
||||
#define ERR_FIND_DATA_FILE -3
|
||||
#define ERR_WRONG_VERSION -4
|
||||
#define ERR_ALGO_FILE_ERROR -5
|
||||
#define ERR_DATA_FILE_ERROR -6
|
||||
#define ERR_OUT_OF_MEMORY -7
|
||||
|
||||
/*************************************************************
|
||||
* *
|
||||
* DATA TYPE REGISTER BIT DEFINITIONS *
|
||||
* *
|
||||
*************************************************************/
|
||||
|
||||
#define SIR_DATA 0x0001 /*** Current command is SIR ***/
|
||||
#define SDR_DATA 0x0002 /*** Current command is SDR ***/
|
||||
#define TDI_DATA 0x0004 /*** Command contains TDI ***/
|
||||
#define TDO_DATA 0x0008 /*** Command contains TDO ***/
|
||||
#define MASK_DATA 0x0010 /*** Command contains MASK ***/
|
||||
#define DTDI_DATA 0x0020 /*** Verification flow ***/
|
||||
#define DTDO_DATA 0x0040 /*** Verification flow ***/
|
||||
#define COMPRESS 0x0080 /*** Compressed data file ***/
|
||||
#define COMPRESS_FRAME 0x0100 /*** Compressed data frame ***/
|
||||
|
||||
/*************************************************************
|
||||
* *
|
||||
* USED JTAG STATE *
|
||||
* *
|
||||
*************************************************************/
|
||||
|
||||
#define RESET 0x00
|
||||
#define IDLE 0x01
|
||||
#define IRPAUSE 0x02
|
||||
#define DRPAUSE 0x03
|
||||
#define SHIFTIR 0x04
|
||||
#define SHIFTDR 0x05
|
||||
#define DRCAPTURE 0x06
|
||||
|
||||
/*************************************************************
|
||||
* *
|
||||
* VME OPCODE DEFINITIONS *
|
||||
* *
|
||||
* These are the opcodes found in the VME file. Although *
|
||||
* most of them are similar to SVF commands, a few opcodes *
|
||||
* are available only in VME format. *
|
||||
* *
|
||||
*************************************************************/
|
||||
|
||||
#define STATE 0x10
|
||||
#define SIR 0x11
|
||||
#define SDR 0x12
|
||||
#define TCK 0x1B
|
||||
#define WAIT 0x1A
|
||||
#define ENDDR 0x02
|
||||
#define ENDIR 0x03
|
||||
#define HIR 0x06
|
||||
#define TIR 0x07
|
||||
#define HDR 0x08
|
||||
#define TDR 0x09
|
||||
#define TDI 0x13
|
||||
#define CONTINUE 0x70
|
||||
#define TDO 0x14
|
||||
#define MASK 0x15
|
||||
#define LOOP 0x58
|
||||
#define ENDLOOP 0x59
|
||||
#define LCOUNT 0x66
|
||||
#define LDELAY 0x67
|
||||
#define LSDR 0x68
|
||||
#define ENDSTATE 0x69
|
||||
#define ENDVME 0x7F
|
||||
|
||||
/*************************************************************
|
||||
* *
|
||||
* Begin future opcodes at 0xA0 to avoid conflict with Full *
|
||||
* VME opcodes. *
|
||||
* *
|
||||
*************************************************************/
|
||||
|
||||
#define BEGIN_REPEAT 0xA0
|
||||
#define END_REPEAT 0xA1
|
||||
#define END_FRAME 0xA2
|
||||
#define DATA 0xA3
|
||||
#define PROGRAM 0xA4
|
||||
#define VERIFY 0xA5
|
||||
#define DTDI 0xA6
|
||||
#define DTDO 0xA7
|
||||
|
||||
/*************************************************************
|
||||
* *
|
||||
* Opcode for discrete pins toggling *
|
||||
* *
|
||||
*************************************************************/
|
||||
#define signalENABLE 0x1C /*assert the ispEN pin*/
|
||||
#define signalTMS 0x1D /*assert the MODE or TMS pin*/
|
||||
#define signalTCK 0x1E /*assert the SCLK or TCK pin*/
|
||||
#define signalTDI 0x1F /*assert the SDI or TDI pin*/
|
||||
#define signalTRST 0x20 /*assert the RESET or TRST pin*/
|
||||
#define signalTDO 0x21 /*assert the RESET or TDO pin*/
|
||||
#define signalCableEN 0x22 /*assert the RESET or CableEN pin*/
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,218 @@
|
|||
/**************************************************************
|
||||
*
|
||||
* Lattice Semiconductor Corp. Copyright 2008
|
||||
*
|
||||
*
|
||||
***************************************************************/
|
||||
|
||||
|
||||
/**************************************************************
|
||||
*
|
||||
* Revision History of slim_vme.c
|
||||
*
|
||||
*
|
||||
* 09/11/07 NN Updated to support version 1.3
|
||||
* This version supported new POLING STATUS LOOP opcodes (LOOP and ENDLOOP)
|
||||
* for Flash programming of the Lattice FPGA devices
|
||||
* 09/11/07 NN Added Global variables initialization
|
||||
* 09/11/07 NN type cast all mismatch variables
|
||||
***************************************************************/
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "opcode.h"
|
||||
#include "hardware.h"
|
||||
|
||||
#define xdata
|
||||
#define reentrant
|
||||
|
||||
/*************************************************************
|
||||
* *
|
||||
* EXTERNAL FUNCTIONS *
|
||||
* *
|
||||
*************************************************************/
|
||||
|
||||
extern unsigned char GetByte( int a_iCurrentIndex, char a_cAlgo );
|
||||
extern short ispProcessVME();
|
||||
extern void EnableHardware();
|
||||
extern void DisableHardware();
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* Supported VME versions.
|
||||
*
|
||||
***************************************************************/
|
||||
char *g_szSupportedVersions[] = { "_SVME1.1", "_SVME1.2", "_SVME1.3", 0 };
|
||||
|
||||
/*************************************************************
|
||||
* *
|
||||
* EXTERNAL VARIABLES *
|
||||
* *
|
||||
* If the algorithm does not require the data, then *
|
||||
* declare the variables g_pucDataArray and g_iDataSize *
|
||||
* as local variables and set them to NULL and 0, *
|
||||
* respectively. *
|
||||
* *
|
||||
* Example: *
|
||||
* xdata unsigned char * g_pucDataArray = NULL; *
|
||||
* xdata int g_iDataSize = 0; *
|
||||
* *
|
||||
*************************************************************/
|
||||
|
||||
extern int g_iMovingAlgoIndex;
|
||||
extern int g_iMovingDataIndex;
|
||||
extern unsigned short g_usDataType;
|
||||
|
||||
|
||||
/*************************************************************
|
||||
* *
|
||||
* ISPVMENTRYPOINT *
|
||||
* *
|
||||
* INPUT: *
|
||||
* a_pszAlgoFile: this is the name of the algorithm file. *
|
||||
* *
|
||||
* a_pszDataFile: this is the name of the data file. *
|
||||
* Note that this argument may be empty if the algorithm *
|
||||
* does not require a data file. *
|
||||
* *
|
||||
* RETURN: *
|
||||
* The return value will be a negative number if an error *
|
||||
* occurred, or 0 if everything was successful *
|
||||
* *
|
||||
* DESCRIPTION: *
|
||||
* This function opens the file pointers to the algo and *
|
||||
* data file. It intializes global variables to their *
|
||||
* default values and enters the processor. *
|
||||
* *
|
||||
*************************************************************/
|
||||
|
||||
short int ispEntryPoint()
|
||||
{
|
||||
char szFileVersion[ 9 ] = { 0 };
|
||||
short int siRetCode = 0;
|
||||
short int iIndex = 0;
|
||||
short int cVersionIndex = 0;
|
||||
|
||||
/*************************************************************
|
||||
* *
|
||||
* VARIABLES INITIALIZATION *
|
||||
* *
|
||||
*************************************************************/
|
||||
|
||||
g_usDataType = 0;
|
||||
g_iMovingAlgoIndex = 0;
|
||||
g_iMovingDataIndex = 0;
|
||||
|
||||
if ( g_ispDataSize ) {
|
||||
if ( GetByte( g_iMovingDataIndex++, 0 ) ) {
|
||||
g_usDataType |= COMPRESS;
|
||||
}
|
||||
}
|
||||
/***************************************************************
|
||||
*
|
||||
* Read and store the version of the VME file.
|
||||
*
|
||||
***************************************************************/
|
||||
|
||||
for ( iIndex = 0; iIndex < 8; iIndex++ ) {
|
||||
szFileVersion[ iIndex ] = GetByte( g_iMovingAlgoIndex++, 1 );
|
||||
}
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* Compare the VME file version against the supported version.
|
||||
*
|
||||
***************************************************************/
|
||||
|
||||
for ( cVersionIndex = 0; g_szSupportedVersions[ cVersionIndex ] != 0; cVersionIndex++ ) {
|
||||
for ( iIndex = 0; iIndex < 8; iIndex++ ) {
|
||||
if ( szFileVersion[ iIndex ] != g_szSupportedVersions[ cVersionIndex ][ iIndex ] ) {
|
||||
siRetCode = ERR_WRONG_VERSION;
|
||||
break;
|
||||
}
|
||||
siRetCode = 0;
|
||||
}
|
||||
|
||||
if ( siRetCode == 0 ) {
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* Found matching version, break.
|
||||
*
|
||||
***************************************************************/
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if ( siRetCode < 0 ) {
|
||||
|
||||
/***************************************************************
|
||||
*
|
||||
* VME file version failed to match the supported versions.
|
||||
*
|
||||
***************************************************************/
|
||||
|
||||
return ERR_WRONG_VERSION;
|
||||
}
|
||||
|
||||
|
||||
/*************************************************************
|
||||
* *
|
||||
* Start the hardware. *
|
||||
* *
|
||||
*************************************************************/
|
||||
|
||||
EnableHardware();
|
||||
|
||||
/*************************************************************
|
||||
* *
|
||||
* Begin processing algorithm and data file. *
|
||||
* *
|
||||
*************************************************************/
|
||||
|
||||
siRetCode = ispProcessVME();
|
||||
|
||||
/*************************************************************
|
||||
* *
|
||||
* Stop the hardware. *
|
||||
* *
|
||||
*************************************************************/
|
||||
|
||||
DisableHardware();
|
||||
|
||||
/*************************************************************
|
||||
* *
|
||||
* Return the return code. *
|
||||
* *
|
||||
*************************************************************/
|
||||
|
||||
return ( siRetCode );
|
||||
}
|
||||
/*************************************************************
|
||||
* *
|
||||
* MAIN *
|
||||
* *
|
||||
*************************************************************/
|
||||
|
||||
#if 0
|
||||
short int main()
|
||||
{
|
||||
/*************************************************************
|
||||
* *
|
||||
* LOCAL VARIABLES: *
|
||||
* siRetCode: this variable holds the return. *
|
||||
* *
|
||||
*************************************************************/
|
||||
|
||||
short int siRetCode = 0;
|
||||
/*************************************************************
|
||||
* *
|
||||
* Pass in the command line arguments to the entry point. *
|
||||
* *
|
||||
*************************************************************/
|
||||
|
||||
siRetCode = ispEntryPoint();
|
||||
return( siRetCode );
|
||||
}
|
||||
#endif
|
|
@ -8,19 +8,24 @@
|
|||
static int printSyntax()
|
||||
{
|
||||
fprintf(stderr, "Error: Invalid command line!\n\n"
|
||||
#ifdef WINDOWS
|
||||
"syntax: sdr-samba com1 command\n"
|
||||
#else
|
||||
"syntax: sdr-samba /dev/ttyACM0 command\n"
|
||||
#endif
|
||||
"valid commands are:\n"
|
||||
" - detect: detect OsmoSDR and print unique ID\n"
|
||||
" - blink: blink LEDs on board\n"
|
||||
" - ramload image.bin: load image.bin into SRAM and start it\n"
|
||||
" - flash image.bin: write image.bin to FLASH\n");
|
||||
" - flashfpga algo.vme data.vme: write data.vme to FPGA FLASH using algo.vme\n"
|
||||
" - flashmcu image.bin: write image.bin to MCU FLASH\n");
|
||||
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
int fd;
|
||||
HANDLE fd;
|
||||
int res = -1;
|
||||
void* bin;
|
||||
size_t binSize;
|
||||
|
@ -31,7 +36,7 @@ int main(int argc, char* argv[])
|
|||
if(strcmp(argv[2], "detect") == 0) {
|
||||
if(argc != 3)
|
||||
return printSyntax();
|
||||
if((fd = serialOpen(argv[1])) < 0)
|
||||
if((fd = serialOpen(argv[1])) == INVALID_HANDLE_VALUE)
|
||||
return EXIT_FAILURE;
|
||||
res = 0;
|
||||
if(res >= 0)
|
||||
|
@ -44,7 +49,7 @@ int main(int argc, char* argv[])
|
|||
} else if(strcmp(argv[2], "blink") == 0) {
|
||||
if(argc != 3)
|
||||
return printSyntax();
|
||||
if((fd = serialOpen(argv[1])) < 0)
|
||||
if((fd = serialOpen(argv[1])) == INVALID_HANDLE_VALUE)
|
||||
return EXIT_FAILURE;
|
||||
res = 0;
|
||||
if(res >= 0)
|
||||
|
@ -57,7 +62,7 @@ int main(int argc, char* argv[])
|
|||
return printSyntax();
|
||||
if((bin = loadFile(argv[3], &binSize)) == NULL)
|
||||
return EXIT_FAILURE;
|
||||
if((fd = serialOpen(argv[1])) < 0)
|
||||
if((fd = serialOpen(argv[1])) == INVALID_HANDLE_VALUE)
|
||||
return EXIT_FAILURE;
|
||||
res = 0;
|
||||
if(res >= 0)
|
||||
|
@ -65,18 +70,35 @@ int main(int argc, char* argv[])
|
|||
if(res >= 0)
|
||||
res = osmoSDRRamLoad(fd, bin, binSize);
|
||||
serialClose(fd);
|
||||
} else if(strcmp(argv[2], "flash") == 0) {
|
||||
if(argc != 4)
|
||||
} else if(strcmp(argv[2], "flashfpga") == 0) {
|
||||
void* algo;
|
||||
size_t algoSize;
|
||||
if(argc != 5)
|
||||
return printSyntax();
|
||||
if((bin = loadFile(argv[3], &binSize)) == NULL)
|
||||
if((algo = loadFile(argv[3], &algoSize)) == NULL)
|
||||
return EXIT_FAILURE;
|
||||
if((fd = serialOpen(argv[1])) < 0)
|
||||
if((bin = loadFile(argv[4], &binSize)) == NULL)
|
||||
return EXIT_FAILURE;
|
||||
if((fd = serialOpen(argv[1])) == INVALID_HANDLE_VALUE)
|
||||
return EXIT_FAILURE;
|
||||
res = 0;
|
||||
if(res >= 0)
|
||||
res = osmoSDRDetect(fd);
|
||||
if(res >= 0)
|
||||
res = osmoSDRFlash(fd, bin, binSize);
|
||||
res = osmoSDRFlashFPGA(fd, algo, algoSize, bin, binSize);
|
||||
serialClose(fd);
|
||||
} else if(strcmp(argv[2], "flashmcu") == 0) {
|
||||
if(argc != 4)
|
||||
return printSyntax();
|
||||
if((bin = loadFile(argv[3], &binSize)) == NULL)
|
||||
return EXIT_FAILURE;
|
||||
if((fd = serialOpen(argv[1])) == INVALID_HANDLE_VALUE)
|
||||
return EXIT_FAILURE;
|
||||
res = 0;
|
||||
if(res >= 0)
|
||||
res = osmoSDRDetect(fd);
|
||||
if(res >= 0)
|
||||
res = osmoSDRFlashMCU(fd, bin, binSize);
|
||||
serialClose(fd);
|
||||
} else {
|
||||
return printSyntax();
|
||||
|
|
|
@ -2,8 +2,9 @@
|
|||
#include <unistd.h>
|
||||
#include "osmosdr.h"
|
||||
#include "sam3u.h"
|
||||
#include "lattice/hardware.h"
|
||||
|
||||
int osmoSDRDetect(int fd)
|
||||
int osmoSDRDetect(HANDLE fd)
|
||||
{
|
||||
uint32_t chipID;
|
||||
|
||||
|
@ -20,7 +21,7 @@ int osmoSDRDetect(int fd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int osmoSDRPrintUID(int fd, int bank)
|
||||
int osmoSDRPrintUID(HANDLE fd, int bank)
|
||||
{
|
||||
uint8_t uniqueID[16];
|
||||
int i;
|
||||
|
@ -38,7 +39,7 @@ int osmoSDRPrintUID(int fd, int bank)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int osmoSDRBlink(int fd)
|
||||
int osmoSDRBlink(HANDLE fd)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
@ -68,12 +69,16 @@ int osmoSDRBlink(int fd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int osmoSDRRamLoad(int fd, void* bin, size_t binSize)
|
||||
int osmoSDRRamLoad(HANDLE fd, const void* bin, size_t binSize)
|
||||
{
|
||||
size_t ofs;
|
||||
uint32_t tmp;
|
||||
|
||||
#ifdef WINDOWS
|
||||
printf("Uploading %u bytes @ 0x20001000", binSize);
|
||||
#else
|
||||
printf("Uploading %zu bytes @ 0x20001000", binSize);
|
||||
#endif
|
||||
|
||||
for(ofs = 0; ofs < binSize; ofs += 4) {
|
||||
if(sam3uWrite32(fd, 0x20001000 + ofs, ((uint32_t*)bin)[ofs / 4]) < 0)
|
||||
|
@ -98,7 +103,37 @@ int osmoSDRRamLoad(int fd, void* bin, size_t binSize)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int osmoSDRFlash(int fd, void* bin, size_t binSize)
|
||||
int osmoSDRFlashMCU(HANDLE fd, const void* bin, size_t binSize)
|
||||
{
|
||||
return sam3uFlash(fd, 0, bin, binSize);
|
||||
}
|
||||
|
||||
// HACK
|
||||
short int ispEntryPoint();
|
||||
|
||||
int osmoSDRFlashFPGA(HANDLE fd, const void* algo, size_t algoSize, const void* bin, size_t binSize)
|
||||
{
|
||||
g_ispFd = fd;
|
||||
g_ispAlgo = (uint8_t*)algo;
|
||||
g_ispAlgoSize = algoSize;
|
||||
g_ispData = (uint8_t*)bin;
|
||||
g_ispDataSize = binSize;
|
||||
|
||||
if(sam3uWrite32(fd, 0x400e0410, (1 << 11)) < 0)
|
||||
return -1;
|
||||
|
||||
if(sam3uWrite32(fd, 0x400e0e00 + 0x44, (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8)) < 0)
|
||||
return -1;
|
||||
if(sam3uWrite32(fd, 0x400e0e00 + 0x60, (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8)) < 0)
|
||||
return -1;
|
||||
if(sam3uWrite32(fd, 0x400e0e00 + 0x54, (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8)) < 0)
|
||||
return -1;
|
||||
if(sam3uWrite32(fd, 0x400e0e00 + 0x10, (1 << 5) | (1 << 7) | (1 << 8)) < 0)
|
||||
return -1;
|
||||
if(sam3uWrite32(fd, 0x400e0e00 + 0x00, (1 << 5) | (1 << 6) | (1 << 7) | (1 << 8)) < 0)
|
||||
return -1;
|
||||
|
||||
ispEntryPoint();
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -2,11 +2,13 @@
|
|||
#define INCLUDE_OSMOSDR_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "utils.h"
|
||||
|
||||
int osmoSDRDetect(int fd);
|
||||
int osmoSDRPrintUID(int fd, int bank);
|
||||
int osmoSDRBlink(int fd);
|
||||
int osmoSDRRamLoad(int fd, void* bin, size_t binSize);
|
||||
int osmoSDRFlash(int fd, void* bin, size_t binSize);
|
||||
int osmoSDRDetect(HANDLE fd);
|
||||
int osmoSDRPrintUID(HANDLE fd, int bank);
|
||||
int osmoSDRBlink(HANDLE fd);
|
||||
int osmoSDRRamLoad(HANDLE fd, const void* bin, size_t binSize);
|
||||
int osmoSDRFlashMCU(HANDLE fd, const void* bin, size_t binSize);
|
||||
int osmoSDRFlashFPGA(HANDLE fd, const void* algo, size_t algoSize, const void* bin, size_t binSize);
|
||||
|
||||
#endif // INCLUDE_OSMOSDR_H
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
#include "sam3u.h"
|
||||
#include "serial.h"
|
||||
|
||||
int sam3uRead32(int fd, uint32_t address, uint32_t* value)
|
||||
int sam3uRead32(HANDLE fd, uint32_t address, uint32_t* value)
|
||||
{
|
||||
char str[32];
|
||||
sprintf(str, "w%08X,4#", address);
|
||||
|
@ -27,7 +27,7 @@ int sam3uRead32(int fd, uint32_t address, uint32_t* value)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int sam3uRead16(int fd, uint32_t address, uint16_t* value)
|
||||
int sam3uRead16(HANDLE fd, uint32_t address, uint16_t* value)
|
||||
{
|
||||
char str[32];
|
||||
sprintf(str, "h%08X,2#", address);
|
||||
|
@ -49,7 +49,7 @@ int sam3uRead16(int fd, uint32_t address, uint16_t* value)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int sam3uRead8(int fd, uint32_t address, uint8_t* value)
|
||||
int sam3uRead8(HANDLE fd, uint32_t address, uint8_t* value)
|
||||
{
|
||||
char str[32];
|
||||
sprintf(str, "o%08X,1#", address);
|
||||
|
@ -71,7 +71,7 @@ int sam3uRead8(int fd, uint32_t address, uint8_t* value)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int sam3uWrite32(int fd, uint32_t address, uint32_t value)
|
||||
int sam3uWrite32(HANDLE fd, uint32_t address, uint32_t value)
|
||||
{
|
||||
char str[32];
|
||||
sprintf(str, "W%08X,%08X#", address, value);
|
||||
|
@ -82,7 +82,7 @@ int sam3uWrite32(int fd, uint32_t address, uint32_t value)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int sam3uWrite16(int fd, uint32_t address, uint16_t value)
|
||||
int sam3uWrite16(HANDLE fd, uint32_t address, uint16_t value)
|
||||
{
|
||||
char str[32];
|
||||
sprintf(str, "H%08X,%04X#", address, value);
|
||||
|
@ -93,7 +93,7 @@ int sam3uWrite16(int fd, uint32_t address, uint16_t value)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int sam3uWrite8(int fd, uint32_t address, uint8_t value)
|
||||
int sam3uWrite8(HANDLE fd, uint32_t address, uint8_t value)
|
||||
{
|
||||
char str[32];
|
||||
sprintf(str, "O%08X,%02X#", address, value);
|
||||
|
@ -104,7 +104,7 @@ int sam3uWrite8(int fd, uint32_t address, uint8_t value)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int sam3uRun(int fd, uint32_t address)
|
||||
int sam3uRun(HANDLE fd, uint32_t address)
|
||||
{
|
||||
char str[32];
|
||||
sprintf(str, "G%08X#", address);
|
||||
|
@ -113,9 +113,9 @@ int sam3uRun(int fd, uint32_t address)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int sam3uDetect(int fd, uint32_t* chipID)
|
||||
int sam3uDetect(HANDLE fd, uint32_t* chipID)
|
||||
{
|
||||
char c;
|
||||
uint8_t c;
|
||||
|
||||
while(serialGetC(fd, &c, 100) >= 0) ;
|
||||
|
||||
|
@ -130,7 +130,7 @@ int sam3uDetect(int fd, uint32_t* chipID)
|
|||
return sam3uRead32(fd, 0x400e0740, chipID);
|
||||
}
|
||||
|
||||
int sam3uReadUniqueID(int fd, int bank, uint8_t* uniqueID)
|
||||
int sam3uReadUniqueID(HANDLE fd, int bank, uint8_t* uniqueID)
|
||||
{
|
||||
uint32_t regBase;
|
||||
uint32_t flashBase;
|
||||
|
@ -175,7 +175,7 @@ int sam3uReadUniqueID(int fd, int bank, uint8_t* uniqueID)
|
|||
return 0;
|
||||
}
|
||||
|
||||
int sam3uFlash(int fd, int bank, void* bin, size_t binSize)
|
||||
int sam3uFlash(HANDLE fd, int bank, const void* bin, size_t binSize)
|
||||
{
|
||||
uint32_t regBase;
|
||||
uint32_t flashBase;
|
||||
|
|
|
@ -2,18 +2,19 @@
|
|||
#define INCLUDE_SAM3U_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "utils.h"
|
||||
|
||||
int sam3uRead32(int fd, uint32_t address, uint32_t* value);
|
||||
int sam3uRead16(int fd, uint32_t address, uint16_t* value);
|
||||
int sam3uRead8(int fd, uint32_t address, uint8_t* value);
|
||||
int sam3uRead32(HANDLE fd, uint32_t address, uint32_t* value);
|
||||
int sam3uRead16(HANDLE fd, uint32_t address, uint16_t* value);
|
||||
int sam3uRead8(HANDLE fd, uint32_t address, uint8_t* value);
|
||||
|
||||
int sam3uWrite32(int fd, uint32_t address, uint32_t value);
|
||||
int sam3uWrite16(int fd, uint32_t address, uint16_t value);
|
||||
int sam3uWrite8(int fd, uint32_t address, uint8_t value);
|
||||
int sam3uWrite32(HANDLE fd, uint32_t address, uint32_t value);
|
||||
int sam3uWrite16(HANDLE fd, uint32_t address, uint16_t value);
|
||||
int sam3uWrite8(HANDLE fd, uint32_t address, uint8_t value);
|
||||
|
||||
int sam3uRun(int fd, uint32_t address);
|
||||
int sam3uDetect(int fd, uint32_t* chipID);
|
||||
int sam3uReadUniqueID(int fd, int bank, uint8_t* uniqueID);
|
||||
int sam3uFlash(int fd, int bank, void* bin, size_t binSize);
|
||||
int sam3uRun(HANDLE fd, uint32_t address);
|
||||
int sam3uDetect(HANDLE fd, uint32_t* chipID);
|
||||
int sam3uReadUniqueID(HANDLE fd, int bank, uint8_t* uniqueID);
|
||||
int sam3uFlash(HANDLE fd, int bank, const void* bin, size_t binSize);
|
||||
|
||||
#endif // INCLUDE_SAM3U_H
|
||||
|
|
|
@ -1,175 +1,337 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <termios.h>
|
||||
#include <poll.h>
|
||||
#include "serial.h"
|
||||
#include "utils.h"
|
||||
|
||||
int serialOpen(const char* device)
|
||||
{
|
||||
int fd = -1;
|
||||
struct termios tios;
|
||||
|
||||
if((fd = open(device, O_RDWR | O_NOCTTY | O_NDELAY)) < 0) {
|
||||
fprintf(stderr, "could not open %s: %s\n", device, strerror(errno));
|
||||
goto failed;
|
||||
}
|
||||
bzero(&tios, sizeof(tios));
|
||||
tios.c_cflag = B115200 | CS8 | CLOCAL | CREAD;
|
||||
tios.c_iflag = IGNPAR;
|
||||
tios.c_oflag = 0;
|
||||
tios.c_lflag = ICANON;
|
||||
tios.c_cc[VMIN] = 1;
|
||||
cfmakeraw(&tios);
|
||||
if(tcflush(fd, TCIOFLUSH) < 0) {
|
||||
fprintf(stderr, "tcflush() failed: %s\n", strerror(errno));
|
||||
goto failed;
|
||||
}
|
||||
if(tcsetattr(fd, TCSAFLUSH, &tios) < 0) {
|
||||
fprintf(stderr, "tcsetattr() failed: %s\n", strerror(errno));
|
||||
goto failed;
|
||||
}
|
||||
if(tcflush(fd, TCIOFLUSH) < 0) {
|
||||
fprintf(stderr, "tcflush() failed: %s\n", strerror(errno));
|
||||
goto failed;
|
||||
}
|
||||
|
||||
return fd;
|
||||
|
||||
failed:
|
||||
if(fd >= 0)
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
void serialClose(int fd)
|
||||
{
|
||||
if(fd >= 0)
|
||||
close(fd);
|
||||
}
|
||||
|
||||
int serialPutC(int fd, char c)
|
||||
{
|
||||
if(write(fd, &c, sizeof(char)) != sizeof(char)) {
|
||||
if(errno == EAGAIN) {
|
||||
struct pollfd pollfd;
|
||||
int res;
|
||||
pollfd.fd = fd;
|
||||
pollfd.events = POLLOUT;
|
||||
pollfd.revents = 0;
|
||||
do {
|
||||
res = poll(&pollfd, 1, 250);
|
||||
} while((res < 0) && (errno == EINTR));
|
||||
if(res > 0) {
|
||||
if(write(fd, &c, sizeof(char)) != sizeof(char)) {
|
||||
fprintf(stderr, "write failed: %s\n", strerror(errno));
|
||||
return -1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else if(res == 0) {
|
||||
fprintf(stderr, "write failed: %s\n", strerror(errno));
|
||||
return -1;
|
||||
} else {
|
||||
fprintf(stderr, "poll failed: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "write failed: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int serialPutS(int fd, const char* str)
|
||||
{
|
||||
while(*str != '\0') {
|
||||
if(serialPutC(fd, *str++) < 0)
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int serialGetC(int fd, char* c, int timeout)
|
||||
{
|
||||
struct pollfd pollfd;
|
||||
int res;
|
||||
|
||||
pollfd.fd = fd;
|
||||
pollfd.events = POLLIN;
|
||||
pollfd.revents = 0;
|
||||
|
||||
do {
|
||||
res = poll(&pollfd, 1, timeout);
|
||||
} while((res < 0) && (errno == EINTR));
|
||||
|
||||
if(res > 0) {
|
||||
if(read(fd, c, sizeof(char)) != sizeof(char)) {
|
||||
fprintf(stderr, "read failed: %s\n", strerror(errno));
|
||||
return -1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else if(res == 0) {
|
||||
// timeout
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(stderr, "poll failed: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
int serialGetS(int fd, char* str, int len, int timeout)
|
||||
{
|
||||
int todo = len;
|
||||
uint64_t endTime = getTickCount() + timeout;
|
||||
|
||||
while(todo > 0) {
|
||||
uint64_t now = getTickCount();
|
||||
|
||||
if(now < endTime) {
|
||||
char c;
|
||||
if(serialGetC(fd, &c, endTime - now) < 0)
|
||||
return -1;
|
||||
//printf("[%02x]", c);
|
||||
*str++ = c;
|
||||
todo--;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (todo > 0) ? -1 : 0;
|
||||
}
|
||||
|
||||
int serialExpect(int fd, const char* str, int timeout)
|
||||
{
|
||||
int todo = strlen(str);
|
||||
uint64_t endTime = getTickCount() + timeout;
|
||||
|
||||
while(todo > 0) {
|
||||
uint64_t now = getTickCount();
|
||||
|
||||
if(now < endTime) {
|
||||
char c;
|
||||
if(serialGetC(fd, &c, endTime - now) < 0)
|
||||
return -1;
|
||||
//printf("[%02x]", c);
|
||||
if(c == *str++) {
|
||||
todo--;
|
||||
continue;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (todo > 0) ? -1 : 0;
|
||||
}
|
||||
#ifdef WINDOWS
|
||||
|
||||
#include <stdio.h>
|
||||
#include "serial.h"
|
||||
|
||||
static void printErr(const char* text, int err)
|
||||
{
|
||||
char errorBuf[256];
|
||||
char* buf = errorBuf;
|
||||
size_t max = sizeof(errorBuf) - 1;
|
||||
memset(errorBuf, 0x00, sizeof(errorBuf));
|
||||
|
||||
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), LANG_NEUTRAL, buf, (DWORD)max, NULL);
|
||||
fprintf(stderr, "%s: %s\n", text, errorBuf);
|
||||
fflush(stderr);
|
||||
}
|
||||
|
||||
HANDLE serialOpen(const char* dev)
|
||||
{
|
||||
char str[64];
|
||||
HANDLE fd;
|
||||
int err;
|
||||
|
||||
snprintf(str, sizeof(str), "\\\\.\\%s", dev);
|
||||
fd = CreateFileA(str, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
||||
if(fd == INVALID_HANDLE_VALUE) {
|
||||
err = GetLastError();
|
||||
if(err == ERROR_FILE_NOT_FOUND) {
|
||||
fprintf(stderr, "could not open %s: serial port does not exist\n", dev);
|
||||
} else {
|
||||
snprintf(str, sizeof(str), "could not open %s", dev);
|
||||
printErr(str, err);
|
||||
}
|
||||
goto failed;
|
||||
}
|
||||
|
||||
if(serialSetBaudrate(fd, 115200) < 0)
|
||||
goto failed;
|
||||
|
||||
return fd;
|
||||
|
||||
failed:
|
||||
if(fd != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(fd);
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
void serialClose(HANDLE fd)
|
||||
{
|
||||
if(fd != INVALID_HANDLE_VALUE)
|
||||
CloseHandle(fd);
|
||||
}
|
||||
|
||||
int serialSetBaudrate(HANDLE fd, int baudrate)
|
||||
{
|
||||
DCB dcb;
|
||||
|
||||
memset(&dcb, 0x00, sizeof(dcb));
|
||||
dcb.DCBlength = sizeof(dcb);
|
||||
if(!GetCommState(fd, &dcb)) {
|
||||
printErr("error getting serial port state", GetLastError());
|
||||
return -1;
|
||||
}
|
||||
dcb.BaudRate = baudrate;
|
||||
dcb.ByteSize = 8;
|
||||
dcb.StopBits = ONESTOPBIT;
|
||||
dcb.Parity = NOPARITY;
|
||||
dcb.fBinary = 1;
|
||||
dcb.fOutxCtsFlow = 0;
|
||||
dcb.fOutxDsrFlow = 0;
|
||||
dcb.fOutX = 0;
|
||||
dcb.fInX = 0;
|
||||
dcb.fNull = 0;
|
||||
dcb.fTXContinueOnXoff = 0;
|
||||
dcb.fDtrControl = DTR_CONTROL_DISABLE;
|
||||
dcb.fDsrSensitivity = 0;
|
||||
dcb.fRtsControl = RTS_CONTROL_DISABLE;
|
||||
if(!SetCommState(fd, &dcb)) {
|
||||
printErr("error setting serial port state", GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int serialPutC(HANDLE fd, uint8_t c)
|
||||
{
|
||||
DWORD bytesWritten;
|
||||
|
||||
if(!WriteFile(fd, &c, 1, &bytesWritten, NULL)) {
|
||||
printErr("error writing to serial port", GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int serialGetC(HANDLE fd, uint8_t* c, int timeout)
|
||||
{
|
||||
COMMTIMEOUTS timeouts;
|
||||
unsigned long res;
|
||||
COMSTAT comStat;
|
||||
DWORD errors;
|
||||
|
||||
if(!ClearCommError(fd, &errors, &comStat)) {
|
||||
printErr("could not reset comm errors", GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!GetCommTimeouts(fd, &timeouts)) {
|
||||
printErr("error getting comm timeouts", GetLastError());
|
||||
return -1;
|
||||
}
|
||||
timeouts.ReadIntervalTimeout = timeout;
|
||||
timeouts.ReadTotalTimeoutConstant = timeout;
|
||||
timeouts.ReadTotalTimeoutMultiplier = 10;
|
||||
if(!SetCommTimeouts(fd, &timeouts)) {
|
||||
printErr("error setting comm timeouts", GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(!ReadFile(fd, c, 1, &res, NULL)) {
|
||||
printErr("error reading from serial port", GetLastError());
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(res != 1)
|
||||
return -1;
|
||||
|
||||
return *c;
|
||||
}
|
||||
|
||||
#else // #ifdef WINDOWS
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <termios.h>
|
||||
#include <poll.h>
|
||||
#include "serial.h"
|
||||
|
||||
HANDLE serialOpen(const char* dev)
|
||||
{
|
||||
HANDLE fd;
|
||||
|
||||
if((fd = open(dev, O_RDWR | O_NOCTTY | O_NDELAY)) < 0) {
|
||||
fprintf(stderr, "could not open %s: %s\n", dev, strerror(errno));
|
||||
goto failed;
|
||||
}
|
||||
if(tcflush(fd, TCIOFLUSH) < 0) {
|
||||
fprintf(stderr, "tcflush() failed: %s\n", strerror(errno));
|
||||
goto failed;
|
||||
}
|
||||
if(serialSetBaudrate(fd, 115200) < 0)
|
||||
goto failed;
|
||||
|
||||
return fd;
|
||||
|
||||
failed:
|
||||
if(fd >= 0)
|
||||
close(fd);
|
||||
return INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
void serialClose(HANDLE fd)
|
||||
{
|
||||
if(fd != INVALID_HANDLE_VALUE)
|
||||
close(fd);
|
||||
}
|
||||
|
||||
int serialSetBaudrate(HANDLE fd, int baudrate)
|
||||
{
|
||||
struct termios tios;
|
||||
|
||||
bzero(&tios, sizeof(tios));
|
||||
switch(baudrate) {
|
||||
case 230400:
|
||||
tios.c_cflag = B230400;
|
||||
break;
|
||||
|
||||
case 460800:
|
||||
tios.c_cflag = B460800;
|
||||
break;
|
||||
|
||||
case 921600:
|
||||
tios.c_cflag = B921600;
|
||||
break;
|
||||
|
||||
default:
|
||||
tios.c_cflag = B115200;
|
||||
break;
|
||||
}
|
||||
tios.c_cflag |= CS8 | CLOCAL | CREAD;
|
||||
tios.c_iflag = IGNPAR;
|
||||
tios.c_oflag = 0;
|
||||
tios.c_lflag = ICANON;
|
||||
tios.c_cc[VMIN] = 1;
|
||||
cfmakeraw(&tios);
|
||||
|
||||
if(tcsetattr(fd, TCSAFLUSH, &tios) < 0) {
|
||||
fprintf(stderr, "tcsetattr() failed: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
if(tcflush(fd, TCIOFLUSH) < 0) {
|
||||
fprintf(stderr, "tcflush() failed: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int serialPutC(HANDLE fd, uint8_t c)
|
||||
{
|
||||
if(write(fd, &c, sizeof(uint8_t)) != sizeof(uint8_t)) {
|
||||
if(errno == EAGAIN) {
|
||||
struct pollfd pollfd;
|
||||
int res;
|
||||
pollfd.fd = fd;
|
||||
pollfd.events = POLLOUT;
|
||||
pollfd.revents = 0;
|
||||
do {
|
||||
res = poll(&pollfd, 1, 250);
|
||||
} while((res < 0) && (errno == EINTR));
|
||||
if(res > 0) {
|
||||
if(write(fd, &c, sizeof(char)) != sizeof(char)) {
|
||||
fprintf(stderr, "write failed: %s\n", strerror(errno));
|
||||
return -1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else if(res == 0) {
|
||||
fprintf(stderr, "write failed: %s\n", strerror(errno));
|
||||
return -1;
|
||||
} else {
|
||||
fprintf(stderr, "poll failed: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "write failed: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int serialGetC(HANDLE fd, uint8_t* c, int timeout)
|
||||
{
|
||||
struct pollfd pollfd;
|
||||
int res;
|
||||
|
||||
pollfd.fd = fd;
|
||||
pollfd.events = POLLIN;
|
||||
pollfd.revents = 0;
|
||||
|
||||
do {
|
||||
res = poll(&pollfd, 1, timeout);
|
||||
} while((res < 0) && (errno == EINTR));
|
||||
|
||||
if(res > 0) {
|
||||
if(read(fd, c, sizeof(char)) != sizeof(char)) {
|
||||
fprintf(stderr, "read failed: %s\n", strerror(errno));
|
||||
return -1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
} else if(res == 0) {
|
||||
// timeout
|
||||
return -1;
|
||||
}
|
||||
|
||||
fprintf(stderr, "poll failed: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
|
||||
#endif // #ifdef WINDOWS
|
||||
|
||||
int serialPutS(HANDLE fd, const char* str)
|
||||
{
|
||||
while(*str != '\0') {
|
||||
if(serialPutC(fd, *((uint8_t*)str)) < 0)
|
||||
return -1;
|
||||
str++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int serialGetS(HANDLE fd, char* str, int len, int timeout)
|
||||
{
|
||||
int todo = len;
|
||||
uint64_t endTime = getTickCount() + timeout;
|
||||
|
||||
while(todo > 0) {
|
||||
uint64_t now = getTickCount();
|
||||
|
||||
if(now < endTime) {
|
||||
uint8_t c;
|
||||
if(serialGetC(fd, &c, endTime - now) < 0)
|
||||
return -1;
|
||||
*((uint8_t*)str) = c;
|
||||
str++;
|
||||
todo--;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (todo > 0) ? -1 : 0;
|
||||
}
|
||||
|
||||
int serialExpect(HANDLE fd, const char* str, int timeout)
|
||||
{
|
||||
int todo = strlen(str);
|
||||
uint64_t endTime = getTickCount() + timeout;
|
||||
|
||||
while(todo > 0) {
|
||||
uint64_t now = getTickCount();
|
||||
|
||||
if(now < endTime) {
|
||||
uint8_t c;
|
||||
if(serialGetC(fd, &c, endTime - now) < 0)
|
||||
return -1;
|
||||
if(c == (uint8_t)(*str++)) {
|
||||
todo--;
|
||||
continue;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return (todo > 0) ? -1 : 0;
|
||||
}
|
||||
|
|
|
@ -1,14 +1,16 @@
|
|||
#ifndef INCLUDE_SERIAL_H
|
||||
#define INCLUDE_SERIAL_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
int serialOpen(const char* device);
|
||||
void serialClose(int fd);
|
||||
int serialPutC(int fd, char c);
|
||||
int serialPutS(int fd, const char* str);
|
||||
int serialGetC(int fd, char* c, int timeout);
|
||||
int serialGetS(int fd, char* str, int len, int timeout);
|
||||
int serialExpect(int fd, const char* str, int timeout);
|
||||
|
||||
#endif // INCLUDE_SERIAL_H
|
||||
#ifndef INCLUDE_SERIAL_H
|
||||
#define INCLUDE_SERIAL_H
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
HANDLE serialOpen(const char* dev);
|
||||
void serialClose(HANDLE fd);
|
||||
int serialSetBaudrate(HANDLE fd, int baudrate);
|
||||
int serialPutC(HANDLE fd, uint8_t c);
|
||||
int serialGetC(HANDLE fd, uint8_t* c, int timeout);
|
||||
|
||||
int serialPutS(HANDLE fd, const char* str);
|
||||
int serialGetS(HANDLE fd, char* str, int len, int timeout);
|
||||
int serialExpect(HANDLE fd, const char* str, int timeout);
|
||||
|
||||
#endif // INCLUDE_SERIAL_H
|
||||
|
|
|
@ -5,15 +5,28 @@
|
|||
#include <sys/stat.h>
|
||||
#include "utils.h"
|
||||
|
||||
#ifdef WINDOWS
|
||||
|
||||
#include <windows.h>
|
||||
|
||||
uint64_t getTickCount()
|
||||
{
|
||||
struct timespec t;
|
||||
|
||||
if(clock_gettime(CLOCK_MONOTONIC, &t) != 0)
|
||||
return 0;
|
||||
return (((uint64_t)t.tv_sec) * 1000) + (((uint64_t)t.tv_nsec) / 1000000);
|
||||
return GetTickCount();
|
||||
}
|
||||
|
||||
#else // WINDOWS
|
||||
|
||||
uint64_t getTickCount()
|
||||
{
|
||||
struct timespec t;
|
||||
|
||||
if(clock_gettime(CLOCK_MONOTONIC, &t) != 0)
|
||||
return 0;
|
||||
return (((uint64_t)t.tv_sec) * 1000) + (((uint64_t)t.tv_nsec) / 1000000);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void* loadFile(const char* filename, size_t* size)
|
||||
{
|
||||
void* result = NULL;
|
||||
|
@ -26,7 +39,11 @@ void* loadFile(const char* filename, size_t* size)
|
|||
}
|
||||
|
||||
if((result = calloc(1, statbuf.st_size)) == NULL) {
|
||||
#ifdef WINDOWS
|
||||
fprintf(stderr, "failed to allocate %u bytes of memory\n", (size_t)statbuf.st_size);
|
||||
#else
|
||||
fprintf(stderr, "failed to allocate %zu bytes of memory\n", (size_t)statbuf.st_size);
|
||||
#endif
|
||||
goto failed;
|
||||
}
|
||||
if((f = fopen(filename, "rb")) == NULL) {
|
||||
|
|
|
@ -6,4 +6,11 @@
|
|||
uint64_t getTickCount();
|
||||
void* loadFile(const char* filename, size_t* size);
|
||||
|
||||
#ifndef WINDOWS
|
||||
typedef int HANDLE;
|
||||
#define INVALID_HANDLE_VALUE (-1)
|
||||
#else
|
||||
#include <windows.h>
|
||||
#endif // WINDOWS
|
||||
|
||||
#endif // INCLUDE_UTILS_H
|
||||
|
|
Reference in New Issue