I am having issue configuring the chip select (CS) in my little test program. I have read through the SPI drivers and debugged through it and from what I can tell I have everything setup right. I am also monitoring the CS signal on a scope to watch for it to go low (active low). Even after the SPI init/config routine runs I never see my CS pin go high.
What am I missing?
main.c :
/* * Copyright (c) 2016 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ #include <errno.h> #include <zephyr.h> #include <sys/printk.h> #include <device.h> #include <drivers/spi.h> /** * @file Sample app using the Cypress CY15B102QN (driver based on Fujitsu MB85RS64V) FRAM through SPI. */ #define CY15B102QN_MANUFACTURER_ID_CMD 0x9f #define CY15B102QN_WRITE_ENABLE_CMD 0x06 #define CY15B102QN_READ_CMD 0x03 #define CY15B102QN_WRITE_CMD 0x02 #define MAX_USER_DATA_LENGTH 1024 #define SPI_DEV DT_LABEL(DT_NODELABEL(spi1)) static uint8_t data[MAX_USER_DATA_LENGTH], cmp_data[MAX_USER_DATA_LENGTH]; static int cy15b102qn_access(const struct device *spi, struct spi_config *spi_cfg, uint8_t cmd, uint16_t addr, void *data, size_t len) { uint8_t access[3]; struct spi_buf bufs[] = { { .buf = access, }, { .buf = data, .len = len } }; struct spi_buf_set tx = { .buffers = bufs }; access[0] = cmd; if (cmd == CY15B102QN_WRITE_CMD || cmd == CY15B102QN_READ_CMD) { access[1] = (addr >> 8) & 0xFF; access[2] = addr & 0xFF; bufs[0].len = 3; tx.count = 2; if (cmd == CY15B102QN_READ_CMD) { struct spi_buf_set rx = { .buffers = bufs, .count = 2 }; return spi_transceive(spi, spi_cfg, &tx, &rx); } } else { tx.count = 1; } return spi_write(spi, spi_cfg, &tx); } static int cy15b102qn_read_id(const struct device *spi, struct spi_config *spi_cfg) { uint8_t id[4]; int err; err = cy15b102qn_access(spi, spi_cfg, CY15B102QN_MANUFACTURER_ID_CMD, 0, &id, 4); if (err) { printk("Error during ID read\n"); return -EIO; } /* if (id[0] != 0x04) { return -EIO; } if (id[1] != 0x7f) { return -EIO; } if (id[2] != 0x03) { return -EIO; } if (id[3] != 0x02) { return -EIO; } */ return 0; } static int write_bytes(const struct device *spi, struct spi_config *spi_cfg, uint16_t addr, uint8_t *data, uint32_t num_bytes) { int err; /* disable write protect */ err = cy15b102qn_access(spi, spi_cfg, CY15B102QN_WRITE_ENABLE_CMD, 0, NULL, 0); if (err) { printk("unable to disable write protect\n"); return -EIO; } /* write cmd */ err = cy15b102qn_access(spi, spi_cfg, CY15B102QN_WRITE_CMD, addr, data, num_bytes); if (err) { printk("Error during SPI write\n"); return -EIO; } return 0; } static int read_bytes(const struct device *spi, struct spi_config *spi_cfg, uint16_t addr, uint8_t *data, uint32_t num_bytes) { int err; /* read cmd */ err = cy15b102qn_access(spi, spi_cfg, CY15B102QN_READ_CMD, addr, data, num_bytes); if (err) { printk("Error during SPI read\n"); return -EIO; } return 0; } void main(void) { const struct device *spi; struct spi_config spi_cfg = {0}; printk("fujitsu FRAM example application\n"); spi = device_get_binding(SPI_DEV); if (!spi) { printk("Could not find SPI driver\n"); return; } int err; //Setup chip select struct / config struct spi_cs_control cs_cfg = { .gpio_dev = spi, .delay = 10, .gpio_pin = 20, .gpio_dt_flags = GPIO_ACTIVE_LOW, }; spi_cfg.cs = &cs_cfg; spi_cfg.operation = SPI_WORD_SET(8); //Sets frequency! spi_cfg.frequency = 256000U; err = cy15b102qn_read_id(spi, &spi_cfg); if (err) { printk("Could not verify FRAM ID\n"); return; } /* Do one-byte read/write */ data[0] = 0xAE; err = write_bytes(spi, &spi_cfg, 0x00, data, 1); if (err) { printk("Error writing to FRAM! errro code (%d)\n", err); return; } else { printk("Wrote 0xAE to address 0x00.\n"); } data[0] = 0x86; err = write_bytes(spi, &spi_cfg, 0x01, data, 1); if (err) { printk("Error writing to FRAM! error code (%d)\n", err); return; } else { printk("Wrote 0x86 to address 0x01.\n"); } data[0] = 0x00; err = read_bytes(spi, &spi_cfg, 0x00, data, 1); if (err) { printk("Error reading from FRAM! error code (%d)\n", err); return; } else { printk("Read 0x%X from address 0x00.\n", data[0]); } data[0] = 0x00; err = read_bytes(spi, &spi_cfg, 0x01, data, 1); if (err) { printk("Error reading from FRAM! error code (%d)\n", err); return; } else { printk("Read 0x%X from address 0x01.\n", data[0]); } /* Do multi-byte read/write */ /* get some random data, and clear out data[] */ for (uint32_t i = 0; i < sizeof(cmp_data); i++) { cmp_data[i] = k_cycle_get_32() & 0xFF; data[i] = 0x00; } /* write them to the FRAM */ err = write_bytes(spi, &spi_cfg, 0x00, cmp_data, sizeof(cmp_data)); if (err) { printk("Error writing to FRAM! error code (%d)\n", err); return; } else { printk("Wrote %d bytes to address 0x00.\n", (uint32_t) sizeof(cmp_data)); } err = read_bytes(spi, &spi_cfg, 0x00, data, sizeof(data)); if (err) { printk("Error reading from FRAM! error code (%d)\n", err); return; } else { printk("Read %d bytes from address 0x00.\n", (uint32_t) sizeof(data)); } err = 0; for (uint32_t i = 0; i < sizeof(cmp_data); i++) { if (cmp_data[i] != data[i]) { printk("Data comparison failed @ %d.\n", i); err = -EIO; } } if (err == 0) { printk("Data comparison successful.\n"); } }
nrf52833dk_nrf52833.overlay :
&spi1 { compatible = "nordic,nrf-spim"; status = "okay"; mosi-pin = <23>; miso-pin = <22>; sck-pin = <21>; clock-frequency = <4000000>; //cs-gpios = <&gpio0 20 GPIO_ACTIVE_LOW>; spi-device@0 { reg = <0>; label = "CY15B102QN"; //cs-gpios = <&gpio0 20 GPIO_ACTIVE_LOW>; }; //spi-max-frequency = <4000000>; }; &spi2 { status = "disabled"; }; &i2c1 { status = "disabled"; };
prj.conf :
CONFIG_STDOUT_CONSOLE=y CONFIG_PRINTK=y CONFIG_SPI=y #CONFIG_SPI_1=y #CONFIG_SPI_NRFX=y CONFIG_GPIO=y CONFIG_MAIN_STACK_SIZE=4096
zephyr.dts :
/dts-v1/; / { #address-cells = < 0x1 >; #size-cells = < 0x1 >; model = "Nordic nRF52833 DK NRF52833"; compatible = "nordic,nrf52833-dk-nrf52833"; chosen { zephyr,entropy = &rng; zephyr,flash-controller = &flash_controller; zephyr,console = &uart0; zephyr,shell-uart = &uart0; zephyr,uart-mcumgr = &uart0; zephyr,bt-mon-uart = &uart0; zephyr,bt-c2h-uart = &uart0; zephyr,sram = &sram0; zephyr,flash = &flash0; zephyr,code-partition = &slot0_partition; }; aliases { led0 = &led0; led1 = &led1; led2 = &led2; led3 = &led3; pwm-led0 = &pwm_led0; sw0 = &button0; sw1 = &button1; sw2 = &button2; sw3 = &button3; }; soc { #address-cells = < 0x1 >; #size-cells = < 0x1 >; compatible = "nordic,nRF52833-QIAA", "nordic,nRF52833", "nordic,nRF52", "simple-bus"; interrupt-parent = < &nvic >; ranges; nvic: interrupt-controller@e000e100 { compatible = "arm,v7m-nvic"; reg = < 0xe000e100 0xc00 >; interrupt-controller; #interrupt-cells = < 0x2 >; arm,num-irq-priority-bits = < 0x3 >; phandle = < 0x1 >; }; systick: timer@e000e010 { compatible = "arm,armv7m-systick"; reg = < 0xe000e010 0x10 >; status = "disabled"; }; flash_controller: flash-controller@4001e000 { compatible = "nordic,nrf52-flash-controller"; reg = < 0x4001e000 0x1000 >; #address-cells = < 0x1 >; #size-cells = < 0x1 >; label = "NRF_FLASH_DRV_NAME"; flash0: flash@0 { compatible = "soc-nv-flash"; label = "NRF_FLASH"; erase-block-size = < 0x1000 >; write-block-size = < 0x4 >; reg = < 0x0 0x80000 >; partitions { compatible = "fixed-partitions"; #address-cells = < 0x1 >; #size-cells = < 0x1 >; boot_partition: partition@0 { label = "mcuboot"; reg = < 0x0 0xc000 >; }; slot0_partition: partition@c000 { label = "image-0"; reg = < 0xc000 0x32000 >; }; slot1_partition: partition@3e000 { label = "image-1"; reg = < 0x3e000 0x32000 >; }; scratch_partition: partition@70000 { label = "image-scratch"; reg = < 0x70000 0xa000 >; }; storage_partition: partition@7a000 { label = "storage"; reg = < 0x7a000 0x6000 >; }; }; }; }; sram0: memory@20000000 { compatible = "mmio-sram"; reg = < 0x20000000 0x20000 >; }; adc: adc@40007000 { compatible = "nordic,nrf-saadc"; reg = < 0x40007000 0x1000 >; interrupts = < 0x7 0x1 >; status = "okay"; label = "ADC_0"; #io-channel-cells = < 0x1 >; }; clock: clock@40000000 { compatible = "nordic,nrf-clock"; reg = < 0x40000000 0x1000 >; interrupts = < 0x0 0x1 >; status = "okay"; label = "CLOCK"; }; ecb: ecb@4000e000 { compatible = "nordic,nrf-ecb"; reg = < 0x4000e000 0x1000 >; interrupts = < 0xe 0x1 >; status = "okay"; label = "ECB"; }; uart0: uart@40002000 { reg = < 0x40002000 0x1000 >; interrupts = < 0x2 0x1 >; status = "okay"; label = "UART_0"; compatible = "nordic,nrf-uarte"; current-speed = < 0x1c200 >; tx-pin = < 0x6 >; rx-pin = < 0x8 >; rts-pin = < 0x5 >; cts-pin = < 0x7 >; }; uart1: arduino_serial: uart@40028000 { compatible = "nordic,nrf-uarte"; reg = < 0x40028000 0x1000 >; interrupts = < 0x28 0x1 >; status = "okay"; label = "UART_1"; current-speed = < 0x1c200 >; rx-pin = < 0x21 >; tx-pin = < 0x22 >; }; gpiote: gpiote@40006000 { compatible = "nordic,nrf-gpiote"; reg = < 0x40006000 0x1000 >; interrupts = < 0x6 0x5 >; status = "okay"; label = "GPIOTE_0"; }; gpio0: gpio@50000000 { compatible = "nordic,nrf-gpio"; gpio-controller; reg = < 0x50000000 0x200 0x50000500 0x300 >; #gpio-cells = < 0x2 >; label = "GPIO_0"; status = "okay"; port = < 0x0 >; phandle = < 0x4 >; }; gpio1: gpio@50000300 { compatible = "nordic,nrf-gpio"; gpio-controller; reg = < 0x50000300 0x200 0x50000800 0x300 >; #gpio-cells = < 0x2 >; ngpios = < 0xa >; label = "GPIO_1"; status = "okay"; port = < 0x1 >; phandle = < 0x6 >; }; i2c0: arduino_i2c: i2c@40003000 { #address-cells = < 0x1 >; #size-cells = < 0x0 >; reg = < 0x40003000 0x1000 >; clock-frequency = < 0x186a0 >; interrupts = < 0x3 0x1 >; status = "okay"; label = "I2C_0"; compatible = "nordic,nrf-twi"; sda-pin = < 0x1a >; scl-pin = < 0x1b >; }; i2c1: i2c@40004000 { #address-cells = < 0x1 >; #size-cells = < 0x0 >; reg = < 0x40004000 0x1000 >; clock-frequency = < 0x186a0 >; interrupts = < 0x4 0x1 >; status = "disabled"; label = "I2C_1"; compatible = "nordic,nrf-twi"; sda-pin = < 0x1e >; scl-pin = < 0x1f >; }; pwm0: pwm@4001c000 { compatible = "nordic,nrf-pwm"; reg = < 0x4001c000 0x1000 >; interrupts = < 0x1c 0x1 >; status = "okay"; label = "PWM_0"; #pwm-cells = < 0x1 >; ch0-pin = < 0xd >; ch0-inverted; phandle = < 0x5 >; }; pwm1: pwm@40021000 { compatible = "nordic,nrf-pwm"; reg = < 0x40021000 0x1000 >; interrupts = < 0x21 0x1 >; status = "disabled"; label = "PWM_1"; #pwm-cells = < 0x1 >; }; pwm2: pwm@40022000 { compatible = "nordic,nrf-pwm"; reg = < 0x40022000 0x1000 >; interrupts = < 0x22 0x1 >; status = "disabled"; label = "PWM_2"; #pwm-cells = < 0x1 >; }; pwm3: pwm@4002d000 { compatible = "nordic,nrf-pwm"; reg = < 0x4002d000 0x1000 >; interrupts = < 0x2d 0x1 >; status = "disabled"; label = "PWM_3"; #pwm-cells = < 0x1 >; }; qdec: qdec@40012000 { compatible = "nordic,nrf-qdec"; reg = < 0x40012000 0x1000 >; interrupts = < 0x12 0x1 >; status = "disabled"; label = "QDEC"; }; rng: random@4000d000 { compatible = "nordic,nrf-rng"; reg = < 0x4000d000 0x1000 >; interrupts = < 0xd 0x1 >; status = "okay"; label = "RNG"; }; spi0: spi@40003000 { #address-cells = < 0x1 >; #size-cells = < 0x0 >; reg = < 0x40003000 0x1000 >; interrupts = < 0x3 0x1 >; status = "disabled"; label = "SPI_0"; compatible = "nordic,nrf-spi"; sck-pin = < 0x1b >; mosi-pin = < 0x1a >; miso-pin = < 0x1d >; }; spi1: spi@40004000 { #address-cells = < 0x1 >; #size-cells = < 0x0 >; reg = < 0x40004000 0x1000 >; interrupts = < 0x4 0x1 >; status = "okay"; label = "SPI_1"; compatible = "nordic,nrf-spim"; sck-pin = < 0x15 >; mosi-pin = < 0x17 >; miso-pin = < 0x16 >; clock-frequency = < 0x3d0900 >; spi-device@0 { reg = < 0x0 >; label = "CY15B102QN"; }; }; spi2: spi@40023000 { #address-cells = < 0x1 >; #size-cells = < 0x0 >; reg = < 0x40023000 0x1000 >; interrupts = < 0x23 0x1 >; status = "disabled"; label = "SPI_2"; }; spi3: arduino_spi: spi@4002f000 { compatible = "nordic,nrf-spim"; #address-cells = < 0x1 >; #size-cells = < 0x0 >; reg = < 0x4002f000 0x1000 >; interrupts = < 0x2f 0x1 >; status = "okay"; label = "SPI_3"; sck-pin = < 0x17 >; miso-pin = < 0x16 >; mosi-pin = < 0x15 >; cs-gpios = < &arduino_header 0x10 0x1 >; }; rtc0: rtc@4000b000 { compatible = "nordic,nrf-rtc"; reg = < 0x4000b000 0x1000 >; cc-num = < 0x3 >; interrupts = < 0xb 0x1 >; status = "okay"; clock-frequency = < 0x8000 >; prescaler = < 0x1 >; label = "RTC_0"; }; rtc1: rtc@40011000 { compatible = "nordic,nrf-rtc"; reg = < 0x40011000 0x1000 >; cc-num = < 0x4 >; interrupts = < 0x11 0x1 >; status = "okay"; clock-frequency = < 0x8000 >; prescaler = < 0x1 >; label = "RTC_1"; }; rtc2: rtc@40024000 { compatible = "nordic,nrf-rtc"; reg = < 0x40024000 0x1000 >; cc-num = < 0x4 >; interrupts = < 0x24 0x1 >; status = "okay"; clock-frequency = < 0x8000 >; prescaler = < 0x1 >; label = "RTC_2"; }; timer0: timer@40008000 { compatible = "nordic,nrf-timer"; status = "okay"; reg = < 0x40008000 0x1000 >; cc-num = < 0x4 >; interrupts = < 0x8 0x1 >; prescaler = < 0x0 >; label = "TIMER_0"; }; timer1: timer@40009000 { compatible = "nordic,nrf-timer"; status = "okay"; reg = < 0x40009000 0x1000 >; cc-num = < 0x4 >; interrupts = < 0x9 0x1 >; prescaler = < 0x0 >; label = "TIMER_1"; }; timer2: timer@4000a000 { compatible = "nordic,nrf-timer"; status = "okay"; reg = < 0x4000a000 0x1000 >; cc-num = < 0x4 >; interrupts = < 0xa 0x1 >; prescaler = < 0x0 >; label = "TIMER_2"; phandle = < 0x3 >; }; timer3: timer@4001a000 { compatible = "nordic,nrf-timer"; status = "okay"; reg = < 0x4001a000 0x1000 >; cc-num = < 0x6 >; interrupts = < 0x1a 0x1 >; prescaler = < 0x0 >; label = "TIMER_3"; }; timer4: timer@4001b000 { compatible = "nordic,nrf-timer"; status = "okay"; reg = < 0x4001b000 0x1000 >; cc-num = < 0x6 >; interrupts = < 0x1b 0x1 >; prescaler = < 0x0 >; label = "TIMER_4"; }; temp: temp@4000c000 { compatible = "nordic,nrf-temp"; reg = < 0x4000c000 0x1000 >; interrupts = < 0xc 0x1 >; status = "okay"; label = "TEMP_0"; }; usbd: usbd@40027000 { compatible = "nordic,nrf-usbd"; reg = < 0x40027000 0x1000 >; interrupts = < 0x27 0x1 >; num-bidir-endpoints = < 0x1 >; num-in-endpoints = < 0x7 >; num-out-endpoints = < 0x7 >; num-isoin-endpoints = < 0x1 >; num-isoout-endpoints = < 0x1 >; status = "okay"; label = "USBD"; }; wdt: wdt0: watchdog@40010000 { compatible = "nordic,nrf-watchdog"; reg = < 0x40010000 0x1000 >; interrupts = < 0x10 0x1 >; status = "okay"; label = "WDT"; }; ficr: ficr@10000000 { compatible = "nordic,nrf-ficr"; reg = < 0x10000000 0x1000 >; status = "okay"; }; uicr: uicr@10001000 { compatible = "nordic,nrf-uicr"; reg = < 0x10001000 0x1000 >; status = "okay"; }; radio: radio@40001000 { compatible = "nordic,nrf-radio"; reg = < 0x40001000 0x1000 >; interrupts = < 0x1 0x1 >; status = "okay"; dfe-ant-num = < 0x0 >; }; }; cpus { #address-cells = < 0x1 >; #size-cells = < 0x0 >; cpu@0 { device_type = "cpu"; compatible = "arm,cortex-m4f"; reg = < 0x0 >; }; }; sw_pwm: sw-pwm { compatible = "nordic,nrf-sw-pwm"; status = "disabled"; label = "SW_PWM"; generator = < &timer2 >; channel-count = < 0x3 >; clock-prescaler = < 0x0 >; ppi-base = < 0x0 >; gpiote-base = < 0x0 >; #pwm-cells = < 0x1 >; }; leds { compatible = "gpio-leds"; led0: led_0 { gpios = < &gpio0 0xd 0x1 >; label = "Green LED 0"; }; led1: led_1 { gpios = < &gpio0 0xe 0x1 >; label = "Green LED 1"; }; led2: led_2 { gpios = < &gpio0 0xf 0x1 >; label = "Green LED 2"; }; led3: led_3 { gpios = < &gpio0 0x10 0x1 >; label = "Green LED 3"; }; }; pwmleds { compatible = "pwm-leds"; pwm_led0: pwm_led_0 { pwms = < &pwm0 0xd >; }; }; buttons { compatible = "gpio-keys"; button0: button_0 { gpios = < &gpio0 0xb 0x11 >; label = "Push button switch 0"; }; button1: button_1 { gpios = < &gpio0 0xc 0x11 >; label = "Push button switch 1"; }; button2: button_2 { gpios = < &gpio0 0x18 0x11 >; label = "Push button switch 2"; }; button3: button_3 { gpios = < &gpio0 0x19 0x11 >; label = "Push button switch 3"; }; }; arduino_header: connector { compatible = "arduino-header-r3"; #gpio-cells = < 0x2 >; gpio-map-mask = < 0xffffffff 0xffffffc0 >; gpio-map-pass-thru = < 0x0 0x3f >; gpio-map = < 0x0 0x0 &gpio0 0x3 0x0 >, < 0x1 0x0 &gpio0 0x4 0x0 >, < 0x2 0x0 &gpio0 0x1c 0x0 >, < 0x3 0x0 &gpio0 0x1d 0x0 >, < 0x4 0x0 &gpio0 0x1e 0x0 >, < 0x5 0x0 &gpio0 0x1f 0x0 >, < 0x6 0x0 &gpio1 0x1 0x0 >, < 0x7 0x0 &gpio1 0x2 0x0 >, < 0x8 0x0 &gpio1 0x3 0x0 >, < 0x9 0x0 &gpio1 0x4 0x0 >, < 0xa 0x0 &gpio1 0x5 0x0 >, < 0xb 0x0 &gpio1 0x6 0x0 >, < 0xc 0x0 &gpio1 0x7 0x0 >, < 0xd 0x0 &gpio1 0x8 0x0 >, < 0xe 0x0 &gpio0 0x11 0x0 >, < 0xf 0x0 &gpio0 0x13 0x0 >, < 0x10 0x0 &gpio0 0x14 0x0 >, < 0x11 0x0 &gpio0 0x15 0x0 >, < 0x12 0x0 &gpio0 0x16 0x0 >, < 0x13 0x0 &gpio0 0x17 0x0 >, < 0x14 0x0 &gpio0 0x1a 0x0 >, < 0x15 0x0 &gpio0 0x1b 0x0 >; phandle = < 0x2 >; }; };
CMakeLists.txt :
# SPDX-License-Identifier: Apache-2.0 set(TEST_DTC_OVERLAY_FILE ${CMAKE_CURRENT_SOURCE_DIR}/nrf52833dk_nrf52833.overlay ) set(PRJ_CONF_FILE prj.conf ${CMAKE_CURRENT_LIST_DIR}/prj.conf ) cmake_minimum_required(VERSION 3.13.1) find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE}) project(spi_fujitsu_fram) FILE(GLOB app_sources src/*.c) target_sources(app PRIVATE ${app_sources})
SDK: nRF Connect SDK v1.5.1