Hey,
I try to communicate with an E-Paper display (GDEY0579Z93) from my NRF5252832 DK. I used this thread (SPI example for nRF52833 with nRF Connect SDK 2.3.0) and this example (https://github.com/too1/ncs-spi-master-slave-example) as template.
The manufacturer provides an Arduino example, which runs perfectly fine. I have tried to port it into a NRF52 Zephyr project.
However, I can't get any visible feedback from the display. In fact, I get this strange build warning
../src/main.c:55:15: warning: initialization of 'const struct device *' from incompatible pointer type 'struct spi_cs_control *' [-Wincompatible-pointer-types] 55 | .cs = &spim_cs, | ^ ../src/main.c:55:15: note: (near initialization for 'spi_cfg.cs.gpio.port') ../src/main.c:50:42: warning: missing braces around initializer [-Wmissing-braces] 50 | static const struct spi_config spi_cfg = { | ^ ...... 55 | .cs = &spim_cs, | {{ 56 | }; | }}
The chip also reboots at:
This is my Overlay:
&pinctrl { spi_master_default: spi_master_default { group1 { psels = <NRF_PSEL(SPIM_SCK, 0, 26)>, <NRF_PSEL(SPIM_MOSI, 0, 27)>, <NRF_PSEL(SPIM_MISO, 0, 29)>; }; }; spi_master_sleep: spi_master_sleep { group1 { psels = <NRF_PSEL(SPIM_SCK, 0, 26)>, <NRF_PSEL(SPIM_MOSI, 0, 27)>, <NRF_PSEL(SPIM_MISO, 0, 29)>; low-power-enable; }; }; }; my_spi_master: &spi1 { compatible = "nordic,nrf-spi"; status = "okay"; pinctrl-0 = <&spi1_default>; pinctrl-1 = <&spi1_sleep>; cs-gpios = <&gpio0 02 GPIO_ACTIVE_LOW>; reg_my_spi_master: spi-dev-a@0 { reg = <0>; }; }; / { gpiocustom { compatible = "gpio-keys"; /* pinclk: pin_clk { gpios = <&gpio0 26 GPIO_ACTIVE_HIGH>; label = "CLOCK"; }; pinmosi: pin_mosi { gpios = <&gpio0 27 GPIO_ACTIVE_HIGH>; label = "MOSI"; }; pincs: pin_cs { gpios = <&gpio0 02 GPIO_ACTIVE_HIGH>; label = "CS"; }; */ pinbusy: pin_busy { gpios = <&gpio0 23 GPIO_ACTIVE_HIGH>; label = "BUSY"; }; pinreset: pin_reset { gpios = <&gpio0 24 GPIO_ACTIVE_HIGH>; label = "RESET"; }; pindc: pin_dc { gpios = <&gpio0 25 GPIO_ACTIVE_HIGH>; label = "D/C"; }; }; aliases { /* pinclk = &pinclk; pinmosi = &pinmosi; pincs = &pincs; */ pinbusy = &pinbusy; pinreset = &pinreset; pindc = &pindc; }; };
Code:
/* * Copyright (c) 2016 Intel Corporation * * SPDX-License-Identifier: Apache-2.0 */ #include <zephyr/kernel.h> #include <zephyr/drivers/uart.h> #include <zephyr/drivers/gpio.h> #include <zephyr/drivers/spi.h> #define EPD_WIDTH 272 #define EPD_HEIGHT 800 #define Source_BYTES 400/8 #define Gate_BITS 272 #define ALLSCREEN_BYTES Source_BYTES*Gate_BITS #define NUM_LINE_BYTES 8 // =64/8 #define NUM_COLUMN_BYTES 30 #define MY_SPI_MASTER DT_NODELABEL(my_spi_master) /* Custom Pins */ #define PIN_BUSY_NODE DT_ALIAS(pinbusy) #define PIN_RESET_NODE DT_ALIAS(pinreset) #define PIN_DC_NODE DT_ALIAS(pindc) #define PIN_CS_NODE DT_ALIAS(pincs) #define PIN_MOSI_NODE DT_ALIAS(pinmosi) #define PIN_CLK_NODE DT_ALIAS(pinclk) static const struct gpio_dt_spec pBusy = GPIO_DT_SPEC_GET(PIN_BUSY_NODE, gpios); static const struct gpio_dt_spec pReset = GPIO_DT_SPEC_GET(PIN_RESET_NODE, gpios); static const struct gpio_dt_spec pDc = GPIO_DT_SPEC_GET(PIN_DC_NODE, gpios); //static const struct gpio_dt_spec pMosi = GPIO_DT_SPEC_GET(PIN_MOSI_NODE, gpios); //static const struct gpio_dt_spec pClk = GPIO_DT_SPEC_GET(PIN_CLK_NODE, gpios); //static const struct gpio_dt_spec pCs = GPIO_DT_SPEC_GET(PIN_CS_NODE, gpios); // SPI master functionality const struct device *spi_dev; static struct k_poll_signal spi_done_sig = K_POLL_SIGNAL_INITIALIZER(spi_done_sig); struct spi_cs_control spim_cs = { .gpio = SPI_CS_GPIOS_DT_SPEC_GET(DT_NODELABEL(reg_my_spi_master)), .delay = 0, }; 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, .cs = &spim_cs, }; static uint8_t tx_buffer[2]; const struct spi_buf tx_buf = { .buf = tx_buffer, .len = sizeof(tx_buffer) }; const struct spi_buf_set tx = { .buffers = &tx_buf, .count = 1 }; void spi_write_cmd(uint8_t cmd) { tx_buffer[0] = cmd; //gpio_pin_set_dt(&spim_cs.gpio, 0); gpio_pin_set_dt(&pDc, 0); int error = spi_write(spi_dev, &spi_cfg, &tx); if(error != 0){ printk("SPI write error: %i\n", error); } //gpio_pin_set_dt(&spim_cs.gpio, 1); } void spi_write_data(uint8_t data) { tx_buffer[0] = data; //gpio_pin_set_dt(&spim_cs.gpio, 0); gpio_pin_set_dt(&pDc, 1); int error = spi_write(spi_dev, &spi_cfg, &tx); if(error != 0){ printk("SPI write error: %i\n", error); } //gpio_pin_set_dt(&spim_cs.gpio, 1); } void set_ramMP() { spi_write_cmd(0x11); spi_write_data(0x05); spi_write_cmd(0x44); spi_write_data(0x00); spi_write_data(0x31); spi_write_cmd(0x45); spi_write_data(0x0f); spi_write_data(0x01); spi_write_data(0x00); spi_write_data(0x00); } void set_ramMA() { spi_write_cmd(0x4E); spi_write_data(0x00); spi_write_cmd(0x4f); spi_write_data(0x0f); spi_write_data(0x01); } void set_ramSP(void) // Set RAM X - address Start / End position ; Set RAM Y - address Start / End position -SLAVE { spi_write_cmd(0x91); spi_write_data(0x04); spi_write_cmd(0xc4); // Set Ram X- address Start / End position spi_write_data(0x30); //392/8-1 // XStart, POR = 00h spi_write_data(0x00); spi_write_cmd(0xc5); // Set Ram Y- address Start / End position spi_write_data(0x0f); spi_write_data(0x01); spi_write_data(0x00); // YEnd L spi_write_data(0x00); // YEnd H } void set_ramSA(void) // Set RAM X address counter ; Set RAM Y address counter -SLAVE { spi_write_cmd(0xce); spi_write_data(0x31); spi_write_cmd(0xcf); spi_write_data(0x0f); spi_write_data(0x01); } void EPD_Update(void) { spi_write_cmd(0x22); //Display Update Control spi_write_data(0xF7); spi_write_cmd(0x20); //Activate Display Update Sequence while(1 == gpio_pin_get_dt(&pBusy)){}; } void EPD_DeepSleep(void) { spi_write_cmd(0x10); //enter deep sleep spi_write_data(0x01); k_msleep(100); } void EPD_HW_INIT(void) { printk("Display Init!\n"); gpio_pin_set_dt(&pReset, 0); k_msleep(100); gpio_pin_set_dt(&pReset, 1); k_msleep(100); while(1 == gpio_pin_get_dt(&pBusy)){}; spi_write_cmd(0x12); // SWRESET while(1 == gpio_pin_get_dt(&pBusy)){}; printk("Display Init DONE!\n"); } int main(void) { spi_dev = DEVICE_DT_GET(MY_SPI_MASTER); if(!device_is_ready(spi_dev)) { printk("SPI master device not ready!\n"); } if(!device_is_ready(spim_cs.gpio.port)){ printk("SPI master chip select device not ready!\n"); } if (!device_is_ready(pBusy.port) | !device_is_ready(pReset.port) | !device_is_ready(pDc.port)) { printk("Pins not ready!\n"); } // Configure GPIO pins int ret_busy = gpio_pin_configure_dt(&pBusy, GPIO_INPUT); int ret_reset = gpio_pin_configure_dt(&pReset, GPIO_OUTPUT); int ret_dc = gpio_pin_configure_dt(&pDc, GPIO_OUTPUT); //int ret_cs = gpio_pin_configure_dt(&pCs, GPIO_OUTPUT); //int ret_clk = gpio_pin_configure_dt(&pClk, GPIO_OUTPUT); //int ret_mosi = gpio_pin_configure_dt(&pMosi, GPIO_OUTPUT); if (ret_busy < 0 || ret_reset < 0 || ret_dc < 0) { printk("Error configuring GPIO pins: %d %d %d \n", ret_busy, ret_reset, ret_dc); return -1; } else { printk("Configuring GPIO pins OK: %d %d %d\n", ret_busy, ret_reset, ret_dc); } while (1) { //Init EPD_HW_INIT(); k_msleep(1000); //EPD_WhiteScreen_White printk("EPD_WhiteScreen_White!\n"); set_ramMP(); set_ramMA(); spi_write_cmd(0x24); for(uint32_t i = 0 ; i < Source_BYTES*Gate_BITS ; i++) { spi_write_data(0xff); } set_ramMA(); spi_write_cmd(0x26); for(uint32_t i = 0 ; i < Source_BYTES*Gate_BITS ; i++) { spi_write_data(0x00); } set_ramSP(); set_ramSA(); spi_write_cmd(0xA4); for(uint32_t i = 0 ; i < Source_BYTES*Gate_BITS ; i++) { spi_write_data(0xFF); } set_ramSA(); spi_write_cmd(0xA6); for(uint32_t i = 0 ; i < Source_BYTES*Gate_BITS ; i++) { spi_write_data(0x00); } EPD_Update(); EPD_DeepSleep(); printk("EPD_WhiteScreen_White DONE!\n"); k_msleep(5000); } }