RT-Thread Studio configure QSPI et SFUD

1. Introduction

Cette fois, la carte série STM32F767 de Punctual Atom est utilisée, ce qui est différent du SPI sur F1 et F4, et QSPI est ajouté à F7. Le Flash embarqué de type W25Q256FV réalise également une communication en lecture et en écriture via QSPI. Il existe de nombreux exemples sur Internet concernant l'ouverture de RT-Thread SPI et l'utilisation de SFUD pour la lecture et l'écriture FLASH, mais la plupart d'entre eux sont basés sur ENV, car cette fois j'utilise le Studio nouvellement lancé de RT-Thread, et je configure les processus QSPI et SFUD La Chine a également marché sur de nombreux stands pour enregistrer le processus d'apprentissage et de configuration.


Documents de référence: Site Web original de SFUD Github
Centre de documentation RT-Thread
IOT-OS RT-Thread (9) -SPI Device Object Management and SFUD management framework
Notes d'étude Rtthread (9) RT-Thread Studio ouvre le bus SPI1, flash externe (W25Q64 ) SFUD en tant que périphérique esclave
| Une bibliothèque de pilotes universels Flash série

2 aperçu

2.1 SPI et QSPI

SPI (Serial Peripheral Interface, Serial Peripheral Interface) est un bus de communication synchrone haute vitesse, duplex intégral, souvent utilisé pour les communications à courte distance, utilisant généralement 4 fils pour la communication
Insérez la description de l'image ici

  • Sortie maître MOSI / ligne de données d'entrée esclave (sortie maître bus SPI / entrée esclave).
  • Ligne de données d'entrée MISO-maître / sortie esclave (entrée maître bus SPI / sortie esclave).
  • Ligne d'horloge série SCLK (Serial Clock), l'appareil maître émet le signal d'horloge vers l'appareil esclave.
  • Ligne de sélection CS-Slave (sélection de puce). Aussi appelé SS, CSB, CSN, EN, etc., le dispositif maître émet des signaux de sélection de puce vers le dispositif esclave

Le mode de fonctionnement spécifique est le suivant:
l'horloge du dispositif esclave est fournie par le dispositif maître via SCLK, et MOSI et MISO achèvent la transmission de données sur la base de cette impulsion. Le mode de séquence de travail du SPI est déterminé par la relation de phase entre CPOL (Clock Polarity) et CPHA (Clock Phase). CPOL détermine l'état de niveau de repos de l'horloge, CPOL = 0 signifie que l'état de repos est de niveau bas et CPOL = 1 signifie que l'état de repos est de niveau haut. CPHA signifie échantillonnage sur le premier front, CPHA = 0 signifie échantillonnage sur le premier front de changement d'horloge, correspondant à la ligne rouge dans la figure ci-dessous, CPHA = 1 signifie échantillonnage sur le deuxième front de changement d'horloge, correspondant à la figure ci-dessous La ligne bleue entre.
Insérez la description de l'image ici
QSPI est l'abréviation de Queued SPI, une extension de l'interface SPI lancée par Motorola, et est plus largement utilisée que SPI. Sur la base du protocole SPI, Motorola a amélioré ses fonctions, augmenté le mécanisme de transmission de la file d'attente et introduit le protocole d'interface périphérique série de file d'attente (c'est-à-dire le protocole QSPI). QSPI est une interface de communication dédiée qui connecte des supports de stockage Flash SPI simples, doubles ou quadruples (lignes de données).

L'interface peut fonctionner dans les trois modes suivants:

① Mode indirect: utilisez le registre QSPI pour effectuer toutes les opérations

② Mode d'interrogation d'état: lisez périodiquement le registre d'état Flash externe, et une interruption sera générée lorsque le bit indicateur est mis à 1, (comme l'effacement ou la programmation terminée, une interruption sera générée)

③ Mode de mappage de la mémoire: le Flash externe est mappé à l'espace d'adressage du microcontrôleur, de sorte que le système le considère comme une mémoire interne

