<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://devzone.nordicsemi.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>nRF54L15 SPIS21 slave receives correct RX amount but RX buffer is all zeros when capturing camera (BF3901/BF30A2) data</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/127265/nrf54l15-spis21-slave-receives-correct-rx-amount-but-rx-buffer-is-all-zeros-when-capturing-camera-bf3901-bf30a2-data</link><description>Hi, 
 I&amp;#39;m porting a working SPI camera demo from nRF52840 to nRF54L15 and I&amp;#39;m stuck with an issue where the SPIS RX amount is correct, but the received buffer is all zeros. 
 Hardware / setup: - New platform: nRF54L15 DK, CPUAPP - Old reference project</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Thu, 19 Mar 2026 11:03:29 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/127265/nrf54l15-spis21-slave-receives-correct-rx-amount-but-rx-buffer-is-all-zeros-when-capturing-camera-bf3901-bf30a2-data" /><item><title>RE: nRF54L15 SPIS21 slave receives correct RX amount but RX buffer is all zeros when capturing camera (BF3901/BF30A2) data</title><link>https://devzone.nordicsemi.com/thread/563658?ContentTypeID=1</link><pubDate>Thu, 19 Mar 2026 11:03:29 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:7c1d1ffc-e774-497a-a920-436d60e7e85a</guid><dc:creator>Kazi Afroza Sultana</dc:creator><description>&lt;p&gt;Hello,&lt;/p&gt;
&lt;p&gt;nrf_sys_event_release_global_constlat() is called after the while loop which will never be reachable. You can try to remove it but it will cost power as this&amp;nbsp;nrf_sys_event_request_global_constlat(). Or you can use for loop for finite time.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Have you set&amp;nbsp;&lt;a title="(in Kconfig reference v&amp;amp;nbsp;)" href="https://docs.nordicsemi.com/bundle/ncs-latest/page/kconfig/index.html#CONFIG_NRF_SYS_EVENT"&gt;&lt;code&gt;&lt;span&gt;CONFIG_NRF_SYS_EVENT&lt;/span&gt;&lt;/code&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp; in the config file?&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF54L15 SPIS21 slave receives correct RX amount but RX buffer is all zeros when capturing camera (BF3901/BF30A2) data</title><link>https://devzone.nordicsemi.com/thread/563265?ContentTypeID=1</link><pubDate>Mon, 16 Mar 2026 00:51:36 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:b5bb4658-d172-4451-828a-ddb0b6b123c2</guid><dc:creator>Dorothy</dc:creator><description>&lt;p&gt;Hello,&lt;/p&gt;
&lt;p&gt;I added nrf_sys_event_request_global_constlat() before my application as per what you said, but after testing, I still couldn&amp;#39;t successfully read the data sent by the host on SPIS21. Could there be other issues?&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;int main(void)
{
	printf(&amp;quot;Hello World! %s\n&amp;quot;, CONFIG_BOARD_TARGET);
	nrf_sys_event_request_global_constlat();
	sccb_init();
    bf3901_camera_on(); 
    bf3901_read_id();

	while(1) {
		uint32_t sum = 0;

		m_length_rx_done = bf3901_camera_single_capture(m_rx_buf);
		printf(&amp;quot;Capture complete: size %u bytes\n&amp;quot;, (uint32_t)m_length_rx_done);

		for (uint16_t i = 0; i &amp;lt; m_length_rx_done; i++) {
			sum += m_rx_buf[i];
		}
		printf(&amp;quot;sum = %u\n&amp;quot;, sum);
		k_msleep(1000);
	}
	
	nrf_sys_event_release_global_constlat();
	return 0;
}&lt;/pre&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF54L15 SPIS21 slave receives correct RX amount but RX buffer is all zeros when capturing camera (BF3901/BF30A2) data</title><link>https://devzone.nordicsemi.com/thread/563142?ContentTypeID=1</link><pubDate>Thu, 12 Mar 2026 14:23:53 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:cf56e961-a465-4dca-84fa-6f5f6ba8b0ad</guid><dc:creator>Kazi Afroza Sultana</dc:creator><description>&lt;p&gt;Hello,&lt;/p&gt;
&lt;p&gt;I can see that you have used pins from port P2 for SPIM21.&lt;/p&gt;
&lt;p&gt;&lt;span&gt;To use a peripheral with pins mapped across different domains, you must enable the Constant Latency sub-power mode. You can do this by setting the&amp;nbsp;&lt;/span&gt;&lt;a title="(in Kconfig reference v&amp;amp;nbsp;)" href="https://docs.nordicsemi.com/bundle/ncs-latest/page/kconfig/index.html#CONFIG_NRF_SYS_EVENT"&gt;&lt;code&gt;&lt;span&gt;CONFIG_NRF_SYS_EVENT&lt;/span&gt;&lt;/code&gt;&lt;/a&gt;&lt;span&gt;&amp;nbsp;Kconfig option, and calling the&amp;nbsp;&lt;/span&gt;&lt;code&gt;&lt;span&gt;nrf_sys_event_request_global_constlat()&lt;/span&gt;&lt;/code&gt;&lt;span&gt;&amp;nbsp;function in your application.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;pre class="ui-code" data-mode="text"&gt;#include &amp;lt;nrf_sys_event.h&amp;gt;

