Skip to main content
Visitor II
November 22, 2023
Solved

ST25R3911 high cpu use

  • November 22, 2023
  • 2 replies
  • 4558 views

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

 

 

    This topic has been closed for replies.
    Best answer by Ulysses HERNIOSUS

    Hi zhaocz,

     

    I missed that you are on an old version. It has been updated quite some while ago. Please find it at https://www.st.com/en/embedded-software/stsw-st25r009.html 

     

    BR, Ulysses

    2 replies

    Technical Moderator
    November 22, 2023

    Hi Zhaocz,

    can you please share the results you are getting and also where you think the CPU consumption should be?

    The function is issuing SPI transfers in a blocking manner, but expectation is that it would be sleeping while waiting for the SPI to be finished.

    BR, Ulysses

    zhaoczAuthor
    Visitor II
    November 22, 2023

    My application runs on different boards, both using arm64 architecture with Debian 10, but from different manufacturers.
    On Board A, the CPU usage is only 5%, while on Board B, it's 20%.
    After analysis, I found that on Board B, a significant portion of the CPU is spent on the
    st25r3911ReadMultipleRegisters operation.
    I suspect that this difference in CPU usage might be due to variations in the SPI between the two boards.
    Could you please provide some guidance on this? Thank you.

    Technical Moderator
    November 22, 2023

    Hi,

    I would presume a difference in SPI driver implementation (different SPI IP?). I guess you have also an analysis of the function called by st25r3911ReadMultipleRegisters()? Please look into it as well and share. If this cannot be meaningfully analyzed, then please introduce a proxy function for SPI (for st25r3911ReadMultipleRegisters() only and analyze it. Basically look at the delta of the CPU usage.

    BR, Ulysses

    zhaoczAuthor
    Visitor II
    November 28, 2023

    I've tried adjusting the SPI speed, and the higher the SPI speed, the higher the polling frequency triggered.

    I'm sorry, I misspoke. It's several tens of times per second.

    The wake-up mode is disabled.

    It polls even when there is no card.

    I'm sorry, I don't understand what discoverParam is.

    Technical Moderator
    November 28, 2023

    Hi zhaocs,

    when using our demos you will find a 

    static rfalNfcDiscoverParam discParam;

    Likely in demo_pollling.c the code will set its totalDuration to a value. This value should result in the period of the polling: Does it match your observations from the outside? What is the polling period for both of your implementations?

    If unsure please share logic analyzer traces of both for comparison (MISO,MOSI,SCLK,CS, INT).

     

    Best Regards, Ulysses

    zhaoczAuthor
    Visitor II
    November 29, 2023

    I couldn't locate rfalNfcDiscoverParam in my code. Would it be possible for you to share your Linux demo code? Thank you