我连接了一个Linux嵌入式主板(基于imx233)和一个MSP430 MCU。它们通过4引脚SPI连接,但我在Linux板上使用GPIO进行芯片选择。我所做的是使用poll来检测GPIO的下降沿(nr 52)然后执行SPI读取ioctl
或read()
int main(void)
{
/********************************LINUX SCHEDULING**********************************/
sp.sched_priority = sched_get_priority_max(SCHED_FIFO); //scheduling
sched_setscheduler(0, SCHED_FIFO, &sp); //scheduling
/********************************LINUX SCHEDULING_END******************************/
struct pollfd fdset[2]; //declare the poll to be used in interrupt catching
int nfds = 2;
int gpio_fd, timeout, rc;
char *buf[MAX_BUF]; //max=64byte
int len;
initialize(); //gpio's are set to SPI_SLAVE
// spi_init();
gpio_fd = gpio_fd_open(CHIP_SELECT_PIN); //the CS(SS) pin is opened
timeout = POLL_TIMEOUT; //timeout 3 sec is set
// uint8_t voidFirstDetection = 1;
while (1) {
memset((void*)fdset, 0, sizeof(fdset));
fdset[0].fd = NULL;
fdset[0].events = POLLIN;
fdset[1].fd = gpio_fd;
fdset[1].events = POLLPRI;
/*** POLL starts to detect chipselects****/
rc = poll(fdset, nfds, timeout);
if (rc < 0) {
printf("\npoll() failed!\n");
return -1;
}
if (rc == 0) {
printf(".");
}
if (fdset[1].revents & POLLPRI ) { //HERE I need to run SPI_read
len = read(fdset[1].fd, buf, MAX_BUF);
/* if(voidFirstDetection){
voidFirstDetection = 0;
}else{*/
printf("\npoll() GPIO %d interrupt occurred\n", CHIP_SELECT_PIN);
int fd = open(device, O_RDWR);
if (fd < 0){
// snprintf(systemlogmsg, sizeof(systemlogmsg), "[1181]: errno:%s Cannot open /dev/spidev ", strerror(errno));
// error_logging(systemlogmsg, LOGLEVEL_ERROR);
printf("error spi recive\n");
}
//spi_transfer(fd);
do_read(fd);
close(fd);
// }
}
}
gpio_fd_close(gpio_fd);
return 0;
}
以上代码工作正常,只在信号的下降沿产生中断。当检测到中断时,我使用以下任一代码来读取/dev/spidev1-0
static void do_read(int fd)
{
unsigned char buf[1], *bp;
int status;
int len = 1;
/* read at least 2 bytes, no more than 32 */
memset(buf, 0, sizeof buf);
status = read(fd, buf, len);
if (status < 0) {
perror("read");
return;
}
if (status != len) {
fprintf(stderr, "short read\n");
return;
}
printf("read(%2d, %2d): %02x %02x,", len, status,
buf[0], buf[1]);
status -= 2;
bp = buf + 2;
while (status-- > 0)
printf(" %02x", *bp++);
printf("\n");
}
static void spi_transfer(int fd)
{
int ret;
uint8_t tx[2];
uint8_t rx[3] = {0 };
struct spi_ioc_transfer tr = {
.tx_buf = 0,
.rx_buf = (unsigned long)rx,
.len = ARRAY_SIZE(tx),
.delay_usecs = delay,
.speed_hz = speed,
.bits_per_word = bits,
};
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
if (ret < 1){
printf("can't send spi message");
exit(1);
}
for (ret = 0; ret < ARRAY_SIZE(tx); ret++) {
if (!(ret % 6))
puts("");
printf("%.2X ", rx[ret]);
}
puts("");
}
每当执行ret = ioctl(fd, SPI_IOC_MESSAGE(1), &tr);
上的spi_transfer()
行或status = read(fd, buf, len);
上的do_read()
时,我都会看到一个无限循环,检测到GPIO52上的中断(chipselect)。我尝试通过示波器观察GPIO但我看不到任何信号变化(可能是我的示波器无法检测到的尖峰),但是,当我将chipselect连接到Vcc时,它没有得到无限循环。由于我处于早期阶段,我将MCU中的一个GPIO设置为输出并且设置为恒定逻辑高电平。我使用GPIO52(芯片选择)作为输入,因为我的目标是将数据从MCU传输到linux板。
我想,read()
和ioctl
会以某种方式影响GPIO吸收比GPIO提供的电流更多的电流。如果是问题,我能做什么,ioctl或read()不会打扰GPIO。或者你认为别的东西可能是个问题?
答案 0 :(得分:1)
我很幸运,我发现问题很快。我绑了两块板的地面,现在它工作正常。我将保留帖子,因为其他人可能会遇到同样的问题。但我仍然很好奇ioctl或读取如何干扰GPIO信号电平