int main(void)
{
        /* Request constlat. The API is reference counted. */
        nrf_sys_event_request_global_constlat();

        /* Use peripherals which have pins mapped across power-domains */

        /* Release constlat */
        nrf_sys_event_release_global_constlat();

        return 0;
}
&lt;/pre&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;a href="https://docs.nordicsemi.com/bundle/ncs-latest/page/nrf/app_dev/device_guides/nrf54l/pinmap.html#managing_cross_power-domain_pin_mapping"&gt;nRF54L pin mapping&lt;/a&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF54L15 SPIS21 slave receives correct RX amount but RX buffer is all zeros when capturing camera (BF3901/BF30A2) data</title><link>https://devzone.nordicsemi.com/thread/562861?ContentTypeID=1</link><pubDate>Tue, 10 Mar 2026 00:49:38 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:c20f2134-8417-440c-9203-a333c6e40d89</guid><dc:creator>Dorothy</dc:creator><description>&lt;p&gt;Hello,&lt;/p&gt;
&lt;p&gt;it&amp;#39;s okay. Thank you very much for your help! I have attempted to read several bytes of data using SPIS21, but the situation remains unchanged. However, the small static buffer has not been tested yet, and I will give it a try.&lt;/p&gt;
&lt;p&gt;This is my main.c file:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;#include &amp;lt;stdio.h&amp;gt;
#include &amp;quot;sccb.h&amp;quot;
#include &amp;quot;bf3901.h&amp;quot;

volatile uint8_t width= 200;
volatile uint8_t height= 100;
volatile int timers_gain = 1;;
volatile uint16_t totol_size;

volatile bool capture_flag = false;

uint16_t m_length_rx_done;
static uint8_t m_rx_buf[65536] = { 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x11, 0x22, 0x33, 0x44};    /**&amp;lt; RX buffer. */

// static const struct gpio_dt_spec my_pin = GPIO_DT_SPEC_GET_OR(DT_NODELABEL(user_pin), gpios, {0});

int main(void)
{
	printf(&amp;quot;Hello World! %s\n&amp;quot;, CONFIG_BOARD_TARGET);

	sccb_init();
    bf3901_camera_on(); 
    bf3901_read_id();

	while(1) {
		uint32_t sum = 0;

		m_length_rx_done = bf3901_camera_single_capture(m_rx_buf);
		printf(&amp;quot;Capture complete: size %u bytes\n&amp;quot;, (uint32_t)m_length_rx_done);

		for (uint16_t i = 0; i &amp;lt; m_length_rx_done; i++) {
			sum += m_rx_buf[i];
		}
		printf(&amp;quot;sum = %u\n&amp;quot;, sum);
		k_msleep(1000);
	}

	return 0;
}
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;my prj.conf file:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;CONFIG_GPIO=y
CONFIG_SPI=y
CONFIG_SPI_SLAVE=y
CONFIG_SPI_ASYNC=y
CONFIG_LOG=y
CONFIG_NRFX_GRTC=y
CONFIG_NRFX_SPIS21=y

