code:
#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <getopt.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>
#define WHO_AM_I_REG 0x75
#define WHO_AM_I_EXPECTED_VAL 0x91
#define ACCEL_CONFIG_REG 0x28
#define GYRO_CONFIG_REG 0x27
#define USING_WRITE_FUNC 0
static const char *device = "/dev/spidev0.0";
static uint8_t mode = SPI_MODE_1;
static uint8_t bits = 8;
static uint32_t spi_speed_hz = 1000;
static int transfer_len = 4 ;
static int fd;
/*************************************************************************//**
* Initializes the SPI functionality
*****************************************************************************/
int payload_board_spi_init(void)
{
int ret = 0;
fd = open(device, O_RDWR);
if (fd < 0){
perror("can't open device");
return -1;
}
//spi mode
//mode = SPI_MODE_1;
ret = ioctl(fd, SPI_IOC_WR_MODE, &mode);
if (ret < 0){
perror("can't set spi mode");
return ret;
}
//bits per word
ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
if (ret < 0) {
perror("SPI_IOC_MESSAGE");
return ret ;
}
//max speed hz
ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &spi_speed_hz);
if (ret < 0){
perror("can't set max speed hz");
return ret;
}
return 0;
// There are other IOCTL's which are not relevant to this
// specific slave device.
}
/*************************************************************************//**
* Reads one byte from the SPI slave device register.
*
* @param reg_addr is the address of the register to be read from.
* @param read_buffer is the pointer to the variable where the read data byte
* will be stored.
*
* @return 0 if success. else -1.
*****************************************************************************/
static int icg_20660_reg_read(uint8_t reg_addr, uint8_t* read_buffer)
{
struct spi_ioc_transfer tr;
int ret;
uint8_t wr_data[2] = {0, 0};
uint8_t rd_data[2] = {0, 0};
memset(&tr, 0, sizeof(tr)); //clear any invalid data. This is required.
tr.tx_buf = (unsigned long)wr_data;
tr.rx_buf = (unsigned long)rd_data;
tr.len = transfer_len, //one full read/write cycle consists of 16 bits data transfer.
//set Bit7 to tell slave device that we are reading.
wr_data[0] = (reg_addr|0x80);
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
if (ret < 1){
perror("[PAYLOAD IMU] can't send spi message");
return -1;
}else{
// we have read 2 bytes of data. But first byte is junk.
read_buffer[0] = rd_data[1];
return 0;
}
}
/*************************************************************************//**
* Write one byte to the SPI slave device's register.
*
* @param reg_addr is the address of the register to be written to.
* @param write_data is the 8 bit data to be written.
*
* @return 0 if success. else -1.
*****************************************************************************/
int icg_20660_reg_write(uint8_t reg_addr, uint8_t write_data)
{
struct spi_ioc_transfer tr;
int ret;
uint8_t wr_data[4] = {0};
uint8_t rd_data[4] = {0};
memset(&tr, 0, sizeof(tr)); //clear any invalid data. This is required.
tr.tx_buf = (unsigned long)wr_data;
tr.rx_buf = (unsigned long)rd_data;
tr.len = transfer_len, //one full cycle consists of 16 bits data transfer.
//reset Bit7 to tell slave device that we are writting.
wr_data[0] = reg_addr;
wr_data[1] = write_data;
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
printf("\nwrite buff: %X %X %X %X \n",wr_data[0],wr_data[1],wr_data[2],wr_data[3]);
printf("read buff : %X %X %X %X \n",rd_data[0],rd_data[1],rd_data[2],rd_data[3]);
if (ret < 1){
perror("[ERROR][PAYLOAD IMU] can't send spi message");
return -1;
}else{
return 0;
}
}
/*************************************************************************//**
* starts the payload board SPI interface test.
*
* @param response_buffer is the pointer to the buffer where the TLV
* response from the test function will be stored.
*
* @return the length of the received TLV string
*****************************************************************************/
int cmd_pld_imu_spi_test(char* response_buffer)
{
uint8_t val_read = 0;
int ret;
char* pass_string = "04000300140000010004PASS\r\n";
char* fail_string = "04000300320000010004FAIL0000020008buserror\r\n";
ret = icg_20660_reg_read(WHO_AM_I_REG, &val_read);
if(ret<0){
strcpy(response_buffer, fail_string);
printf("[ERROR][PAYLOAD IMU] read error\n");
return strlen(response_buffer);
}
if(val_read == WHO_AM_I_EXPECTED_VAL){
strcpy(response_buffer, pass_string);
return strlen(response_buffer);
}else{
strcpy(response_buffer, fail_string);
printf("[ERROR][PAYLOAD IMU] unexpected who_am_i value: 0x%x\n", val_read);
return strlen(response_buffer);
}
}
int main(void)
{
printf("\nStart\n");
int ret;
ret = payload_board_spi_init();
printf("\nret = %d",ret);
int i =10;
while(i>0)
{
ret = icg_20660_reg_write(0b11,0xff);
printf("\nret = %d",ret);
sleep(1);
ret = icg_20660_reg_write(0b11,0xa5);
printf("\nret = %d",ret);
i--;
}
close(fd);
}
timing diagram
problem:
On testing ADS8668 using the above code, I got an unexpected behaviour that the value written to the 0x2 register is not getting after the 16th clock. here I'm using spi mode 1 but the data shifted in the falling edge of the 16th clock instead of the leading edge of 17 the clock. i thought the problem occurs. please help me to avoid unexpected result