2023-11-21 11:34 PM
I have integrated the ST25R3911B into an ARM64 Linux development board, using rfal_v1.3 for communication via SPI.
I am able to poll and read cards successfully, but I've observed higher CPU usage.
Upon inspecting the perf.svg, it appears that the st25r3911ReadMultipleRegisters function is consuming a significant amount of CPU.
Could you assist in analyzing this issue? here is my
/******************************************************************************
* @attention
*
* <h2><center>© COPYRIGHT 2018 STMicroelectronics</center></h2>
*
* Licensed under ST MYLIBERTY SOFTWARE LICENSE AGREEMENT (the "License");
* You may not use this file except in compliance with the License.
* You may obtain a copy of the License at:
*
* http://www.st.com/myliberty
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,
* AND SPECIFICALLY DISCLAIMING THE IMPLIED WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
* See the License for the specific language governing permissions and
* limitations under the License.
*
******************************************************************************/
/*! \file pltf_spi.c
*
* \author Shikha Singh
*
* \brief Implementation for SPI communication.
*
*/
/*
******************************************************************************
* INCLUDES
******************************************************************************
*/
#include <string.h>
#include <stdio.h>
#include <fcntl.h>
#include <linux/spi/spidev.h>
#include <sys/ioctl.h>
#include <pthread.h>
#include "pltf_spi.h"
#include "st_errno.h"
/*
******************************************************************************
* DEFINES
******************************************************************************
*/
#define SPI_MODE_CONFIG SPI_MODE_1
#define SPI_BITS_PER_WORD 8
#define SPI_MAX_FREQ 1000000
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
/*
******************************************************************************
* STATIC VARIABLES
******************************************************************************
*/
/* ST25R3911XX is connected with Linux host's SPI port /dev/spidev0.0 */
static const char *device = "/dev/spidev0.0";
static int fd = 0;
static int isSPIInit = 0;
/* Lock to serialize SPI communication */
static pthread_mutex_t lockCom;
/*
******************************************************************************
* GLOBAL AND HELPER FUNCTIONS
******************************************************************************
*/
ReturnCode spi_init(void)
{
int ret = 0;
uint32_t mode = SPI_MODE_CONFIG;
uint8_t bitsperword = SPI_BITS_PER_WORD;
uint32_t speed = SPI_MAX_FREQ;
fd = open(device, O_RDWR);
if (fd < 0) {
printf("Error: spi device open = %d\n", fd);
ret = fd;
goto error;
}
/* set spi mode */
ret = ioctl(fd, SPI_IOC_WR_MODE32, &mode);
if (ret < 0) {
printf("Error: SPI mode setting\n");
goto error;
}
/* set spi bits per word */
ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bitsperword);
if (ret < 0) {
printf("Error: setting spi bitsperword\n");
goto error;
}
/* set spi frequency */
ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
if (ret < 0) {
printf("Error: setting SPI frequency\n");
goto error;
}
ret = pthread_mutex_init(&lockCom, NULL);
if (ret != 0)
{
printf("Error: mutex init to protect SPI communication is failed\n");
goto error;
}
isSPIInit = 1;
return ERR_NONE;
error:
return ERR_IO;
}
HAL_statusTypeDef spiTxRx(const uint8_t *txData, uint8_t *rxData, uint8_t length)
{
int ret = 0;
int i;
/* check if SPI init is done */
if (!isSPIInit) {
printf(" error: spi is used for communication before its initialization\n");
return HAL_ERROR;
}
/* lock for atomic SPI transaction */
//pthread_mutex_lock(&lock);
struct spi_ioc_transfer transfer;
memset(&transfer, 0, sizeof(struct spi_ioc_transfer));
if (txData)
transfer.tx_buf = (unsigned long) txData;
if (rxData)
transfer.rx_buf = (unsigned long) rxData;
transfer.len = (unsigned int) length;
transfer.speed_hz = SPI_MAX_FREQ;
transfer.bits_per_word = SPI_BITS_PER_WORD;
transfer.delay_usecs = 0;
transfer.cs_change = 0;
ret = ioctl(fd, SPI_IOC_MESSAGE(1), &transfer);
if (ret < 0) {
printf("Error: SPI error in data transfer=%d\n",ret);
/* Unlock the mutex before returning from error case */
//pthread_mutex_unlock(&lock);
return HAL_ERROR;
}
/* Unlock the mutex */
//pthread_mutex_unlock(&lock);
return HAL_OK;
}
void pltf_protect_com(void)
{
pthread_mutex_lock(&lockCom);
}
void pltf_unprotect_com(void)
{
pthread_mutex_unlock(&lockCom);
}
void plat_spi_select(void)
{
usleep(150);
}
void plat_spi_deselect(void)
{
usleep(150);
}
Solved! Go to Solution.
2023-12-04 11:18 PM
Hi
I have traced that rfalISO14443ATransceiveShortFrame() consistently returns RFAL_ERR_IO.
2023-12-04 11:32 PM
Hi,
you need to dig deeper, likely you will find that the program is not catching an interrupt where it needs to get one.
Please enable the define ST25R_SELFTEST and observe the flow and return code of st25r3911Initialize(): It will test the connections to the chip (Register R/W, IRQ pin and also perform plausibility checks on the timer subsystem).
BR, Ulysses
2023-12-04 11:38 PM
ok , thank you
2023-12-05 12:53 AM
Hi
stError gpio_init(void)
{
int fd_exportGPIO = 0;
int fd_dirGPIO = 0;
int fd_edgeGPIO = 0;
int fd_unexport = 0;
int ret = 0;
char buf[SIZE];
char buf_tmp[SIZE];
struct stat sts;
/* Export the control of interrupt GPIO to user space */
/* if already exported, first unexport it */
sprintf(buf, "/sys/class/gpio/gpio%d", 34);
if (!stat (buf, &sts)) {
fd_unexport = open("/sys/class/gpio/unexport", O_WRONLY);
if (fd_unexport < 0) {
printf("Error: opening gpio export file in gpio_init\n");
goto error;
}
sprintf(buf_tmp, "%d", 34);
ret = write(fd_unexport, buf_tmp, strlen(buf_tmp));
if (ret <= 0) {
printf("Error: writing to gpio export file in gpio_init\n");
goto error;
}
}
fd_exportGPIO = open("/sys/class/gpio/export", O_WRONLY);
if (fd_exportGPIO < 0) {
printf ("Error: opening gpio export file for interrupt pin\n");
goto error;
}
sprintf(buf, "%d", 34);
ret = write(fd_exportGPIO, buf, strlen(buf));
if(ret < 0) {
printf("Error: writing interrupt pin to gpio export file\n");
goto error;
}
/* set the direction of interrupt pin */
sprintf(buf, "/sys/class/gpio/gpio%d/direction", 34);
fd_dirGPIO = open(buf, O_WRONLY);
if (fd_dirGPIO < 0) {
printf("Error: opening gpio direction file for interrupt pin\n");
goto error;
}
ret = write(fd_dirGPIO, "in", 3);
if (ret <= 0) {
printf("Error: writing gpio direction for interrupt pin\n");
goto error;
}
sprintf(buf, "/sys/class/gpio/gpio%d/value", 34);
// fd_readGPIO = open(buf, O_RDWR);
fd_readGPIO = open(buf, O_RDONLY);
if (fd_readGPIO < 1) {
printf("Error: opening gpio value file for interrupt pin\n");
goto error;
}
sprintf(buf, "/sys/class/gpio/gpio%d/edge", 34);
fd_edgeGPIO = open(buf, O_WRONLY);
if (fd_edgeGPIO < 1) {
printf("Error: opening edge file to configure interrupt pin\n");
goto error;
}
ret = write(fd_edgeGPIO, "both", 5);
if (ret <= 0) {
printf("Error: writing gpio edge setting for interrupt pin\n");
goto error;
}
ret = pthread_mutex_init(&lock, NULL);
if (ret != 0)
{
printf("Error: mutex init to protect interrupt status is failed\n");
goto error;
}
isGPIOInit = 1;
error:
if (fd_exportGPIO > 0)
close(fd_exportGPIO);
if (fd_dirGPIO > 0)
close(fd_dirGPIO);
if (fd_edgeGPIO > 0)
close(fd_edgeGPIO);
if (fd_unexport > 0)
close(fd_unexport);
if(isGPIOInit)
return ERR_NONE;
else
return ERR_IO;
}
2023-12-05 02:11 AM
Hi,
debug your setup: Verify the IRQ line, verify that on IRQ line going high in pthread_func() it returns from read() and calls the ISR.
Regards, Ulysses