cancel
Showing results for 
Search instead for 
Did you mean: 

ST25R3911 high cpu use

zhaocz
Associate II

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 

pltf_spi.c

 

 

/******************************************************************************
  * @attention
  *
  * <h2><center>&copy; 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);
}

 

 

24 REPLIES 24

Hi


I have traced that rfalISO14443ATransceiveShortFrame() consistently returns RFAL_ERR_IO.

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 

ok , thank you

Hi

 

The result of "Check IRQ Handling" is "ERR_TIMEOUT", what is the possible reason?
I modified gpio_init(), is it related to this? How can i dig deeper?


 

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;

}

 

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