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);
}
}