diff --git a/EXAMPLES/C/IR_RECEIVER/ir_hasher.c b/EXAMPLES/C/IR_RECEIVER/ir_hasher.c index ef154a1..4131b9b 100644 --- a/EXAMPLES/C/IR_RECEIVER/ir_hasher.c +++ b/EXAMPLES/C/IR_RECEIVER/ir_hasher.c @@ -118,6 +118,8 @@ Pi_Hasher_t *Pi_Hasher(int gpio, Pi_Hasher_CB_t callback, int timeout) gpioSetMode(gpio, PI_INPUT); gpioSetAlertFuncEx(gpio, _cb, hasher); + + return hasher; } void Pi_Hasher_cancel(Pi_Hasher_t *hasher) @@ -127,6 +129,8 @@ void Pi_Hasher_cancel(Pi_Hasher_t *hasher) gpioSetAlertFunc(hasher->gpio, 0); free(hasher); + + hasher = NULL; } } diff --git a/command.c b/command.c index b875d11..06fc914 100644 --- a/command.c +++ b/command.c @@ -26,7 +26,7 @@ For more information, please refer to */ /* -This version is for pigpio version 30+ +This version is for pigpio version 31+ */ #include @@ -494,6 +494,8 @@ static errInfo_t errInfo[]= {PI_BAD_DATABITS , "serial data bits not 1-32"}, {PI_MSG_TOOBIG , "socket/pipe message too big"}, {PI_BAD_MALLOC_MODE , "bad memory allocation mode"}, + {PI_TOO_MANY_PARTS , "too many I2C transaction parts"}, + {PI_BAD_I2C_PART , "a combined I2C transaction failed"}, }; diff --git a/pigpio.3 b/pigpio.3 index b766fb5..08c5dd9 100644 --- a/pigpio.3 +++ b/pigpio.3 @@ -2062,6 +2062,42 @@ No flags are currently defined. This parameter should be set to zero. Returns a handle (>=0) if OK, otherwise PI_BAD_I2C_BUS, PI_BAD_I2C_ADDR, PI_BAD_FLAGS, PI_NO_HANDLE, or PI_I2C_OPEN_FAILED. +.br + +.br +For the smbus commands the low level transactions are shown at the end +of the function description. The following abbreviations are used. + +.br + +.br + +.EX +S (1 bit) : Start bit +.br +P (1 bit) : Stop bit +.br +Rd/Wr (1 bit) : Read/Write bit. Rd equals 1, Wr equals 0. +.br +A, NA (1 bit) : Accept and not accept bit. +.br +.br +.br +Addr (7 bits): I2C 7 bit address. +.br +Comm (8 bits): Command byte, a data byte which often selects a register. +.br +Data (8 bits): A data byte. +.br +Count (8 bits): A data byte containing the length of a block operation. +.br + +.br +[..]: Data sent by the device. +.br + +.EE + .IP "\fBint i2cClose(unsigned handle)\fP" .IP "" 4 This closes the I2C device associated with the handle. @@ -2157,6 +2193,12 @@ PI_I2C_WRITE_FAILED. .br Quick command. smbus 2.0 5.5.1 +.EX +S Addr Rd/Wr [A] P +.br + +.EE + .IP "\fBint i2cWriteByte(unsigned handle, unsigned bVal)\fP" .IP "" 4 This sends a single byte to the device associated with handle. @@ -2184,6 +2226,12 @@ PI_I2C_WRITE_FAILED. .br Send byte. smbus 2.0 5.5.2 +.EX +S Addr Wr [A] Data [A] P +.br + +.EE + .IP "\fBint i2cReadByte(unsigned handle)\fP" .IP "" 4 This reads a single byte from the device associated with handle. @@ -2209,6 +2257,12 @@ or PI_I2C_READ_FAILED. .br Receive byte. smbus 2.0 5.5.3 +.EX +S Addr Rd [A] [Data] NA P +.br + +.EE + .IP "\fBint i2cWriteByteData(unsigned handle, unsigned i2cReg, unsigned bVal)\fP" .IP "" 4 This writes a single byte to the specified register of the device @@ -2239,6 +2293,12 @@ PI_I2C_WRITE_FAILED. .br Write byte. smbus 2.0 5.5.4 +.EX +S Addr Wr [A] Comm [A] Data [A] P +.br + +.EE + .IP "\fBint i2cWriteWordData(unsigned handle, unsigned i2cReg, unsigned wVal)\fP" .IP "" 4 This writes a single 16 bit word to the specified register of the device @@ -2269,6 +2329,12 @@ PI_I2C_WRITE_FAILED. .br Write word. smbus 2.0 5.5.4 +.EX +S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A] P +.br + +.EE + .IP "\fBint i2cReadByteData(unsigned handle, unsigned i2cReg)\fP" .IP "" 4 This reads a single byte from the specified register of the device @@ -2297,6 +2363,12 @@ PI_BAD_PARAM, or PI_I2C_READ_FAILED. .br Read byte. smbus 2.0 5.5.5 +.EX +S Addr Wr [A] Comm [A] S Addr Rd [A] [Data] NA P +.br + +.EE + .IP "\fBint i2cReadWordData(unsigned handle, unsigned i2cReg)\fP" .IP "" 4 This reads a single 16 bit word from the specified register of the device @@ -2325,6 +2397,12 @@ PI_BAD_PARAM, or PI_I2C_READ_FAILED. .br Read word. smbus 2.0 5.5.5 +.EX +S Addr Wr [A] Comm [A] S Addr Rd [A] [DataLow] A [DataHigh] NA P +.br + +.EE + .IP "\fBint i2cProcessCall(unsigned handle, unsigned i2cReg, unsigned wVal)\fP" .IP "" 4 This writes 16 bits of data to the specified register of the device @@ -2355,6 +2433,14 @@ PI_BAD_PARAM, or PI_I2C_READ_FAILED. .br Process call. smbus 2.0 5.5.6 +.EX +S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A] +.br + S Addr Rd [A] [DataLow] A [DataHigh] NA P +.br + +.EE + .IP "\fBint i2cWriteBlockData(unsigned handle, unsigned i2cReg, char *buf, unsigned count)\fP" .IP "" 4 This writes up to 32 bytes to the specified register of the device @@ -2387,6 +2473,12 @@ PI_I2C_WRITE_FAILED. .br Block write. smbus 2.0 5.5.7 +.EX +S Addr Wr [A] Comm [A] Count [A] Data [A] Data [A] ... [A] Data [A] P +.br + +.EE + .IP "\fBint i2cReadBlockData(unsigned handle, unsigned i2cReg, char *buf)\fP" .IP "" 4 This reads a block of up to 32 bytes from the specified register of @@ -2422,6 +2514,14 @@ PI_BAD_PARAM, or PI_I2C_READ_FAILED. .br Block read. smbus 2.0 5.5.7 +.EX +S Addr Wr [A] Comm [A] +.br + S Addr Rd [A] [Count] A [Data] A [Data] A ... A [Data] NA P +.br + +.EE + .IP "\fBint i2cBlockProcessCall(unsigned handle, unsigned i2cReg, char *buf, unsigned count)\fP" .IP "" 4 This writes data bytes to the specified register of the device @@ -2462,6 +2562,14 @@ bytes sent/received must be 32 or less. .br Block write-block read. smbus 2.0 5.5.8 +.EX +S Addr Wr [A] Comm [A] Count [A] Data [A] ... +.br + S Addr Rd [A] [Count] A [Data] ... A P +.br + +.EE + .IP "\fBint i2cReadI2CBlockData(unsigned handle, unsigned i2cReg, char *buf, unsigned count)\fP" .IP "" 4 This reads count bytes from the specified register of the device @@ -2489,6 +2597,18 @@ i2cReg: 0-255, the register to read Returns the number of bytes read (>0) if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or PI_I2C_READ_FAILED. +.br + +.br + +.EX +S Addr Wr [A] Comm [A] +.br + S Addr Rd [A] [Data] A [Data] A ... A [Data] NA P +.br + +.EE + .IP "\fBint i2cWriteI2CBlockData(unsigned handle, unsigned i2cReg, char *buf, unsigned count)\fP" .IP "" 4 This writes 1 to 32 bytes to the specified register of the device @@ -2516,6 +2636,16 @@ i2cReg: 0-255, the register to write Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or PI_I2C_WRITE_FAILED. +.br + +.br + +.EX +S Addr Wr [A] Comm [A] Data [A] Data [A] ... [A] Data [A] P +.br + +.EE + .IP "\fBint spiOpen(unsigned spiChan, unsigned spiBaud, unsigned spiFlags)\fP" .IP "" 4 This function returns a handle for the SPI device on the channel. @@ -5697,10 +5827,6 @@ The number of bits stored in a buffer. .br .IP "\fBnumBytes\fP" 0 - -.br - -.br The number of bytes used to store characters in a string. Depending on the number of bits per character there may be 1, 2, or 4 bytes per character. @@ -5710,21 +5836,20 @@ per character. .br .IP "\fBnumPar\fP: 0-10" 0 - -.br - -.br The number of parameters passed to a script. .br .br +.IP "\fBnumParts\fP" 0 +The number of parts in a combined I2C transaction. + +.br + +.br + .IP "\fBnumPulses\fP" 0 - -.br - -.br The number of pulses to be added to a waveform. .br @@ -5732,10 +5857,6 @@ The number of pulses to be added to a waveform. .br .IP "\fBoffset\fP" 0 - -.br - -.br The associated data starts this number of microseconds from the start of tghe waveform. @@ -5744,21 +5865,44 @@ tghe waveform. .br .IP "\fB*param\fP" 0 - -.br - -.br An array of script parameters. .br .br +.IP "\fB*parts\fP" 0 +An array of the part transactions which make up a combined I2C transaction. + +.br + +.br + +.IP "\fBpi_i2c_msg_t\fP" 0 + +.EX +typedef struct +.br +{ +.br + uint16_t addr; // slave address +.br + uint16_t flags; +.br + uint16_t len; // msg length +.br + uint8_t *buf; // pointer to msg data +.br +} pi_i2c_msg_t; +.br + +.EE + +.br + +.br + .IP "\fBport\fP: 1024-32000" 0 - -.br - -.br The port used to bind to the pigpio socket. Defaults to 8888. .br @@ -5766,10 +5910,6 @@ The port used to bind to the pigpio socket. Defaults to 8888. .br .IP "\fBpos\fP" 0 - -.br - -.br The position of an item. .br @@ -5777,10 +5917,6 @@ The position of an item. .br .IP "\fBprimaryChannel\fP: 0-14" 0 - -.br - -.br The DMA channel used to time the sampling of gpios and to time servo and PWM pulses. @@ -6902,6 +7038,12 @@ A 16-bit word value. #define PI_MSG_TOOBIG -103 // socket/pipe message too big .br #define PI_BAD_MALLOC_MODE -104 // bad memory allocation mode +.br +#define PI_TOO_MANY_PARTS -105 // too many I2C transaction parts +.br +#define PI_BAD_I2C_PART -106 // a combined I2C transaction failed +.br + .br .br diff --git a/pigpio.c b/pigpio.c index 0559a4b..29bf97a 100644 --- a/pigpio.c +++ b/pigpio.c @@ -25,7 +25,9 @@ OTHER DEALINGS IN THE SOFTWARE. For more information, please refer to */ -/* pigpio version 30 */ +/* pigpio version 31 */ + +/* include ------------------------------------------------------- */ #include #include @@ -178,7 +180,7 @@ bit 0 READ_LAST_NOT_SET_ERROR 6 C3 System Timer Compare 3 */ -/* --------------------------------------------------------------- */ +/* define -------------------------------------------------------- */ #define THOUSAND 1000 #define MILLION 1000000 @@ -283,14 +285,8 @@ bit 0 READ_LAST_NOT_SET_ERROR } \ while (0) -static volatile uint32_t piModel = 1; - #define PI_PERI_BUS 0x7E000000 -static volatile uint32_t pi_peri_phys = 0x20000000; -static volatile uint32_t pi_dram_bus = 0x40000000; -static volatile uint32_t pi_mem_flag = 0x00000004; - #define AUX_BASE (pi_peri_phys + 0x00215000) #define CLK_BASE (pi_peri_phys + 0x00101000) #define DMA_BASE (pi_peri_phys + 0x00007000) @@ -720,6 +716,7 @@ static volatile uint32_t pi_mem_flag = 0x00000004; #define SRX_BUF_SIZE 8192 #define PI_I2C_SLAVE 0x0703 +#define PI_I2C_RDWR 0x0707 #define PI_I2C_SMBUS 0x0720 #define PI_I2C_SMBUS_READ 1 @@ -758,7 +755,31 @@ static volatile uint32_t pi_mem_flag = 0x00000004; #define MB_UNLOCK_MEMORY_TAG 0x3000E #define MB_RELEASE_MEMORY_TAG 0x3000F -/* --------------------------------------------------------------- */ +#define PI_SCRIPT_FREE 0 +#define PI_SCRIPT_RESERVED 1 +#define PI_SCRIPT_IN_USE 2 +#define PI_SCRIPT_DYING 3 + +#define PI_SCRIPT_HALT 0 +#define PI_SCRIPT_RUN 1 +#define PI_SCRIPT_DELETE 2 + +#define PI_SCRIPT_STACK_SIZE 256 + +#define PI_SPI_FLAGS_CHANNEL(x) ((x&7)<<29) + +#define PI_SPI_FLAGS_GET_CHANNEL(x) (((x)>>29)&7) +#define PI_SPI_FLAGS_GET_BITLEN(x) (((x)>>16)&63) +#define PI_SPI_FLAGS_GET_RX_LSB(x) (((x)>>15)&1) +#define PI_SPI_FLAGS_GET_TX_LSB(x) (((x)>>14)&1) +#define PI_SPI_FLAGS_GET_3WREN(x) (((x)>>10)&15) +#define PI_SPI_FLAGS_GET_3WIRE(x) (((x)>>9)&1) +#define PI_SPI_FLAGS_GET_AUX_SPI(x) (((x)>>8)&1) +#define PI_SPI_FLAGS_GET_RESVD(x) (((x)>>5)&7) +#define PI_SPI_FLAGS_GET_CSPOLS(x) (((x)>>2)&7) +#define PI_SPI_FLAGS_GET_MODE(x) ((x)&3) + +/* typedef ------------------------------------------------------- */ typedef void (*callbk_t) (); @@ -830,17 +851,6 @@ typedef struct pthread_t pthId; } gpioTimer_t; -#define PI_SCRIPT_FREE 0 -#define PI_SCRIPT_RESERVED 1 -#define PI_SCRIPT_IN_USE 2 -#define PI_SCRIPT_DYING 3 - -#define PI_SCRIPT_HALT 0 -#define PI_SCRIPT_RUN 1 -#define PI_SCRIPT_DELETE 2 - -#define PI_SCRIPT_STACK_SIZE 256 - typedef struct { unsigned id; @@ -892,19 +902,6 @@ typedef struct uint32_t flags; } spiInfo_t; -#define PI_SPI_FLAGS_CHANNEL(x) ((x&7)<<29) - -#define PI_SPI_FLAGS_GET_CHANNEL(x) (((x)>>29)&7) -#define PI_SPI_FLAGS_GET_BITLEN(x) (((x)>>16)&63) -#define PI_SPI_FLAGS_GET_RX_LSB(x) (((x)>>15)&1) -#define PI_SPI_FLAGS_GET_TX_LSB(x) (((x)>>14)&1) -#define PI_SPI_FLAGS_GET_3WREN(x) (((x)>>10)&15) -#define PI_SPI_FLAGS_GET_3WIRE(x) (((x)>>9)&1) -#define PI_SPI_FLAGS_GET_AUX_SPI(x) (((x)>>8)&1) -#define PI_SPI_FLAGS_GET_RESVD(x) (((x)>>5)&7) -#define PI_SPI_FLAGS_GET_CSPOLS(x) (((x)>>2)&7) -#define PI_SPI_FLAGS_GET_MODE(x) ((x)&3) - typedef struct { uint32_t startTick; @@ -983,6 +980,12 @@ struct my_smbus_ioctl_data union my_smbus_data *data; }; +typedef struct +{ + pi_i2c_msg_t *msgs; /* pointers to pi_i2c_msgs */ + uint32_t nmsgs; /* number of pi_i2c_msgs */ +} my_i2c_rdwr_ioctl_data_t; + typedef struct { unsigned div; @@ -998,34 +1001,27 @@ typedef struct unsigned size; /* in bytes */ } DMAMem_t; -/* --------------------------------------------------------------- */ +/* global -------------------------------------------------------- */ /* initialise once then preserve */ -static volatile gpioCfg_t gpioCfg = -{ - PI_DEFAULT_BUFFER_MILLIS, - PI_DEFAULT_CLK_MICROS, - PI_DEFAULT_CLK_PERIPHERAL, - PI_DEFAULT_DMA_PRIMARY_CHANNEL, - PI_DEFAULT_DMA_SECONDARY_CHANNEL, - PI_DEFAULT_SOCKET_PORT, - PI_DEFAULT_IF_FLAGS, - 0, - 0, - PI_DEFAULT_MEM_ALLOC_MODE, -}; +static volatile uint32_t piModel = 1; +static volatile uint32_t pi_peri_phys = 0x20000000; +static volatile uint32_t pi_dram_bus = 0x40000000; +static volatile uint32_t pi_mem_flag = 0x0C; -static volatile gpioStats_t gpioStats; - -static int gpioMaskSet = 0; +static int libInitialised = 0; /* initialise every gpioInitialise */ static struct timespec libStarted; static int waveClockInited = 0; -/* initialse if not libInitialised */ +static volatile gpioStats_t gpioStats; + +static int gpioMaskSet = 0; + +/* initialise if not libInitialised */ static uint64_t gpioMask; @@ -1058,8 +1054,7 @@ static volatile uint32_t notifyBits = 0; static volatile uint32_t scriptBits = 0; static volatile int DMAstarted = 0; - -static int libInitialised = 0; +static volatile int terminating = 0; static int pthAlertRunning = 0; static int pthFifoRunning = 0; @@ -1085,19 +1080,7 @@ static gpioTimer_t gpioTimer [PI_MAX_TIMER+1]; static int pwmFreq[PWM_FREQS]; -/* no initialisation required */ - -static unsigned bufferBlocks; /* number of blocks in buffer */ -static unsigned bufferCycles; /* number of cycles */ - -static pthread_attr_t pthAttr; - -static pthread_t pthAlert; -static pthread_t pthFifo; -static pthread_t pthSocket; - -static gpioSample_t gpioSample[DATUMS]; -static gpioReport_t gpioReport[DATUMS]; +/* reset after gpioTerminated */ /* resources which must be released on gpioTerminate */ @@ -1133,7 +1116,70 @@ static volatile uint32_t * systReg = MAP_FAILED; static volatile uint32_t * dmaIn = MAP_FAILED; static volatile uint32_t * dmaOut = MAP_FAILED; -/* constant data */ +static uint32_t hw_clk_freq[3]; +static uint32_t hw_pwm_freq[2]; +static uint32_t hw_pwm_duty[2]; +static uint32_t hw_pwm_real_range[2]; + +static volatile gpioCfg_t gpioCfg = +{ + PI_DEFAULT_BUFFER_MILLIS, + PI_DEFAULT_CLK_MICROS, + PI_DEFAULT_CLK_PERIPHERAL, + PI_DEFAULT_DMA_PRIMARY_CHANNEL, + PI_DEFAULT_DMA_SECONDARY_CHANNEL, + PI_DEFAULT_SOCKET_PORT, + PI_DEFAULT_IF_FLAGS, + DBG_MIN_LEVEL, + 0, + PI_DEFAULT_MEM_ALLOC_MODE, +}; + +/* no initialisation required */ + +static unsigned bufferBlocks; /* number of blocks in buffer */ +static unsigned bufferCycles; /* number of cycles */ + +static pthread_t pthAlert; +static pthread_t pthFifo; +static pthread_t pthSocket; + +static gpioSample_t gpioSample[DATUMS]; +static gpioReport_t gpioReport[DATUMS]; + +static uint32_t spi_dummy; + +static unsigned old_mode_ce0; +static unsigned old_mode_ce1; +static unsigned old_mode_sclk; +static unsigned old_mode_miso; +static unsigned old_mode_mosi; + +static uint32_t old_spi_cs; +static uint32_t old_spi_clk; + +static unsigned old_mode_ace0; +static unsigned old_mode_ace1; +static unsigned old_mode_ace2; +static unsigned old_mode_asclk; +static unsigned old_mode_amiso; +static unsigned old_mode_amosi; + +static uint32_t old_spi_cntl0; +static uint32_t old_spi_cntl1; + +/* const --------------------------------------------------------- */ + +static const uint8_t clkDef[PI_MAX_GPIO + 1] = +{ + /* 0 1 2 3 4 5 6 7 8 9 */ + /* 0 */ 0x00, 0x00, 0x00, 0x00, 0x84, 0x94, 0xA4, 0x00, 0x00, 0x00, + /* 1 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 2 */ 0x82, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 3 */ 0x00, 0x00, 0x84, 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 4 */ 0x00, 0x00, 0x94, 0xA4, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 5 */ 0x00, 0x00, 0x00, 0x00, +}; /* 7 6 5 4 3 2 1 0 @@ -1156,17 +1202,15 @@ CC: 00 CLK0, 01 CLK1, 10 CLK2 gpio44 GPCLK1 ALT0 Compute module only (reserved for system use) */ -uint32_t hw_clk_freq[3]; - -uint8_t clkDef[PI_MAX_GPIO + 1] = +static const uint8_t PWMDef[PI_MAX_GPIO + 1] = { - /* 0 1 2 3 4 5 6 7 8 9 */ - /* 0 */ 0x00, 0x00, 0x00, 0x00, 0x84, 0x94, 0xA4, 0x00, 0x00, 0x00, - /* 1 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* 2 */ 0x82, 0x92, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* 3 */ 0x00, 0x00, 0x84, 0x00, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, - /* 4 */ 0x00, 0x00, 0x94, 0xA4, 0x94, 0x00, 0x00, 0x00, 0x00, 0x00, - /* 5 */ 0x00, 0x00, 0x00, 0x00, + /* 0 1 2 3 4 5 6 7 8 9 */ + /* 0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 1 */ 0x00, 0x00, 0x84, 0x94, 0x00, 0x00, 0x00, 0x00, 0x82, 0x92, + /* 2 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 3 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + /* 4 */ 0x84, 0x94, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x00, + /* 5 */ 0x00, 0x00, 0x85, 0x95, }; /* @@ -1188,21 +1232,6 @@ uint8_t clkDef[PI_MAX_GPIO + 1] = gpio53 pwm1 ALT1 */ -uint32_t hw_pwm_freq[2]; -uint32_t hw_pwm_duty[2]; -uint32_t hw_pwm_real_range[2]; - -uint8_t PWMDef[PI_MAX_GPIO + 1] = -{ - /* 0 1 2 3 4 5 6 7 8 9 */ - /* 0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* 1 */ 0x00, 0x00, 0x84, 0x94, 0x00, 0x00, 0x00, 0x00, 0x82, 0x92, - /* 2 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* 3 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* 4 */ 0x84, 0x94, 0x00, 0x00, 0x00, 0x94, 0x00, 0x00, 0x00, 0x00, - /* 5 */ 0x00, 0x00, 0x85, 0x95, -}; - static const clkCfg_t clkCfg[]= { /* valid servo */ @@ -1227,18 +1256,18 @@ static const uint16_t pwmRealRange[PWM_FREQS]= { 25, 50, 100, 125, 200, 250, 400, 500, 625, 800, 1000, 1250, 2000, 2500, 4000, 5000, 10000, 20000}; -/* ======================================================================= */ - -/* Internal prototypes. -*/ +/* prototype ----------------------------------------------------- */ static void intNotifyBits(void); + static void intScriptBits(void); + static int gpioNotifyOpenInBand(int fd); + static void initHWClk (int clkCtl, int clkDiv, int clkSrc, int divI, int divF, int MASH); -static void initDMAgo(volatile uint32_t *dmaAddr, uint32_t cbAddr); +static void initDMAgo(volatile uint32_t *dmaAddr, uint32_t cbAddr); /* ======================================================================= */ @@ -1444,7 +1473,7 @@ static void flushMemory(void) static void waitForDMAstarted(void) { - while (!DMAstarted) + while ((!DMAstarted) && (!terminating)) { if (piModel == 1) myGpioDelay(1000); else flushMemory(); @@ -1531,7 +1560,7 @@ static int myDoCommand(uint32_t *p, unsigned bufSize, char *buf) case PI_CMD_CF2: - /* a couple of extra precautions for untruested code */ + /* a couple of extra precautions for untrusted code */ if (p[2] > bufSize) p[2] = bufSize; res = gpioCustom2(p[1], buf, p[3], buf, p[2]); if (res > p[2]) res = p[2]; @@ -2110,7 +2139,7 @@ static void myGpioSetServo(unsigned gpio, int oldVal, int newVal) https://github.com/raspberrypi/firmware/wiki/Mailbox-property-interface */ -int mbCreate(void) +static int mbCreate(void) { /* <0 error */ @@ -2119,14 +2148,14 @@ int mbCreate(void) return mknod(MB_DEV, S_IFCHR|0600, makedev(MB_DEV_MAJOR, 0)); } -int mbOpen(void) +static int mbOpen(void) { /* <0 error */ return open(MB_DEV, 0); } -void mbClose(int fd) +static void mbClose(int fd) { close(fd); } @@ -2136,7 +2165,7 @@ static int mbProperty(int fd, void *buf) return ioctl(fd, MB_IOCTL, buf); } -unsigned mbAllocateMemory( +static unsigned mbAllocateMemory( int fd, unsigned size, unsigned align, unsigned flags) { int i=1; @@ -2157,7 +2186,7 @@ unsigned mbAllocateMemory( return p[5]; } -unsigned mbLockMemory(int fd, unsigned handle) +static unsigned mbLockMemory(int fd, unsigned handle) { int i=1; unsigned p[32]; @@ -2175,7 +2204,7 @@ unsigned mbLockMemory(int fd, unsigned handle) return p[5]; } -unsigned mbUnlockMemory(int fd, unsigned handle) +static unsigned mbUnlockMemory(int fd, unsigned handle) { int i=1; unsigned p[32]; @@ -2193,7 +2222,7 @@ unsigned mbUnlockMemory(int fd, unsigned handle) return p[5]; } -unsigned mbReleaseMemory(int fd, unsigned handle) +static unsigned mbReleaseMemory(int fd, unsigned handle) { int i=1; unsigned p[32]; @@ -2211,7 +2240,7 @@ unsigned mbReleaseMemory(int fd, unsigned handle) return p[5]; } -void *mbMapMem(unsigned base, unsigned size) +static void *mbMapMem(unsigned base, unsigned size) { void *mem = MAP_FAILED; @@ -2220,13 +2249,13 @@ void *mbMapMem(unsigned base, unsigned size) return mem; } -int mbUnmapMem(void *addr, unsigned size) +static int mbUnmapMem(void *addr, unsigned size) { /* 0 okay, -1 fail */ return munmap(addr, size); } -void mbDMAFree(DMAMem_t *DMAMemP) +static void mbDMAFree(DMAMem_t *DMAMemP) { if (DMAMemP->handle) { @@ -2237,7 +2266,7 @@ void mbDMAFree(DMAMem_t *DMAMemP) } } -int mbDMAAlloc(DMAMem_t *DMAMemP, unsigned size, uint32_t pi_mem_flag) +static int mbDMAAlloc(DMAMem_t *DMAMemP, unsigned size, uint32_t pi_mem_flag) { DMAMemP->size = size; @@ -3388,31 +3417,51 @@ int i2cClose(unsigned handle) return 0; } +int i2cTransaction(unsigned handle, pi_i2c_msg_t *parts, unsigned numParts) +{ + int retval, fd; + my_i2c_rdwr_ioctl_data_t rdwr; + + DBG(DBG_USER, "handle=%d", handle); + + CHECK_INITED; + + if (handle >= PI_I2C_SLOTS) + SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle); + + if (i2cInfo[handle].state != PI_I2C_OPENED) + SOFT_ERROR(PI_BAD_HANDLE, "bad handle (%d)", handle); + + if (parts == NULL) + SOFT_ERROR(PI_BAD_POINTER, "null parts"); + + if (numParts > PI_I2C_RDRW_IOCTL_MAX_MSGS) + SOFT_ERROR(PI_TOO_MANY_PARTS, "too many parts (%d)", numParts); + + fd = open(PI_I2C_COMBINED, O_RDWR); + + if (fd >= 0) + { + write(fd, "1", 1); + close(fd); + } + + rdwr.msgs = parts; + rdwr.nmsgs = numParts; + + retval = ioctl(i2cInfo[handle].fd, PI_I2C_RDWR, &rdwr); + + DBG(0, "i2cTransaction retval=%d", retval); + + if (retval >= 0) return retval; + else return PI_BAD_I2C_PART; +} + + /* ======================================================================= */ /*SPI */ -static uint32_t spi_dummy; /* only used to prevent warning */ - -static unsigned old_mode_ce0; -static unsigned old_mode_ce1; -static unsigned old_mode_sclk; -static unsigned old_mode_miso; -static unsigned old_mode_mosi; - -static uint32_t old_spi_cs; -static uint32_t old_spi_clk; - -static unsigned old_mode_ace0; -static unsigned old_mode_ace1; -static unsigned old_mode_ace2; -static unsigned old_mode_asclk; -static unsigned old_mode_amiso; -static unsigned old_mode_amosi; - -static uint32_t old_spi_cntl0; -static uint32_t old_spi_cntl1; - static uint32_t _spiTXBits(char *buf, int pos, int bitlen, int msbf) { uint32_t bits=0; @@ -3767,7 +3816,7 @@ static void spiInit(uint32_t flags) } } -void spiTerm(uint32_t flags) +static void spiTerm(uint32_t flags) { int resvd; @@ -6341,8 +6390,9 @@ static void initClearGlobals(void) notifyBits = 0; scriptBits = 0; - libInitialised = 0; - DMAstarted = 0; + libInitialised = 0; + DMAstarted = 0; + terminating = 0; pthAlertRunning = 0; pthFifoRunning = 0; @@ -6598,19 +6648,22 @@ static void initReleaseResources(void) int initInitialise(void) { - int i; + int rev, i; struct sockaddr_in server; char * portStr; unsigned port; struct sched_param param; + pthread_attr_t pthAttr; + + DBG(DBG_STARTUP, ""); + + if (libInitialised) return PIGPIO_VERSION; waveClockInited = 0; clock_gettime(CLOCK_REALTIME, &libStarted); - DBG(DBG_STARTUP, ""); - - if (libInitialised) return PIGPIO_VERSION; + rev = gpioHardwareRevision(); initClearGlobals(); @@ -6623,13 +6676,11 @@ int initInitialise(void) if (!gpioMaskSet) { - i = gpioHardwareRevision(); - - if (i == 0) gpioMask = PI_DEFAULT_UPDATE_MASK_R0; - else if (i == 17) gpioMask = PI_DEFAULT_UPDATE_MASK_COMPUTE; - else if (i < 4) gpioMask = PI_DEFAULT_UPDATE_MASK_R1; - else if (i < 16) gpioMask = PI_DEFAULT_UPDATE_MASK_R2; - else gpioMask = PI_DEFAULT_UPDATE_MASK_R3; + if (rev == 0) gpioMask = PI_DEFAULT_UPDATE_MASK_R0; + else if (rev == 17) gpioMask = PI_DEFAULT_UPDATE_MASK_COMPUTE; + else if (rev < 4) gpioMask = PI_DEFAULT_UPDATE_MASK_R1; + else if (rev < 16) gpioMask = PI_DEFAULT_UPDATE_MASK_R2; + else gpioMask = PI_DEFAULT_UPDATE_MASK_R3; gpioMaskSet = 1; } @@ -6937,10 +6988,14 @@ void gpioTerminate(void) DBG(DBG_USER, ""); - gpioMaskSet = 0; + terminating = 1; if (libInitialised) { + libInitialised = 0; + + gpioMaskSet = 0; + /* reset DMA */ DMAstarted = 0; @@ -6948,8 +7003,6 @@ void gpioTerminate(void) dmaIn[DMA_CS] = DMA_CHANNEL_RESET; dmaOut[DMA_CS] = DMA_CHANNEL_RESET; - libInitialised = 0; - if (gpioCfg.showStats) { fprintf(stderr, @@ -8573,6 +8626,8 @@ static int intGpioSetTimerFunc(unsigned id, int user, void *userdata) { + pthread_attr_t pthAttr; + DBG(DBG_INTERNAL, "id=%d millis=%d function=%08X user=%d userdata=%08X", id, millis, (uint32_t)f, user, (uint32_t)userdata); @@ -8587,6 +8642,14 @@ static int intGpioSetTimerFunc(unsigned id, if (!gpioTimer[id].running) { + if (pthread_attr_init(&pthAttr)) + SOFT_ERROR(PI_TIMER_FAILED, + "pthread_attr_init failed (%m)"); + + if (pthread_attr_setstacksize(&pthAttr, STACK_SIZE)) + SOFT_ERROR(PI_TIMER_FAILED, + "pthread_attr_setstacksize failed (%m)"); + if (pthread_create( &gpioTimer[id].pthId, &pthAttr, pthTimerTick, &gpioTimer[id])) SOFT_ERROR(PI_TIMER_FAILED, @@ -9377,7 +9440,7 @@ unsigned gpioHardwareRevision(void) chars = 4; pi_peri_phys = 0x20000000; pi_dram_bus = 0x40000000; - pi_mem_flag = 0x0c; + pi_mem_flag = 0x0C; } else if (strstr (buf, "ARMv7") != NULL) { diff --git a/pigpio.h b/pigpio.h index be6e813..69afbc8 100644 --- a/pigpio.h +++ b/pigpio.h @@ -31,7 +31,7 @@ For more information, please refer to #include #include -#define PIGPIO_VERSION 30 +#define PIGPIO_VERSION 31 /*TEXT @@ -319,6 +319,8 @@ OVERVIEW*/ #define PI_LOCKFILE "/var/run/pigpio.pid" +#define PI_I2C_COMBINED "/sys/module/i2c_bcm2708/parameters/combined" + #ifdef __cplusplus extern "C" { #endif @@ -399,6 +401,29 @@ uint32_t next; uint32_t pad[2]; } rawCbs_t; +/* max pi_i2c_msg_t per transaction */ + +#define PI_I2C_RDRW_IOCTL_MAX_MSGS 42 + +/* flags for pi_i2c_msg_t */ + +#define PI_I2C_M_WR 0x0000 /* write data */ +#define PI_I2C_M_RD 0x0001 /* read data */ +#define PI_I2C_M_TEN 0x0010 /* ten bit chip address */ +#define PI_I2C_M_RECV_LEN 0x0400 /* length will be first received byte */ +#define PI_I2C_M_NO_RD_ACK 0x0800 /* if I2C_FUNC_PROTOCOL_MANGLING */ +#define PI_I2C_M_IGNORE_NAK 0x1000 /* if I2C_FUNC_PROTOCOL_MANGLING */ +#define PI_I2C_M_REV_DIR_ADDR 0x2000 /* if I2C_FUNC_PROTOCOL_MANGLING */ +#define PI_I2C_M_NOSTART 0x4000 /* if I2C_FUNC_PROTOCOL_MANGLING */ + +typedef struct +{ + uint16_t addr; /* slave address */ + uint16_t flags; + uint16_t len; /* msg length */ + uint8_t *buf; /* pointer to msg data */ +} pi_i2c_msg_t; + typedef void (*gpioAlertFunc_t) (int gpio, int level, uint32_t tick); @@ -1699,7 +1724,6 @@ user_gpio: 0-31, previously opened with [*gpioSerialReadOpen*] Returns 0 if OK, otherwise PI_BAD_USER_GPIO, or PI_NOT_SERIAL_GPIO. D*/ - /*F*/ int i2cOpen(unsigned i2cBus, unsigned i2cAddr, unsigned i2cFlags); /*D @@ -1715,6 +1739,22 @@ No flags are currently defined. This parameter should be set to zero. Returns a handle (>=0) if OK, otherwise PI_BAD_I2C_BUS, PI_BAD_I2C_ADDR, PI_BAD_FLAGS, PI_NO_HANDLE, or PI_I2C_OPEN_FAILED. + +For the smbus commands the low level transactions are shown at the end +of the function description. The following abbreviations are used. + +. . +S (1 bit) : Start bit +P (1 bit) : Stop bit +Rd/Wr (1 bit) : Read/Write bit. Rd equals 1, Wr equals 0. +A, NA (1 bit) : Accept and not accept bit. +Addr (7 bits): I2C 7 bit address. +Comm (8 bits): Command byte, a data byte which often selects a register. +Data (8 bits): A data byte. +Count (8 bits): A data byte containing the length of a block operation. + +[..]: Data sent by the device. +. . D*/ @@ -1762,6 +1802,10 @@ Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or PI_I2C_WRITE_FAILED. D*/ +int i2cTransaction(unsigned handle, pi_i2c_msg_t *parts, unsigned numParts); +/* +This performs a combined I2C transction made up of count parts. +*/ /*F*/ int i2cWriteQuick(unsigned handle, unsigned bit); @@ -1778,6 +1822,9 @@ Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or PI_I2C_WRITE_FAILED. Quick command. smbus 2.0 5.5.1 +. . +S Addr Rd/Wr [A] P +. . D*/ @@ -1795,6 +1842,9 @@ Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or PI_I2C_WRITE_FAILED. Send byte. smbus 2.0 5.5.2 +. . +S Addr Wr [A] Data [A] P +. . D*/ @@ -1811,6 +1861,9 @@ Returns the byte read (>=0) if OK, otherwise PI_BAD_HANDLE, or PI_I2C_READ_FAILED. Receive byte. smbus 2.0 5.5.3 +. . +S Addr Rd [A] [Data] NA P +. . D*/ @@ -1830,6 +1883,9 @@ Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or PI_I2C_WRITE_FAILED. Write byte. smbus 2.0 5.5.4 +. . +S Addr Wr [A] Comm [A] Data [A] P +. . D*/ @@ -1849,6 +1905,9 @@ Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or PI_I2C_WRITE_FAILED. Write word. smbus 2.0 5.5.4 +. . +S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A] P +. . D*/ @@ -1867,6 +1926,9 @@ Returns the byte read (>=0) if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or PI_I2C_READ_FAILED. Read byte. smbus 2.0 5.5.5 +. . +S Addr Wr [A] Comm [A] S Addr Rd [A] [Data] NA P +. . D*/ @@ -1885,6 +1947,9 @@ Returns the word read (>=0) if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or PI_I2C_READ_FAILED. Read word. smbus 2.0 5.5.5 +. . +S Addr Wr [A] Comm [A] S Addr Rd [A] [DataLow] A [DataHigh] NA P +. . D*/ @@ -1904,6 +1969,10 @@ Returns the word read (>=0) if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or PI_I2C_READ_FAILED. Process call. smbus 2.0 5.5.6 +. . +S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A] + S Addr Rd [A] [DataLow] A [DataHigh] NA P +. . D*/ @@ -1925,6 +1994,9 @@ Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or PI_I2C_WRITE_FAILED. Block write. smbus 2.0 5.5.7 +. . +S Addr Wr [A] Comm [A] Count [A] Data [A] Data [A] ... [A] Data [A] P +. . D*/ @@ -1946,6 +2018,10 @@ Returns the number of bytes read (>=0) if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or PI_I2C_READ_FAILED. Block read. smbus 2.0 5.5.7 +. . +S Addr Wr [A] Comm [A] + S Addr Rd [A] [Count] A [Data] A [Data] A ... A [Data] NA P +. . D*/ @@ -1972,6 +2048,10 @@ sent and a minimum of 1 byte may be received. The total number of bytes sent/received must be 32 or less. Block write-block read. smbus 2.0 5.5.8 +. . +S Addr Wr [A] Comm [A] Count [A] Data [A] ... + S Addr Rd [A] [Count] A [Data] ... A P +. . D*/ @@ -1991,6 +2071,11 @@ i2cReg: 0-255, the register to read Returns the number of bytes read (>0) if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or PI_I2C_READ_FAILED. + +. . +S Addr Wr [A] Comm [A] + S Addr Rd [A] [Data] A [Data] A ... A [Data] NA P +. . D*/ @@ -2010,6 +2095,10 @@ i2cReg: 0-255, the register to write Returns 0 if OK, otherwise PI_BAD_HANDLE, PI_BAD_PARAM, or PI_I2C_WRITE_FAILED. + +. . +S Addr Wr [A] Comm [A] Data [A] Data [A] ... [A] Data [A] P +. . D*/ @@ -3742,38 +3831,47 @@ numBits:: The number of bits stored in a buffer. numBytes:: - The number of bytes used to store characters in a string. Depending on the number of bits per character there may be 1, 2, or 4 bytes per character. numPar:: 0-10 - The number of parameters passed to a script. -numPulses:: +numParts:: +The number of parts in a combined I2C transaction. +numPulses:: The number of pulses to be added to a waveform. offset:: - The associated data starts this number of microseconds from the start of tghe waveform. *param:: - An array of script parameters. -port:: 1024-32000 +*parts:: +An array of the part transactions which make up a combined I2C transaction. +pi_i2c_msg_t:: +. . +typedef struct +{ + uint16_t addr; // slave address + uint16_t flags; + uint16_t len; // msg length + uint8_t *buf; // pointer to msg data +} pi_i2c_msg_t; +. . + +port:: 1024-32000 The port used to bind to the pigpio socket. Defaults to 8888. pos:: - The position of an item. primaryChannel:: 0-14 - The DMA channel used to time the sampling of gpios and to time servo and PWM pulses. @@ -4323,6 +4421,9 @@ after this command is issued. #define PI_BAD_STOPBITS -102 // serial (half) stop bits not 2-8 #define PI_MSG_TOOBIG -103 // socket/pipe message too big #define PI_BAD_MALLOC_MODE -104 // bad memory allocation mode +#define PI_TOO_MANY_PARTS -105 // too many I2C transaction parts +#define PI_BAD_I2C_PART -106 // a combined I2C transaction failed + #define PI_PIGIF_ERR_0 -2000 #define PI_PIGIF_ERR_99 -2099