Lorsque le mode double flash est adopté, deux flash Quad-SPI seront accessibles en même temps, et le débit et la capacité peuvent être doublés.

Il peut être simplement compris comme une version avancée de SPI.

2.2 SFUD

SFUD est une bibliothèque de pilotes universels SPI Flash open source. Comme il existe la plupart des types de Flash série sur le marché et que les spécifications et commandes de chaque Flash sont différentes, SFUD est conçu pour résoudre ces différences dans Flash, afin que nos produits puissent prendre en charge Flash de différentes marques et spécifications, et améliorer le Flash La réutilisabilité et l'extensibilité du logiciel fonctionnel peuvent également éviter le risque de rupture de stock de Flash ou d'arrêt du produit.

  • Principales caractéristiques: prise en charge de l'interface SPI / QSPI, orientée objet (prise en charge de plusieurs objets Flash en même temps), personnalisation flexible, forte évolutivité, prise en charge des adresses 4 octets
  • Occupation des ressources
    • Occupation standard: RAM: 0,2 Ko ROM: 5,5 Ko
    • Occupation minimale: RAM: 0,1 Ko ROM: 3,6 Ko

Adresse de la bibliothèque open source: https://github.com/armink/SFUD

2,3 W25Q256FV

Les extraits suivants sont sélectionnés dans le manuel de la bibliothèque Punctual Atom Hal
Insérez la description de l'image ici

3 processus de transplantation

Veuillez lire attentivement les documents d'aide fournis par le code source SFUD et le manuel officiel RT-Thread avant la transplantation.

3.1 Composants connexes ouverts

Tout d'abord, entrez dans le centre du progiciel sous Paramètres RT-Thread sous le dossier de projet sélectionné , comme indiqué dans la figure ci-dessous, sélectionnez et activez les deux fonctions de SPI et SFUD,
Insérez la description de l'image ici
puis sélectionnez plus de configurations dans le coin inférieur droit ou le symbole de la flèche gauche à l'extrême droite de la figure , Entrez dans l'interface, le processus de configuration est le suivant, une fois la configuration terminée, comme indiqué sur la figure,
composant → pilote de périphérique → utiliser le bus SPI / pilote de périphérique (vérifier)utiliser le mode QSPI (vérifier)utiliser le pilote universel Flash série ( SFUD) (cocher)cocher les trois premières options
Insérez la description de l'image ici
, enregistrer après ouverture pour mettre à jour, et quitter cette interface une fois la mise à jour terminée.

S'il est configuré par ENV, vous devez télécharger le programme source à partir de l'URL source et copier les fichiers à l'intérieur (les fichiers sources principaux incluent: sfud.c, sfud_sfdp.c, sfud_port.c), mais RT-Thread Studio complétera automatiquement la configuration pour vous , C'est aussi la puissance de cet éditeur, mais si vous n'êtes pas familier avec ce logiciel et la configuration du code source associé, vous vous sentirez assombri lors de votre premier démarrage. Une fois la configuration terminée, SFUD se trouve sous le chemin "rt-thread → components → drivers → spi". Principalement le dossier sfud et les fichiers spi_flash_sfud.c, spi_flash_sfud.h.
Insérez la description de l'image ici
Ignorons SFUD et configurons d'abord QSPI.

3.2 Configuration QSPI

Ouvrez le fichier board.h (sous le chemin des pilotes) et recherchez les informations de configuration QSPI comme suit:
Insérez la description de l'image ici
Tout d'abord, ajoutez le fichier board.h: #define BSP_USING_QSPI (configurez juste en dessous du texte dans la figure ci-dessus).

