4148 views|0 replies

118

Posts

1

Resources
The OP
 

RT-Thread device framework learning SPI device [Copy link]

RT-Thread learning record

1. New Studio Project

2. Brief description of console usage

3. PIN device framework learning

4.UART device framework learning

5.I2C device framework learning

SPI Devices

The SPI driver of RT-Thread currently only supports hardware SPI/QSPI mode.

First, check the SPI driver framework under the Components setting. The options here are QSPI mode, SPI SD card, SPI Flash, SPI Ethernet, and SPI WiFi. I have QSPI FLASH and SPI SD card on board, so I checked both. If the device is not one of the above options, you can skip it directly, as shown in the following figure

Then check the spi device routine under the Samples setting and save. As shown in the figure below, you can see that the spi routine has been added to the project

Open the example file, you can see that the function of this example is to grab the device ID of Flash through SPI. Because my board uses qspi Flash, the example cannot be used and needs to be re-implemented by myself.

First, we turn on the QSPI device driver support in board.h

Then add the pin initialization for QSPI in the board.c file or any other source file. Here I copied it after setting up the generated code under CubeMX, as shown in the figure below:

Imitate the SPI example added earlier and simply write a test routine

#include <rtthread.h>
#include <rtdevice.h>
#include "drv_qspi.h"

#define W25Q_SPI_DEVICE_NAME "qspi10"

char w25qxx_read_status_register2(struct rt_qspi_device *device)
{
  /* 0x35 read status register2 */
  char instruction = 0x35, status;

  rt_qspi_send_then_recv(device, &instruction, 1, &status, 1);

  return status;
}

void w25qxx_write_enable(struct rt_qspi_device *device)
{
  /* 0x06 write enable */
  char instruction = 0x06;

  rt_qspi_send(device, &instruction, 1);
}

void w25qxx_enter_qspi_mode(struct rt_qspi_device *device)
{
  char status = 0;
  /* 0x38 enter qspi mode */
  char instruction = 0x38;
  char write_status2_buf[2] = {0};

  /* 0x31 write status register2 */
  write_status2_buf[0] = 0x31;

  status = w25qxx_read_status_register2(device);
  if (!(status & 0x02))
   {
    status |= 1 << 1;
    w25qxx_write_enable(device);
    write_status2_buf[1] = status;
    rt_qspi_send(device, &write_status2_buf, 2);
    rt_qspi_send(device, &instruction, 1);
    rt_kprintf("flash already enter qspi mode\n");
    rt_thread_mdelay(10);
   }
}

//static void usr_spi_hw_config(struct rt_spi_device* device)
//{
// struct rt_spi_configuration cfg;
//
// cfg.data_width = 8;
// cfg.mode = RT_SPI_MASTER | RT_SPI_MODE_0 | RT_SPI_MSB;
// cfg.max_hz = 50 * 1000 *1000; /* 50M */
//
// rt_spi_configure(device, &cfg);
//}

static void usr_qspi_hw_config(struct rt_qspi_device* device)
{
  struct rt_qspi_configuration cfg;

  cfg.parent.data_width = 8;
  cfg.parent.mode = RT_SPI_MASTER | RT_SPI_MODE_0 | RT_SPI_MSB;
  cfg.parent.max_hz = 50 * 1000 *1000; /* 20M */

  cfg.medium_size = 0x1000000;
  cfg.ddr_mode = 0;
  cfg.qspi_dl_width = 4;
  rt_qspi_configure(device, &cfg);
}

static void qspi_w25q_sample(int argc, char *argv[])
{
  struct rt_qspi_device *spi_dev_w25q;
  char name[RT_NAME_MAX];
  rt_uint8_t w25x_read_id = 0x90;
  rt_uint8_t id[5] = {0};


  stm32_qspi_bus_attach_device("qspi1", "qspi10", RT_NULL, 4, w25qxx_enter_qspi_mode, RT_NULL);

  if (argc == 2)
   {
    rt_strncpy(name, argv[1], RT_NAME_MAX);
   }
  else
   {
    rt_strncpy(name, W25Q_SPI_DEVICE_NAME, RT_NAME_MAX);
   }

  /* Find the spi device and get the device handle*/
  spi_dev_w25q = (struct rt_qspi_device *)rt_device_find(name);
  if (!spi_dev_w25q)
   {
    rt_kprintf("spi sample run failed! can't find %s device!\n", name);
   }
  else
   {
    usr_qspi_hw_config(spi_dev_w25q);

    /* Method 1: Use rt_spi_send_then_recv() to send a command to read the ID */
    rt_qspi_send_then_recv(spi_dev_w25q, &w25x_read_id, 1, id, 5);
    rt_kprintf("use rt_qspi_send_then_recv() read w25q ID is:%x%x\n", id[3], id[4]);

    /* Method 2: Use rt_spi_transfer_message() to send a command to read the ID */
// struct rt_qspi_message msg1, msg2;
//
// msg1.send_buf = &w25x_read_id;
// msg1.recv_buf = RT_NULL;
// msg1.length = 1;
// msg1.cs_take = 1;
//msg1.cs_release = 0;
// msg1.next = &msg2;
//
// msg2.send_buf = RT_NULL;
// msg2.recv_buf = id;
// msg2.length = 5;
// msg2.cs_take = 0;
//msg2.cs_release = 1;
// msg2.next = RT_NULL;

// rt_qspi_transfer_message(spi_dev_w25q, &msg1);
// rt_kprintf("use rt_spi_transfer_message() read w25q ID is:%x%x\n", id[3], id[4]);

   }
}
/* Export to msh command list */
MSH_CMD_EXPORT(qspi_w25q_sample, qspi w25q sample);

Save, compile, and run. You can see that the device ID of the external FLASH has been read.

For SPI testing, you can refer to the sample program provided on the official website. I don’t have the corresponding peripherals to do the testing, so the SD card test will be left for the file system component testing later.

The above is the instruction for using the SPI driver framework.


This content is originally created by EEWORLD forum user ID.LODA. If you want to reprint or use it for commercial purposes, you must obtain the author's consent and indicate the source

This post is from Embedded System

Guess Your Favourite
Just looking around
Find a datasheet?

EEWorld Datasheet Technical Support

EEWorld
subscription
account

EEWorld
service
account

Automotive
development
circle

Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号
快速回复 返回顶部 Return list