CONFIG_TRUSTED_EXECUTION_NONSECURE=n
# STEP 1 - Enable debugging
CONFIG_DEBUG_THREAD_INFO=y
CONFIG_DEBUG_OPTIMIZATIONS=y&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Since my main function will call other functions, I am also including my bf3901.c and sccb.c here.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;#include &amp;quot;bf3901.h&amp;quot;

LOG_MODULE_DECLARE(Bt_Transmission);

static const struct device *spis_dev = DEVICE_DT_GET(DT_NODELABEL(spi21));

static const struct spi_config spis_cfg = {
    .operation = SPI_OP_MODE_SLAVE | SPI_MODE_CPOL | SPI_TRANSFER_LSB | SPI_WORD_SET(8),
    .frequency = 0,
    .slave = 0,
    .cs = NULL,
};

extern uint8_t width;
extern uint8_t height;
extern uint16_t totol_size;
extern int timers_gain;

#define SPI_INSTANCE_ID    21

static const struct gpio_dt_spec csn_pin = GPIO_DT_SPEC_GET_BY_IDX(DT_NODELABEL(user_pin), gpios, 0);
// static const struct gpio_dt_spec pdn_pin = GPIO_DT_SPEC_GET_BY_IDX(DT_NODELABEL(my_i2c_pins), gpios, 1);
static const nrfx_spis_t spis = NRFX_SPIS_INSTANCE(SPI_INSTANCE_ID);

static uint8_t m_tx_buf[42414];


static size_t last_rx_amount;

static void spis_transfer_cb(const struct device *dev, int result, void *data)
{
    (void)dev;
    (void)data;
    if (result &amp;gt;= 0) {
        last_rx_amount = (size_t)result;
    } else {
        last_rx_amount = 0;
    }
    spis_xfer_done = true;
}



int bf3901_read_id(void)
{
    uint8_t h_id = read_reg(0xfc);
    uint8_t l_id = read_reg(0xfd);
    printf(&amp;quot;%02X %02X\n&amp;quot;, h_id, l_id);
    // if(((uint16_t)h_id &amp;lt;&amp;lt; 8) + l_id != 0x3901) {
    //     printf(&amp;quot;BF3901 read id faild!&amp;quot;);
    //     return -1;
    // }
    return 0;
}

int bf3901_init_reg(void)
{
    int len = sizeof(gc032a_init_reg_tb) / sizeof(gc032a_init_reg_tb[0]);
    for(int i = 0; i &amp;lt; len; i++) {
        write_reg(gc032a_init_reg_tb[i][0], gc032a_init_reg_tb[i][1]);
    }
    write_reg(0x17, 0x00);
    write_reg(0x18, width);
    write_reg(0x19, 0x00);
    write_reg(0x1a, height);
    return 0;
}

void bf3901_camera_on(void)
{
    gpio_pin_configure_dt(&amp;amp;csn_pin, GPIO_OUTPUT | GPIO_PULL_UP);
	gpio_pin_set_dt(&amp;amp;csn_pin, 1);
    // nrf_gpio_cfg_output(PDN);   
    // nrf_gpio_pin_clear(PDN);
    // camera_clk_out();

    nrf_gpio_pin_control_select(GRTC_PIN, NRF_GPIO_PIN_SEL_GRTC);
	nrfy_grtc_clkout_divider_set(NRF_GRTC, 1);
	nrfy_grtc_clkout_set(NRF_GRTC, NRF_GRTC_CLKOUT_FAST, true);

    // nrf_gpio_cfg(AVDD,NRF_GPIO_PIN_DIR_OUTPUT,NRF_GPIO_PIN_INPUT_DISCONNECT,NRF_GPIO_PIN_PULLUP,NRF_GPIO_PIN_S0S1,NRF_GPIO_PIN_NOSENSE);
    // nrf_gpio_pin_set(AVDD);
    bf3901_init_reg();
}