Ensuite, ouvrez CubeMx pour la configuration appropriée pour générer du code. Déterminez les broches qui doivent être activées comme suit:
Insérez la description de l'image ici
Notez que la série W25Q256 est une puce Flash série de 32 Mo, 32 M = 32 1024 1024 = 2 ^ 25, donc la configuration Flash Size doit être 25-1 = 24. La configuration est la suivante:
Insérez la description de l'image ici
Insérez la description de l'image ici
Selon la déclaration officielle, le programme généré doit être placé dans board.c, puis la fonction d'initialisation correspondante doit être placée dans le fichier principal. Mais cela rendra le programme un peu gonflé et compliqué et peu pratique à vérifier, nous ajoutons donc deux nouveaux dossiers inc et src sous le fichier d'application, créons un nouveau fichier d'en-tête qspi.h dans inc, et créons un nouveau fichier source qspi.c sous src pour stocker Le code correspondant. Dans le processus de programmation suivant, inc et src peuvent également être utilisés pour stocker d'autres fichiers d'en-tête et fichiers source (n'oubliez pas d'inclure ces deux chemins dans l'espace de travail pour trouver les fichiers correspondants et compiler correctement). Les procédures internes sont les suivantes:

/* qspi.h 文件内容*/
#ifndef APPLICATIONS_INC_QSPI_H_
#define APPLICATIONS_INC_QSPI_H_

#include <board.h>

void HAL_QSPI_MspInit(QSPI_HandleTypeDef* hqspi);
void MX_QUADSPI_Init(void);


#endif /* APPLICATIONS_INC_QSPI_H_ */
/* qspi.c 文件内容*/
#include "qspi.h"

QSPI_HandleTypeDef hqspi;

