513 lines
11 KiB
C
Executable File
513 lines
11 KiB
C
Executable File
|
|
|
|
#include <stdint.h>
|
|
#include <unistd.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <linux/types.h>
|
|
#include <linux/spi/spidev.h>
|
|
#include <sys/ioctl.h>
|
|
#include <string.h>
|
|
#include <fcntl.h>
|
|
|
|
#include "../inc/ispi.h"
|
|
#include "../inc/isys_com.h"
|
|
|
|
|
|
|
|
static int openSpiDev(char *pDevName)
|
|
{
|
|
int fd ;
|
|
int ret ;
|
|
|
|
if(pDevName == NULL)
|
|
return -2;
|
|
|
|
if(!access(pDevName, F_OK))
|
|
{
|
|
fd = open(pDevName, O_RDWR);
|
|
if(fd < 0)
|
|
{
|
|
log_printf(LOG_ERR,I_NOUSED,"open error %s \n",pDevName);
|
|
return -1;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
//spidev_fd = fd;
|
|
|
|
return (fd);
|
|
}
|
|
|
|
static int initSpiDev(int fd, u8 mode, u8 bits, int speed)
|
|
{
|
|
int err;
|
|
|
|
err = ioctl(fd, SPI_IOC_WR_MODE, &mode);
|
|
if (err == -1)
|
|
{
|
|
log_printf(LOG_ERR,I_NOUSED,"can't set spi SPI_IOC_WR_MODE\n");
|
|
return err;
|
|
}
|
|
|
|
err = ioctl(fd, SPI_IOC_RD_MODE, &mode);
|
|
if (err == -1)
|
|
{
|
|
log_printf(LOG_ERR,I_NOUSED,"can't set spi SPI_IOC_RD_MODE\n");
|
|
return err;
|
|
}
|
|
|
|
err = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
|
|
if (err == -1)
|
|
{
|
|
log_printf(LOG_ERR,I_NOUSED,"can't set spi SPI_IOC_WR_BITS_PER_WORD\n");
|
|
return err;
|
|
}
|
|
|
|
err = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits);
|
|
if (err == -1)
|
|
{
|
|
log_printf(LOG_ERR,I_NOUSED,"can't set spi SPI_IOC_RD_BITS_PER_WORD\n");
|
|
return err;
|
|
}
|
|
|
|
// err = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
|
|
// if (err == -1)
|
|
// {
|
|
// printf("can't set spi SPI_IOC_WR_MAX_SPEED_HZ\n");
|
|
// return err;
|
|
// }
|
|
|
|
err = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed);
|
|
if (err == -1)
|
|
{
|
|
log_printf(LOG_ERR,I_NOUSED,"can't set spi SPI_IOC_RD_MAX_SPEED_HZ\n");
|
|
return err;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
static int transfer_r(int fd, u16 addr, u8 *pdata)
|
|
{
|
|
int ret;
|
|
uint8_t rx[3] = {0};
|
|
uint8_t tx[3] = {0};
|
|
u16 writeInstruct = 0;
|
|
|
|
if(fd < 0 || pdata == NULL)
|
|
return -1;
|
|
|
|
writeInstruct= (addr|0x8000);
|
|
tx[0]= writeInstruct>>8;
|
|
tx[1]= (u8)(writeInstruct&0xff);
|
|
|
|
struct spi_ioc_transfer tr = {
|
|
.tx_buf = (unsigned long)tx,
|
|
.rx_buf = (unsigned long)rx,
|
|
.len = ARRAY_SIZE(tx),
|
|
.delay_usecs = SPI_DELAY,
|
|
.speed_hz = SPEED,
|
|
.bits_per_word = 8,
|
|
};
|
|
|
|
|
|
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
|
|
if (ret < 1)
|
|
{
|
|
log_printf(LOG_ERR,I_NOUSED,"can't send spi message,for read %d\n",fd);
|
|
return -1;
|
|
}
|
|
|
|
//printf("addr=%.2x rd: ",addr);
|
|
/*printf("r Tx:");
|
|
for (ret = 0; ret < ARRAY_SIZE(tx); ret++)
|
|
{
|
|
printf("%.2X ", tx[ret]);
|
|
}
|
|
|
|
printf("r Rx:");
|
|
for (ret = 0; ret < ARRAY_SIZE(tx); ret++)
|
|
{
|
|
printf("%.2X ", rx[ret]);
|
|
}
|
|
printf("\n");
|
|
*/
|
|
*pdata = rx[2];
|
|
return 0;
|
|
}
|
|
|
|
static int transfer_w(int fd, u32 addr, u8 data)
|
|
{
|
|
int ret;
|
|
uint8_t rx[3] = {0};
|
|
uint8_t tx[3] = {0};
|
|
|
|
if(fd < 0)
|
|
return -1;
|
|
|
|
addr &=~0x8000;
|
|
tx[0] =(u8)((addr & 0xFF00) >> 8);
|
|
tx[1] =(u8)(addr & 0x00FF);
|
|
tx[2] = data;
|
|
|
|
struct spi_ioc_transfer tr = {
|
|
.tx_buf = (unsigned long)tx,
|
|
.rx_buf = (unsigned long)rx,
|
|
.len = ARRAY_SIZE(tx),
|
|
.delay_usecs = SPI_DELAY,
|
|
.speed_hz = SPEED,
|
|
.bits_per_word = 8,
|
|
};
|
|
|
|
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
|
|
if (ret < 1)
|
|
{
|
|
log_printf(LOG_ERR,I_NOUSED,"can't send spi message, for write fd %d\n",fd);
|
|
return -1;
|
|
}
|
|
|
|
//printf("[sub]addr=%.2x w-rd: ",addr);
|
|
|
|
/*printf("w Tx:");
|
|
for (ret = 0; ret < ARRAY_SIZE(tx); ret++)
|
|
{
|
|
printf(" %.2X ", tx[ret]);
|
|
}
|
|
printf("\n");
|
|
|
|
printf("w Rx:\n");
|
|
for (ret = 0; ret < ARRAY_SIZE(tx); ret++)
|
|
{
|
|
printf(" %.2X ", rx[ret]);
|
|
}
|
|
printf("\n");*/
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 4 wrie need tx and rx len : 3 ,return: ff xx xx*/
|
|
int spi_r(int fd, u8 addr, u16 *pdata)
|
|
{
|
|
int ret;
|
|
uint8_t rx[3] = {0};
|
|
uint8_t tx[3] = {0};
|
|
|
|
if(fd < 0)
|
|
return -1;
|
|
|
|
tx[0] = (u8)(addr | 0x80);
|
|
tx[1] = 0x00;
|
|
tx[2] = 0x00;
|
|
|
|
struct spi_ioc_transfer tr = {
|
|
.tx_buf = (unsigned long)tx,
|
|
.rx_buf = (unsigned long)rx,
|
|
.len = ARRAY_SIZE(tx),
|
|
.delay_usecs = SPI_DELAY,
|
|
.speed_hz = SPEED,
|
|
.bits_per_word = 8,
|
|
};
|
|
|
|
ret = ioctl(fd, SPI_IOC_MESSAGE(HALF_DUPLEX), &tr);
|
|
if (ret < 1){
|
|
log_printf(LOG_ERR,I_NOUSED,"can't send spi message, for write fd %d\n",fd);
|
|
return -1;
|
|
}
|
|
|
|
*pdata = (rx[1]<<8) + rx[2];
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
/* 4 wrie need tx and rx len : 3 ,return: ff xx xx*/
|
|
int spi_r_addr16_data8(int fd, u16 addr, u8 *pdata)
|
|
{
|
|
int ret;
|
|
uint8_t rx[3] = {0};
|
|
uint8_t tx[3] = {0};
|
|
|
|
if(fd < 0)
|
|
return -1;
|
|
|
|
tx[0] = (u8)((addr>>8)&0xff | 0x80);
|
|
tx[1] = (u8)( addr&0xff);
|
|
tx[2] = 0x00;
|
|
|
|
struct spi_ioc_transfer tr = {
|
|
.tx_buf = (unsigned long)tx,
|
|
.rx_buf = (unsigned long)rx,
|
|
.len = ARRAY_SIZE(tx),
|
|
.delay_usecs = SPI_DELAY,
|
|
.speed_hz = SPEED,
|
|
.bits_per_word = 8,
|
|
};
|
|
|
|
ret = ioctl(fd, SPI_IOC_MESSAGE(HALF_DUPLEX), &tr);
|
|
if (ret < 1){
|
|
log_printf(LOG_ERR,I_NOUSED,"can't send spi message, for write fd %d\n",fd);
|
|
return -1;
|
|
}
|
|
|
|
*pdata = rx[2];
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
uint8_t spi_rx_buff[35] = {0};
|
|
uint8_t spi_tx_buff[35] = {0};
|
|
|
|
int spi_transfer_big_block(int spi_fd, uint8 *pdata, int bytelen)
|
|
{
|
|
int ret;
|
|
|
|
if(spi_fd < 0)
|
|
return -1;
|
|
|
|
if(bytelen>SPI_BUFF_MAX)
|
|
printf("[%s,%d] buff full!! %d > 4KB\n", __func__,__LINE__, bytelen);
|
|
|
|
memset(spi_tx_buff, 0, sizeof(spi_tx_buff));
|
|
memcpy(spi_tx_buff, pdata, bytelen);
|
|
|
|
struct spi_ioc_transfer tr = {
|
|
.tx_buf = (unsigned long)spi_tx_buff,
|
|
.rx_buf = (unsigned long)spi_rx_buff,
|
|
.len = bytelen,//ARRAY_SIZE(spi_tx_buff),
|
|
.delay_usecs = SPI_DELAY,
|
|
.speed_hz = SPEED,
|
|
.bits_per_word = 8,
|
|
};
|
|
|
|
#if 1
|
|
/* SPI_IOC_MESSAGE(n) -- [n] means numbers of struct spi_ioc_transfer, so 1. */
|
|
ret = ioctl(spi_fd, SPI_IOC_MESSAGE(1), &tr);
|
|
if (ret < 1) {
|
|
printf(" [%s,%d]send spi msg err, len=%d ret=%d rx[0]=%d tx[0]=%d (%d)\n", __func__,__LINE__, bytelen,ret, spi_rx_buff[0],spi_tx_buff[0], tr.len);
|
|
//pabort("can't send spi message");
|
|
return -1;
|
|
}
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
int spi_receiver_big_block(int spi_fd, uint8 *pdata, int bytelen)
|
|
{
|
|
int ret;
|
|
|
|
if(spi_fd < 0)
|
|
return -1;
|
|
|
|
if(bytelen>SPI_BUFF_MAX)
|
|
printf("[%s,%d] buff full!! %d > 4KB\n", __func__,__LINE__, bytelen);
|
|
|
|
memset(spi_tx_buff, 0, sizeof(spi_tx_buff));
|
|
memcpy(spi_tx_buff, pdata, 3);
|
|
|
|
memset(spi_rx_buff, 0, sizeof(spi_rx_buff));
|
|
|
|
struct spi_ioc_transfer tr = {
|
|
.tx_buf = (unsigned long)spi_tx_buff,
|
|
.rx_buf = (unsigned long)spi_rx_buff,
|
|
.len = bytelen,//ARRAY_SIZE(spi_tx_buff),
|
|
.delay_usecs = SPI_DELAY,
|
|
.speed_hz = SPEED,
|
|
.bits_per_word = 8,
|
|
};
|
|
|
|
#if 1
|
|
/* SPI_IOC_MESSAGE(n) -- [n] means numbers of struct spi_ioc_transfer, so 1. */
|
|
ret = ioctl(spi_fd, SPI_IOC_MESSAGE(1), &tr);
|
|
if (ret < 1) {
|
|
printf(" [%s,%d]send spi msg err, len=%d ret=%d rx[0]=%d tx[0]=%d (%d)\n", __func__,__LINE__, bytelen,ret, spi_rx_buff[0],spi_tx_buff[0], tr.len);
|
|
return -1;
|
|
}
|
|
|
|
//printf(" rxbuf[3-4]= 0x%02x 0x%02x\n",spi_rx_buff[3], spi_rx_buff[4]);
|
|
memcpy(pdata, spi_rx_buff, bytelen);
|
|
#endif
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int spi_w(int fd, u8 addr, uint16_t u16_data)
|
|
{
|
|
int ret;
|
|
uint8_t rx[3] = {0};
|
|
uint8_t tx[3] = {0};
|
|
uint32 u32addr = (uint32)addr << 16;
|
|
|
|
if(fd < 0)
|
|
return -1;
|
|
|
|
u32addr &= ~0x800000;
|
|
u32addr |= u16_data;
|
|
|
|
tx[0] = (u8)((u32addr >> 16) & 0xFF);
|
|
tx[1] = (u8)((u32addr >> 8) & 0xFF);
|
|
tx[2] = (u8)((u32addr >> 0) & 0xFF);
|
|
|
|
struct spi_ioc_transfer tr = {
|
|
.tx_buf = (unsigned long)tx,
|
|
.rx_buf = (unsigned long)rx,
|
|
.len = ARRAY_SIZE(tx),
|
|
.delay_usecs = SPI_DELAY,
|
|
.speed_hz = SPEED,
|
|
.bits_per_word = 8,
|
|
};
|
|
|
|
ret = ioctl(fd, SPI_IOC_MESSAGE(HALF_DUPLEX), &tr);
|
|
if (ret < 1){
|
|
log_printf(LOG_ERR,I_NOUSED,"can't send spi message, for write fd %d\n",fd);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
int spi_w_addr16_data8(int fd, u16 addr, uint8_t data)
|
|
{
|
|
int ret;
|
|
uint8_t rx[3] = {0};
|
|
uint8_t tx[3] = {0};
|
|
uint32 u16addr=0;
|
|
|
|
if(fd < 0)
|
|
return -1;
|
|
|
|
u16addr &= ~0x8000;
|
|
u16addr |= (addr&0x7fff);
|
|
|
|
tx[0] = (u8)((u16addr >> 8) & 0xFF);
|
|
tx[1] = (u8)((u16addr) & 0xFF);
|
|
tx[2] = (u8)((data) & 0xFF);
|
|
|
|
struct spi_ioc_transfer tr = {
|
|
.tx_buf = (unsigned long)tx,
|
|
.rx_buf = (unsigned long)rx,
|
|
.len = ARRAY_SIZE(tx),
|
|
.delay_usecs = SPI_DELAY,
|
|
.speed_hz = SPEED,
|
|
.bits_per_word = 8,
|
|
};
|
|
|
|
ret = ioctl(fd, SPI_IOC_MESSAGE(HALF_DUPLEX), &tr);
|
|
if (ret < 1){
|
|
log_printf(LOG_ERR,I_NOUSED,"can't send spi message, for write fd %d\n",fd);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
uint8_t iSPI_I2S_SendData(int spi_fd, uint16_t Data)
|
|
{
|
|
int ret;
|
|
uint8_t rx[2] = {0};
|
|
uint8_t tx[2] = {0};
|
|
|
|
if(spi_fd < 0)
|
|
return -1;
|
|
|
|
tx[0] = (u8)((Data & 0xFF00) >> 8);
|
|
tx[1] = (u8)((Data & 0x00FF) >> 0);
|
|
|
|
struct spi_ioc_transfer tr = {
|
|
.tx_buf = (unsigned long)tx,
|
|
.rx_buf = (unsigned long)rx,
|
|
.len = ARRAY_SIZE(tx),
|
|
.delay_usecs = SPI_DELAY,
|
|
.speed_hz = SPEED,
|
|
.bits_per_word = 8,
|
|
};
|
|
|
|
ret = ioctl(spi_fd, SPI_IOC_MESSAGE(1), &tr);
|
|
if (ret < 1)
|
|
{
|
|
log_printf(LOG_ERR,I_NOUSED,"can't send spi message, for write fd %d\n",spi_fd);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
|
|
|
|
uint8_t iSPI_I2S_Send4Byte(int spi_fd, uint8 *pdata)
|
|
{
|
|
int ret;
|
|
uint8_t rx[4] = {0};
|
|
uint8_t tx[4] = {0};
|
|
|
|
if(spi_fd < 0)
|
|
return -1;
|
|
|
|
memcpy(tx, pdata, 4);
|
|
|
|
struct spi_ioc_transfer tr = {
|
|
.tx_buf = (unsigned long)tx,
|
|
.rx_buf = (unsigned long)rx,
|
|
.len = ARRAY_SIZE(tx),
|
|
.delay_usecs = SPI_DELAY,
|
|
.speed_hz = SPEED,
|
|
.bits_per_word = 8,
|
|
};
|
|
|
|
/* SPI_IOC_MESSAGE(n) -- [n] means numbers of struct spi_ioc_transfer, so 1. */
|
|
ret = ioctl(spi_fd, SPI_IOC_MESSAGE(1), &tr);
|
|
if (ret < 1) {
|
|
log_printf(LOG_ERR,I_NOUSED,"can't send spi message, for write fd %d\n", spi_fd);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
int init_spi_dev(char *pspi_node_name, int *pfd, uint8 mode, uint8 bits, uint8 speed)
|
|
{
|
|
int ret;
|
|
int fd=-1;
|
|
|
|
/*
|
|
wr/rd speed: defined through macro definitions[ SPEED ].
|
|
*/
|
|
// unsigned char mode = SPI_MODE_3 ;
|
|
// unsigned char bits = 8;
|
|
// unsigned int speed = 100000;
|
|
|
|
fd = openSpiDev(pspi_node_name);
|
|
if(fd < 0) {
|
|
log_printf(LOG_ERR, I_NOUSED, "init_spi_dev >%s< open failed!\n", pspi_node_name);
|
|
}
|
|
|
|
ret = initSpiDev(fd, mode, bits, speed);
|
|
if(ret < 0 ) {
|
|
log_printf(LOG_ERR, I_NOUSED, "init_spi_dev >%s< init failed!\n", pspi_node_name);
|
|
return -1;
|
|
}
|
|
|
|
log_printf(LOG_INFO, I_SYS_STATUS, "init_spi_dev >%s< init ok!!\n", pspi_node_name);
|
|
|
|
*pfd = fd;
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|