This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

ZEPHYR spi asynchronus api transfer with asymmetric buffers error

Hi,

Zephyr 3.0 , nrf5340  ncs 1.9.1 

i can successfully sent data with

this function ; 
int adxl362ext_get_fifo_data(const struct device *dev,uint8_t *read_buf, uint16_t count,struct k_poll_signal *signal_)
{
	const struct adxl362ext_config *cfg = dev->config;
	int err;
	uint8_t access[1] = { ADXL362EXT_READ_FIFO};
	const struct spi_buf buf[2] = {
		{
			.buf = access,
			.len = 1
		},
		{
			.buf = read_buf,
			.len = count
		}
	};
	struct spi_buf_set tx = {
		.buffers = buf,
		.count = 1
	};

	const struct spi_buf_set rx = {
		.buffers = buf,
		.count = 2
	};
	err = spi_transceive_dt(&cfg->bus,&tx, &rx);
	//err = spi_transceive_async_dt(&cfg->bus,&tx, &rx,signal_);
	return err;
}
So it sends 2 transactions without changing cs state.
1byte tx+rx  , and remaining rx bytes at the second transaction.. all works as expected.
but if i try async transceive function with these the same buffers / buffersets , i got kpoll event signal result as  -5 error ...
update: i could get 0 (success) but again it only sends the first buffers in the buffer set . 
if count is 1 in the buffer set , it works, but if count is 2 only the first parts fires. 
this is the debugger watch after the first chunk transferred. so this is the second chunk and it says 0 for rx and tx buffers.
if i use synchronous spi these chunks points the initial buffer address...
static inline int spi_transceive_async_dt(const struct spi_dt_spec *spec,
				    const struct spi_buf_set *tx_bufs,
				    const struct spi_buf_set *rx_bufs,struct k_poll_signal *signal_)
{
	return spi_transceive_async(spec->bus, &spec->config, tx_bufs, rx_bufs,signal_);
}
i tested with symmetric buffers, and it worked! 
one more finding , may be this helps to find out the issue ; 
void spi_context_update_rx(struct spi_context *ctx, uint8_t dfs, uint32_t len)
{
#ifdef CONFIG_SPI_SLAVE
	if (spi_context_is_slave(ctx)) {
		ctx->recv_frames += len;
	}

#endif /* CONFIG_SPI_SLAVE */

	if (!ctx->rx_len) {
		return;
	}
if(len>100){
volatile int oo;
oo=0;
}
	if (len > ctx->rx_len) {
		LOG_ERR("Update exceeds current buffer");
		return;
	}

	ctx->rx_len -= len;
	if (!ctx->rx_len) {
		/* Current buffer is done. Get the next one to be processed. */
		++ctx->current_rx;
		--ctx->rx_count;
		ctx->rx_buf = (uint8_t *)
			spi_context_get_next_buf(&ctx->current_rx,
						 &ctx->rx_count,
						 &ctx->rx_len, dfs);
	} else if (ctx->rx_buf) {
		ctx->rx_buf += dfs * len;
	}

	LOG_DBG("rx buf/len %p/%zu", ctx->rx_buf, ctx->rx_len);
}
i have added this code to make a breakpoint for debugger in spi_context_update_rx(struct spi_context *ctx, uint8_t dfs, uint32_t len) function( as you can see above. line 13)
if(len>100){
volatile int oo;
oo=0;
}
I set my second buffer length as 256
	uint8_t access[1] = { ADXL362EXT_READ_FIFO};
	const struct spi_buf buf[2] = {
		{
			.buf = access,
			.len = 1
		},
		{
			.buf = read_buf,
			.len = 256
		}
	};
	struct spi_buf_set tx = {
		.buffers = buf,
		.count = 1
	};

	const struct spi_buf_set rx = {
		.buffers = buf,
		.count = 2
	};
	#if(CONFIG_SPI_ASYNC)
	err = spi_transceive_async_dt(&cfg->bus,&tx, &rx,signal_);
	#else