/**
* @brief QSPI MSP Initialization
* This function configures the hardware resources used in this example
* @param hqspi: QSPI handle pointer
* @retval None
*/
void HAL_QSPI_MspInit(QSPI_HandleTypeDef* hqspi)
{
    
    
  GPIO_InitTypeDef GPIO_InitStruct = {
    
    0};
  if(hqspi->Instance==QUADSPI)
  {
    
    
  /* USER CODE BEGIN QUADSPI_MspInit 0 */

  /* USER CODE END QUADSPI_MspInit 0 */
    /* Peripheral clock enable */
    __HAL_RCC_QSPI_CLK_ENABLE();

    __HAL_RCC_GPIOF_CLK_ENABLE();
    __HAL_RCC_GPIOB_CLK_ENABLE();
    /**QUADSPI GPIO Configuration
    PF6     ------> QUADSPI_BK1_IO3
    PF7     ------> QUADSPI_BK1_IO2
    PF8     ------> QUADSPI_BK1_IO0
    PF9     ------> QUADSPI_BK1_IO1
    PB2     ------> QUADSPI_CLK
    PB6     ------> QUADSPI_BK1_NCS
    */
    GPIO_InitStruct.Pin = GPIO_PIN_6|GPIO_PIN_7;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF9_QUADSPI;
    HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_8|GPIO_PIN_9;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF10_QUADSPI;
    HAL_GPIO_Init(GPIOF, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_2;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF9_QUADSPI;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_6;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLUP;
    GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF10_QUADSPI;
    HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /* USER CODE BEGIN QUADSPI_MspInit 1 */

  /* USER CODE END QUADSPI_MspInit 1 */
  }

}

/**
  * @brief QUADSPI Initialization Function
  * @param None
  * @retval None
  */
void MX_QUADSPI_Init(void)
{
    
    

  /* USER CODE BEGIN QUADSPI_Init 0 */

  /* USER CODE END QUADSPI_Init 0 */

  /* USER CODE BEGIN QUADSPI_Init 1 */

  /* USER CODE END QUADSPI_Init 1 */
  /* QUADSPI parameter configuration*/
  hqspi.Instance = QUADSPI;
  hqspi.Init.ClockPrescaler = 2;
  hqspi.Init.FifoThreshold = 4;
  hqspi.Init.SampleShifting = QSPI_SAMPLE_SHIFTING_HALFCYCLE;
  hqspi.Init.FlashSize = 24;
  hqspi.Init.ChipSelectHighTime = QSPI_CS_HIGH_TIME_4_CYCLE;
  hqspi.Init.ClockMode = QSPI_CLOCK_MODE_0;
  hqspi.Init.FlashID = QSPI_FLASH_ID_1;
  hqspi.Init.DualFlash = QSPI_DUALFLASH_DISABLE;
  if (HAL_QSPI_Init(&hqspi) != HAL_OK)
  {
    
    
    Error_Handler();
  }
  /* USER CODE BEGIN QUADSPI_Init 2 */

  /* USER CODE END QUADSPI_Init 2 */

}

En conséquence, comme il n'y a pas de définition de fonction dans le fichier board.c, nous devons déclarer la fonction appropriée dans board.h pour faire l'appel du programme entier normalement. La configuration est la suivante:
Insérez la description de l'image ici
À ce stade , le terminal est activé après que le programme est compilé et téléchargé dans le microcontrôleur. Et appelez la commande list_device pour voir que le bus qspi interne a été activé
Insérez la description de l'image ici

3.3 Configuration SFUD

Bien sûr, il ne suffit pas d'allumer le bus, il faut monter l'appareil sur le bus pour l'utiliser normalement.

Dans des circonstances normales, après les opérations ci-dessus, notre configuration interne dans le fichier rtconfig.h devrait être la suivante (parce que j'ai activé d'autres fonctions ici, donc cela peut être différent, mais à peu près trop de configuration QSPI et SFUD devrait être similaire de)

/* Device Drivers */

#define RT_USING_DEVICE_IPC
#define RT_PIPE_BUFSZ 512
#define RT_USING_SERIAL
#define RT_SERIAL_RB_BUFSZ 64
#define RT_USING_HWTIMER
#define RT_USING_PIN
#define RT_USING_PWM
#define RT_USING_SPI
#define RT_USING_QSPI
#define RT_USING_SFUD
#define RT_SFUD_USING_SFDP
#define RT_SFUD_USING_FLASH_INFO_TABLE
#define RT_SFUD_USING_QSPI
#define RT_SFUD_SPI_MAX_HZ 50000000

Permettez-moi d'en parler brièvement ici. S'il est transplanté dans le Studio, vous constaterez qu'il n'y a pas de fichier sfud_port.c. La fonction associée RT-Thread a été intégrée pour vous et implémentée dans spi_flash_sfud.c, donc aucune configuration n'est requise. Même les fonctions liées à l'initialisation de QSPI ont été implémentées pour vous sous le fichier drv_qspi.c.

En ce qui concerne le processus de mise en œuvre interne plus détaillé et le portage de SFUD, veuillez lire attentivement les documents officiels sur Github et de nombreux détails y sont décrits.

Notez que les informations relatives à la puce ont été définies dans sfud_flash_def.h, principalement comme suit:

#ifdef SFUD_USING_FLASH_INFO_TABLE
/* SFUD supported flash chip information table. If the flash not support JEDEC JESD216 standard,
 * then the SFUD will find the flash chip information by this table. You can add other flash to here then
 *  notice me for update it. The configuration information name and index reference the sfud_flash_chip structure.
 * | name | mf_id | type_id | capacity_id | capacity | write_mode | erase_gran | erase_gran_cmd |
 */
#define SFUD_FLASH_CHIP_TABLE                                                                                       \
{                                                                                                                   \
    {"AT45DB161E", SFUD_MF_ID_ATMEL, 0x26, 0x00, 2L*1024L*1024L, SFUD_WM_BYTE|SFUD_WM_DUAL_BUFFER, 512, 0x81},      \
    {"W25Q40BV", SFUD_MF_ID_WINBOND, 0x40, 0x13, 512L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20},                        \
    {"W25Q16BV", SFUD_MF_ID_WINBOND, 0x40, 0x15, 2L*1024L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20},                    \
    {"W25Q64DW", SFUD_MF_ID_WINBOND, 0x60, 0x17, 8L*1024L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20},                    \
    {"W25Q128BV", SFUD_MF_ID_WINBOND, 0x40, 0x18, 16L*1024L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20},                  \
    {"W25Q256FV", SFUD_MF_ID_WINBOND, 0x40, 0x19, 32L*1024L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20},                  \
    {"SST25VF016B", SFUD_MF_ID_SST, 0x25, 0x41, 2L*1024L*1024L, SFUD_WM_BYTE|SFUD_WM_AAI, 4096, 0x20},              \
    {"M25P32", SFUD_MF_ID_MICRON, 0x20, 0x16, 4L*1024L*1024L, SFUD_WM_PAGE_256B, 64L*1024L, 0xD8},                  \
    {"M25P80", SFUD_MF_ID_MICRON, 0x20, 0x14, 1L*1024L*1024L, SFUD_WM_PAGE_256B, 64L*1024L, 0xD8},                  \
    {"M25P40", SFUD_MF_ID_MICRON, 0x20, 0x13, 512L*1024L, SFUD_WM_PAGE_256B, 64L*1024L, 0xD8},                      \
    {"EN25Q32B", SFUD_MF_ID_EON, 0x30, 0x16, 4L*1024L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20},                        \
    {"GD25Q64B", SFUD_MF_ID_GIGADEVICE, 0x40, 0x17, 8L*1024L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20},                 \
    {"GD25Q16B", SFUD_MF_ID_GIGADEVICE, 0x40, 0x15, 2L*1024L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20},                 \
    {"S25FL216K", SFUD_MF_ID_CYPRESS, 0x40, 0x15, 2L*1024L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20},                   \
    {"S25FL032P", SFUD_MF_ID_CYPRESS, 0x02, 0x15, 4L*1024L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20},                   \
    {"A25L080", SFUD_MF_ID_AMIC, 0x30, 0x14, 1L*1024L*1024L, SFUD_WM_PAGE_256B, 4096, 0x20},                        \
    {"F25L004", SFUD_MF_ID_ESMT, 0x20, 0x13, 512L*1024L, SFUD_WM_BYTE|SFUD_WM_AAI, 4096, 0x20},                     \
    {"PCT25VF016B", SFUD_MF_ID_SST, 0x25, 0x41, 2L*1024L*1024L, SFUD_WM_BYTE|SFUD_WM_AAI, 4096, 0x20},              \
}
#endif /* SFUD_USING_FLASH_INFO_TABLE */

#ifdef SFUD_USING_QSPI
/* This table saves flash read-fast instructions in QSPI mode, 
 * SFUD can use this table to select the most appropriate read instruction for flash.
 * | mf_id | type_id | capacity_id | qspi_read_mode |
 */
#define SFUD_FLASH_EXT_INFO_TABLE                                                                  \
{                                                                                                  \
    /* W25Q40BV */                                                                                 \
    {
    
    SFUD_MF_ID_WINBOND, 0x40, 0x13, NORMAL_SPI_READ|DUAL_OUTPUT},                                 \
    /* W25Q80JV */                                                                                 \
    {
    
    SFUD_MF_ID_WINBOND, 0x40, 0x14, NORMAL_SPI_READ|DUAL_OUTPUT},                                 \
    /* W25Q16BV */                                                                                 \
    {
    
    SFUD_MF_ID_WINBOND, 0x40, 0x15, NORMAL_SPI_READ|DUAL_OUTPUT},                                 \
    /* W25Q32BV */                                                                                 \
    {
    
    SFUD_MF_ID_WINBOND, 0x40, 0x16, NORMAL_SPI_READ|DUAL_OUTPUT},                                 \
    /* W25Q64JV */                                                                                 \
    {
    
    SFUD_MF_ID_WINBOND, 0x40, 0x17, NORMAL_SPI_READ|DUAL_OUTPUT|DUAL_IO|QUAD_OUTPUT|QUAD_IO},     \
    /* W25Q128JV */                                                                                \
    {
    
    SFUD_MF_ID_WINBOND, 0x40, 0x18, NORMAL_SPI_READ|DUAL_OUTPUT|DUAL_IO|QUAD_OUTPUT|QUAD_IO},     \
    /* W25Q256FV */                                                                                \
    {
    
    SFUD_MF_ID_WINBOND, 0x40, 0x19, NORMAL_SPI_READ|DUAL_OUTPUT|DUAL_IO|QUAD_OUTPUT|QUAD_IO},     \
    /* EN25Q32B */                                                                                 \
    {
    
    SFUD_MF_ID_EON, 0x30, 0x16, NORMAL_SPI_READ|DUAL_OUTPUT|QUAD_IO},                             \
    /* S25FL216K */                                                                                \
    {
    
    SFUD_MF_ID_CYPRESS, 0x40, 0x15, NORMAL_SPI_READ|DUAL_OUTPUT},                                 \
    /* A25L080 */                                                                                  \
    {
    
    SFUD_MF_ID_AMIC, 0x30, 0x14, NORMAL_SPI_READ|DUAL_OUTPUT|DUAL_IO},                            \
    /* A25LQ64 */                                                                                  \
    {
    
    SFUD_MF_ID_AMIC, 0x40, 0x17, NORMAL_SPI_READ|DUAL_OUTPUT|DUAL_IO|QUAD_IO},                    \
    /* MX25L3206E and KH25L3206E */                                                                \
    {
    
    SFUD_MF_ID_MICRONIX, 0x20, 0x16, NORMAL_SPI_READ|DUAL_OUTPUT},                                \
    /* GD25Q64B */                                                                                 \
    {
    
    SFUD_MF_ID_GIGADEVICE, 0x40, 0x17, NORMAL_SPI_READ|DUAL_OUTPUT},                              \
}
#endif /* SFUD_USING_QSPI */

Regardez attentivement pour voir s'il y a une puce que vous utilisez à l'intérieur. En gros, la plupart des puces doivent être à l'intérieur.

Vous pouvez également configurer vous-même la table des appareils. Modifiez la définition de macro de SFUD_FLASH_DEVICE_TABLE dans sfud_cfg.h

enum {
    
    
    SFUD_W25Q256FV_DEVICE_INDEX = 0,
};

#define SFUD_FLASH_DEVICE_TABLE                                                 \
{                                                                               \
    [SFUD_W25Q256FV_DEVICE_INDEX] = {.name = "W25Q256FV", .spi.name = "qspi1"}  \
}

Ensuite, nous ajoutons le pilote de périphérique esclave. Dans inc et src sous le chemin de l'application, nous ajoutons respectivement les fichiers flash.h et flash.c. Les procédures internes sont les suivantes:

#include "board.h"
#include "drv_qspi.h"
#include "rtdevice.h"

#define QSPI_BUS_NAME       "qspi1"
#define QSPI_DEVICE_NAME    "qspi10"
#define W25Q_FLASH_NAME     "W25Q256FV"

#define QSPI_CS_PIN         GET_PIN(B, 6)	//此处注意引脚区分,用你自己的

static int rt_hw_qspi_flash_with_sfud_init(void)
{
    
    
    if (stm32_qspi_bus_attach_device(QSPI_BUS_NAME, QSPI_DEVICE_NAME, (rt_uint32_t)QSPI_CS_PIN, 4, RT_NULL, RT_NULL) != RT_EOK)
        return -RT_ERROR;

#ifdef  RT_USING_SFUD
    if (rt_sfud_flash_probe(W25Q_FLASH_NAME, QSPI_DEVICE_NAME) == RT_NULL)
        return -RT_ERROR;
#endif

    return RT_EOK;
}
INIT_COMPONENT_EXPORT(rt_hw_qspi_flash_with_sfud_init);

Après la compilation et le téléchargement, nous avons constaté que la puce 32M avait été lue avec succès. Nous avons tapé list_device dans msh et avons obtenu le résultat indiqué dans la figure ci-dessous (veuillez ignorer pwm1 et pwm8, qui sont mes autres pilotes).
Insérez la description de l'image ici
Utilisez la commande sf pour afficher le périphérique,
Insérez la description de l'image ici
puis le transplanter Succès! Pour des commandes plus détaillées, veuillez consulter le document officiel RT

Veuillez signaler toute erreur dans le temps

Je suppose que tu aimes

Origine blog.csdn.net/moumde/article/details/108002454
conseillé
Classement