This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Using 16MHz SPIM on nRF5340-PDK

I have SPIM working at 8MHz on nRF5340-PDK

I want to increase the SPIM speed to 16MHz.

The errata for nRF5340 states "In 128 MHz mode, SPIM max receive frequency is 16 Mbps. In 64 MHz mode, SPIM max receive frequency is 8 Mbps."

So I need to increase the core frequency from 64MHz to 128MHz and increase the SPIM clock frequency from 8MHz to 16MHz.

To change the core frequency to 128MHz do I just manually write HFCLKCTRL sometime during initialization, or is there some kind of zephyr/project setting that controls this?

I tried putting these lines at the beginning of main()

*((volatile uint32_t *)0x50039530ul) = 0xBEEF0044ul;
NRF_CLOCK_S->HFCLKCTRL = CLOCK_HFCLKCTRL_HCLK_Div1 << CLOCK_HFCLKCTRL_HCLK_Pos;

On a secure build, it doesn't seem to cause a problem

On a non-secure build, this causes some kind of repeating reset.  Can you tell me why?

It looks like zephyr/drivers/spi/spi_nrfx_spim.c does not let me set the SPI frequency to 16MHz for the nRF5340.

static inline nrf_spim_frequency_t get_nrf_spim_frequency(u32_t frequency)
{
	/* Get the highest supported frequency not exceeding the requested one.
	 */
	if (frequency < 250000) {
		return NRF_SPIM_FREQ_125K;
	} else if (frequency < 500000) {
		return NRF_SPIM_FREQ_250K;
	} else if (frequency < 1000000) {
		return NRF_SPIM_FREQ_500K;
	} else if (frequency < 2000000) {
		return NRF_SPIM_FREQ_1M;
	} else if (frequency < 4000000) {
		return NRF_SPIM_FREQ_2M;
	} else if (frequency < 8000000) {
		return NRF_SPIM_FREQ_4M;
#if defined(CONFIG_SOC_NRF52833) || defined(CONFIG_SOC_NRF52840)
	} else if (frequency < 16000000) {
		return NRF_SPIM_FREQ_8M;
	} else if (frequency < 32000000) {
		return NRF_SPIM_FREQ_16M;
	} else {
		return NRF_SPIM_FREQ_32M;
#else
	} else {
		return NRF_SPIM_FREQ_8M;
#endif
	}
}

I tried bypassing the "#if defined" part like this

static inline nrf_spim_frequency_t get_nrf_spim_frequency(u32_t frequency)
{
	/* Get the highest supported frequency not exceeding the requested one.
	 */
	if (frequency < 250000) {
		return NRF_SPIM_FREQ_125K;
	} else if (frequency < 500000) {
		return NRF_SPIM_FREQ_250K;
	} else if (frequency < 1000000) {
		return NRF_SPIM_FREQ_500K;
	} else if (frequency < 2000000) {
		return NRF_SPIM_FREQ_1M;
	} else if (frequency < 4000000) {
		return NRF_SPIM_FREQ_2M;
	} else if (frequency < 8000000) {
		return NRF_SPIM_FREQ_4M;
	} else if (frequency < 16000000) {
		return NRF_SPIM_FREQ_8M;
	} else if (frequency < 32000000) {
		return NRF_SPIM_FREQ_16M;
#if defined(CONFIG_SOC_NRF52833) || defined(CONFIG_SOC_NRF52840) || defined(CONFIG_SOC_NRF5340)
	} else {
		return NRF_SPIM_FREQ_32M;
#else
	} else {
		return NRF_SPIM_FREQ_8M;
#endif
	}
}

And in my overlay file I set spi-max-frequency = <16000000>;

But this results in an SPIM clock frequency of 634kHz, for both secure and non-secure builds.

What am I missing?

Parents Reply
  • Thanks Sigurd.

    Both these hints were helpful.

    Is there a sample program that uses nrfx_clock_divider_set()?  When I tried to use it I got some build errors so I ended up using the NRF_CLOCK_NS->HFCLKCTRL code directly.

    I switched to SPIM4 and the dedicated SPIM4 pins and was able to get it to work.  It looked like I might need to setup the SPI pins to use high drive instead of standard drive for 16MHz operation.

    I noticed that the datasheet mentions there is an extra high drive option as well, but when I tried to set the PIN_CNF[] register to use extra high drive it didn't work (at least in SES).  Are there only some pins that allow extra high drive?

    (I tried to set PIN_CNF[8] to 0x00000B01)

Children
Related