If i transfer these buffers with this function ;
spi_transceive_async_dt(&cfg->bus,&tx, &rx,signal_);
debugger will never stop at  len>100 condition;
if i transfer the same buffer with 
err = spi_transceive_dt(&cfg->bus,&tx, &rx);
debugger stops at break point and , i can see len is 256...
So i check the documentation i couldn't find any information about this issue.
How can we use asymmetric buffer/sets with asynchronous spi api ?
Thanks.
Parents
  • Hi Mehmet

    I don't seem to have any issues with this on my side. I can use the spi_transceive_async functions whether or not I have the same number of TX and RX buffers. 

    Please find my main.c file attached:

    /*
     * Copyright (c) 2016 Intel Corporation
     *
     * SPDX-License-Identifier: Apache-2.0
     */
    
    #include <zephyr.h>
    #include <device.h>
    #include <devicetree.h>
    #include <drivers/gpio.h>
    #include <drivers/spi.h>
    
    /* 1000 msec = 1 sec */
    #define SLEEP_TIME_MS   1000
    
    /* The devicetree node identifier for the "led0" alias. */
    #define LED0_NODE DT_ALIAS(led0)
    
    #if DT_NODE_HAS_STATUS(LED0_NODE, okay)
    #define LED0	DT_GPIO_LABEL(LED0_NODE, gpios)
    #define PIN	DT_GPIO_PIN(LED0_NODE, gpios)
    #define FLAGS	DT_GPIO_FLAGS(LED0_NODE, gpios)
    #else
    /* A build error here means your board isn't set up to blink an LED. */
    #error "Unsupported board: led0 devicetree alias is not defined"
    #define LED0	""
    #define PIN	0
    #define FLAGS	0
    #endif
    
    #define PIN1 DT_GPIO_PIN(DT_ALIAS(led1), gpios)
    
    static const struct spi_config spi_cfg = {
    	.operation = SPI_WORD_SET(8) | SPI_TRANSFER_MSB |
    		     SPI_MODE_CPOL | SPI_MODE_CPHA,
    	.frequency = 4000000,
    	.slave = 0,
    };
    
    const struct device * spi_dev;
    
    static void spi_init(void)
    {
    	const char* const spiName = "SPI_2";
    	spi_dev = device_get_binding(spiName);
    
    	if (spi_dev == NULL) {
    		printk("Could not get %s device\n", spiName);
    		return;
    	}
    }
    
    const struct device *dev;
    
    static struct k_poll_signal async_sig = K_POLL_SIGNAL_INITIALIZER(async_sig);
    static struct k_poll_event  async_evt =
    	K_POLL_EVENT_INITIALIZER(K_POLL_TYPE_SIGNAL,
    				 K_POLL_MODE_NOTIFY_ONLY,
    				 &async_sig);
    
    void spi_test_send(void)
    {
    	int err;
    	static uint8_t tx_buffer1[4] = {1,2,3,4};
    	static uint8_t tx_buffer2[3] = {2,3,4};
    	static uint8_t rx_buffer[2];
    	static uint8_t rx_buffer2[4];
    
    	const struct spi_buf tx_buf[2] = {{
    		.buf = tx_buffer1,
    		.len = sizeof(tx_buffer1)}, {
    		.buf = tx_buffer2, 
    		.len = sizeof(tx_buffer2)}
    	};
    	const struct spi_buf_set tx = {
    		.buffers = tx_buf,
    		.count = 1
    	};
    
    	struct spi_buf rx_buf[2] = {{
    		.buf = rx_buffer,
    		.len = sizeof(rx_buffer)},{
    		.buf = rx_buffer2,
    		.len = sizeof(rx_buffer2)}
    	};
    	const struct spi_buf_set rx = {
    		.buffers = rx_buf,
    		.count = 2
    	};
    	
    	//err = spi_transceive(spi_dev, &spi_cfg, &tx, &rx);
    	err = spi_transceive_async(spi_dev, &spi_cfg, &tx, &rx, &async_sig);
    
    	if (err) {
    		printk("SPI error: %d\n", err);
    		return;
    	}
    	// Waiting for event to occur
    	err = k_poll(&async_evt, 1, K_MSEC(100));
    	if (err) {
    		printk("Failed waiting for SPI async event\n");
    	} else {
    		printk("SPI complete!\n");
    		printk("TX sent: %x-%x-%x-%x\n", tx_buffer1[0], tx_buffer1[1], tx_buffer1[2], tx_buffer1[3]);
    		printk("RX recv: %x-%x\n", rx_buffer[0], rx_buffer[1]);
    		printk("RX2 recv: %x-%x\n", rx_buffer2[0], rx_buffer2[1]);
    		tx_buffer1[0]++;
    		tx_buffer1[1]++;
    		tx_buffer1[2]++;
    	}
    }
    
    void main(void)
    {
    	bool led_is_on = true;
    	int ret;
    
    	printk("SPI async test\n");
    
    	dev = device_get_binding(LED0);
    	if (dev == NULL) {
    		return;
    	}
    
    	ret = gpio_pin_configure(dev, PIN, GPIO_OUTPUT_ACTIVE | FLAGS);
    	if (ret < 0) {
    		return;
    	}
    
    	ret = gpio_pin_configure(dev, PIN1, GPIO_OUTPUT_ACTIVE | FLAGS);
    	if (ret < 0) {
    		return;
    	}
    
    	spi_init();
    
    	while (1) {
    		gpio_pin_set(dev, PIN, (int)led_is_on);
    		led_is_on = !led_is_on;
    		spi_test_send();
    		k_msleep(SLEEP_TIME_MS);
    	}
    }
    

    Are you sure you are setting up the poll signal and event correctly?

    How are you polling the signal after starting the SPI transaction?

    Best regards
    Torbjørn

  • Could you please give me full project , i couldnt make it work standalone. 

  • Hi Mehmet

    I have attached the project here: 

    5432.spi_test.zip

    It is basically just the zephyr blinky sample, with some code added to test the SPI driver. 

    It was tested in v1.9.1. 

    If you are still having problems getting it to build or run please let me know which issues you're seeing, and I will do my best to help. 

    Best regards
    Torbjørn

Reply
  • Hi Mehmet

    I have attached the project here: 

    5432.spi_test.zip

    It is basically just the zephyr blinky sample, with some code added to test the SPI driver. 

    It was tested in v1.9.1. 

    If you are still having problems getting it to build or run please let me know which issues you're seeing, and I will do my best to help. 

    Best regards
    Torbjørn

Children
No Data
Related