Files

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;
}