uint16_t bf3901_camera_single_capture(uint8_t *m_rx_buf)
{
    memset(m_tx_buf, 0xFF, sizeof(m_tx_buf));

    totol_size = (12 + width * 1) * height * 2 + 13;
    spis_xfer_done = false;
    last_rx_amount = 0;

    if (!device_is_ready(spis_dev)) {
        printf(&amp;quot;spis_dev not ready\n&amp;quot;);
        return 0;
    }

    struct spi_buf tx_buf = {
        .buf = m_tx_buf,
        .len = totol_size,
    };
    struct spi_buf rx_buf = {
        .buf = m_rx_buf,
        .len = totol_size,
    };
    struct spi_buf_set tx_set = {
        .buffers = &amp;amp;tx_buf,
        .count = 1,
    };
    struct spi_buf_set rx_set = {
        .buffers = &amp;amp;rx_buf,
        .count = 1,
    };

    int ret = spi_transceive_cb(spis_dev, &amp;amp;spis_cfg, &amp;amp;tx_set, &amp;amp;rx_set, spis_transfer_cb, NULL);
    printf(&amp;quot;spi_transceive_cb ret = %d\n&amp;quot;, ret);
    if (ret &amp;lt; 0) {
        return 0;
    }

    gpio_pin_set_dt(&amp;amp;csn_pin, 0);
    // debug_capture_spi_edges();
    NRFX_DELAY_US(180 * 1000);

    gpio_pin_set_dt(&amp;amp;csn_pin, 1);

    printf(&amp;quot;wait XFER Done\n&amp;quot;);

    uint32_t timeout = 1000000;
    while (!spis_xfer_done &amp;amp;&amp;amp; timeout--) {
        k_busy_wait(10);
    }

    printf(&amp;quot;xfer_done: %d, timeout: %s, len: %u\n&amp;quot;,
           spis_xfer_done,
           (timeout == 0) ? &amp;quot;yes&amp;quot; : &amp;quot;no&amp;quot;,
           (unsigned int)last_rx_amount);

    if (spis_xfer_done &amp;amp;&amp;amp; last_rx_amount &amp;gt; 0) {
        sys_cache_data_invd_range(m_rx_buf, last_rx_amount);

        printf(&amp;quot;first 10 bytes:\n&amp;quot;);
        for (int i = 0; i &amp;lt; 64 &amp;amp;&amp;amp; i &amp;lt; last_rx_amount; i++) {
            printf(&amp;quot;0x%02X &amp;quot;, m_rx_buf[i]);
        }
        printf(&amp;quot;\n&amp;quot;);
    }

    return (uint16_t)last_rx_amount;
}
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;sccb.c:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;#include &amp;quot;sccb.h&amp;quot;

static const struct gpio_dt_spec scl_pin = GPIO_DT_SPEC_GET_BY_IDX(DT_NODELABEL(my_i2c_pins), gpios, 0);
static const struct gpio_dt_spec sda_pin = GPIO_DT_SPEC_GET_BY_IDX(DT_NODELABEL(my_i2c_pins), gpios, 1);

static void sccb_set_sda_out(void)
{
    if (sda_pin.port) {
        gpio_pin_configure_dt(&amp;amp;sda_pin, GPIO_OUTPUT | GPIO_PULL_UP);
    }
}

static void sccb_set_scl_out(void)
{
    if (scl_pin.port) {
        gpio_pin_configure_dt(&amp;amp;scl_pin, GPIO_OUTPUT | GPIO_PULL_UP);
    }
}

void sccb_init(void)
{
    sccb_set_sda_out();
    sccb_set_scl_out();
}

static inline void sccb_delay(void)
{
    NRFX_DELAY_US(2);
}


static void sccb_start(void)
{
    gpio_pin_set_dt(&amp;amp;sda_pin, 1);
    gpio_pin_set_dt(&amp;amp;scl_pin, 1);
    sccb_delay();
    gpio_pin_set_dt(&amp;amp;sda_pin, 0);
    sccb_delay();
    gpio_pin_set_dt(&amp;amp;scl_pin, 0);
}

static void sccb_stop(void)
{
    gpio_pin_set_dt(&amp;amp;sda_pin, 0);
    sccb_delay();
    gpio_pin_set_dt(&amp;amp;scl_pin, 1);
    sccb_delay();
    gpio_pin_set_dt(&amp;amp;sda_pin, 1);
    sccb_delay();
}

static void sccb_write_byte(uint8_t dat)
{
    int8_t dat_index;
    uint8_t dat_bit;

    for (dat_index=7; dat_index&amp;gt;=0; dat_index--)
    {
        dat_bit = (dat &amp;gt;&amp;gt; dat_index) &amp;amp; 0x01;
        if (dat_bit == 1)
            gpio_pin_set_dt(&amp;amp;sda_pin, 1);
        else
            gpio_pin_set_dt(&amp;amp;sda_pin, 0);
        sccb_delay();
        gpio_pin_set_dt(&amp;amp;scl_pin, 1);
        sccb_delay();
        gpio_pin_set_dt(&amp;amp;scl_pin, 0);
    }

    gpio_pin_set_dt(&amp;amp;sda_pin, 1);
    sccb_delay();
    gpio_pin_set_dt(&amp;amp;scl_pin, 1);
    sccb_delay();
    gpio_pin_set_dt(&amp;amp;scl_pin, 0);
}

static uint8_t sccb_read_byte(void)
{
    int8_t dat_index;
    uint8_t dat_bit;
    uint8_t dat=0;
    if (sda_pin.port) {
        gpio_pin_configure_dt(&amp;amp;sda_pin, GPIO_INPUT | GPIO_PULL_UP);
    }
    for (dat_index=7; dat_index&amp;gt;=0; dat_index--)
    {
        sccb_delay();
        gpio_pin_set_dt(&amp;amp;scl_pin, 1);
        dat_bit = gpio_pin_get_dt(&amp;amp;sda_pin);
        dat |= (dat_bit &amp;lt;&amp;lt; dat_index);
        sccb_delay();
        gpio_pin_set_dt(&amp;amp;scl_pin, 0);
    }

    sccb_delay();
    gpio_pin_set_dt(&amp;amp;scl_pin, 1);
    sccb_delay();
    gpio_pin_set_dt(&amp;amp;scl_pin, 0);
    sccb_delay();
    gpio_pin_set_dt(&amp;amp;sda_pin, 0);
    sccb_delay();
    sccb_set_sda_out();
    return dat;
}

static void sccb_3_phase_write(uint8_t id_addr, uint8_t sub_addr, uint8_t dat)
{
    sccb_start();
    sccb_write_byte((id_addr &amp;lt;&amp;lt; 1) | SCCB_WRITE);
    sccb_write_byte(sub_addr);
    sccb_write_byte(dat);
    sccb_stop();
}


static void sccb_2_phase_write(uint8_t id_addr, uint8_t sub_addr)
{
    sccb_start();
    sccb_write_byte((id_addr &amp;lt;&amp;lt; 1) | SCCB_WRITE);
    sccb_write_byte(sub_addr);
    sccb_stop();
}


static uint8_t sccb_2_phase_read(uint8_t id_addr)
{
    uint8_t dat=0;
    sccb_start();
    sccb_write_byte((id_addr &amp;lt;&amp;lt; 1) | SCCB_READ);
    dat=sccb_read_byte();
    sccb_stop();
    return dat;
}

void write_reg(uint8_t reg, uint8_t dat)
{
    sccb_3_phase_write(SCCB_ADDR, reg, dat);
}

uint8_t read_reg(uint8_t reg)
{
    uint8_t dat = 0;
    sccb_2_phase_write(SCCB_ADDR, reg);
    dat = sccb_2_phase_read(SCCB_ADDR);

    return dat;
}


&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Thanks.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF54L15 SPIS21 slave receives correct RX amount but RX buffer is all zeros when capturing camera (BF3901/BF30A2) data</title><link>https://devzone.nordicsemi.com/thread/562778?ContentTypeID=1</link><pubDate>Mon, 09 Mar 2026 07:20:45 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:53ccecfc-4b19-4fec-b185-07dd477f1fd4</guid><dc:creator>Kazi Afroza Sultana</dc:creator><description>&lt;p&gt;Hello,&lt;/p&gt;
&lt;p&gt;Can you replace buffer with a small static buffer. If this helps to solve the issue, then probably the issue is in the memory region.&lt;/p&gt;
&lt;p&gt;I am sorry for the late reply. I have asked team to get accurate answers of your queries. In the meantime, can you please send me the application folder so I can look at the prj.conf and main.c file?&lt;/p&gt;
&lt;p&gt;Thanks.&lt;/p&gt;
&lt;p&gt;BR&lt;br /&gt;Kazi&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>